mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2025-01-20 18:17:20 +00:00
Merge branch 'project-next'
This commit is contained in:
commit
0be6fb8e17
@ -849,7 +849,7 @@ to avoid corrupting the original LIST1 and LIST2.
|
||||
(memq (car cl-list1) cl-list2))
|
||||
(push (car cl-list1) cl-res))
|
||||
(pop cl-list1))
|
||||
cl-res))))
|
||||
(nreverse cl-res)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun cl-nset-difference (cl-list1 cl-list2 &rest cl-keys)
|
||||
|
@ -230,7 +230,7 @@ Blank lines separate paragraphs. Semicolons start comments.
|
||||
:group 'lisp
|
||||
(defvar xref-find-function)
|
||||
(defvar xref-identifier-completion-table-function)
|
||||
(defvar project-search-path-function)
|
||||
(defvar project-library-roots-function)
|
||||
(lisp-mode-variables nil nil 'elisp)
|
||||
(add-hook 'after-load-functions #'elisp--font-lock-flush-elisp-buffers)
|
||||
(setq-local electric-pair-text-pairs
|
||||
@ -242,7 +242,7 @@ Blank lines separate paragraphs. Semicolons start comments.
|
||||
(setq-local xref-find-function #'elisp-xref-find)
|
||||
(setq-local xref-identifier-completion-table-function
|
||||
#'elisp--xref-identifier-completion-table)
|
||||
(setq-local project-search-path-function #'elisp-search-path)
|
||||
(setq-local project-library-roots-function #'elisp-library-roots)
|
||||
(add-hook 'completion-at-point-functions
|
||||
#'elisp-completion-at-point nil 'local))
|
||||
|
||||
@ -801,7 +801,7 @@ non-nil result supercedes the xrefs produced by
|
||||
|
||||
xrefs))
|
||||
|
||||
(declare-function project-search-path "project")
|
||||
(declare-function project-library-roots "project")
|
||||
(declare-function project-current "project")
|
||||
|
||||
(defun elisp--xref-find-references (symbol)
|
||||
@ -809,7 +809,10 @@ non-nil result supercedes the xrefs produced by
|
||||
(cl-mapcan
|
||||
(lambda (dir)
|
||||
(xref-collect-references symbol dir))
|
||||
(project-search-path (project-current))))
|
||||
(let ((pr (project-current t)))
|
||||
(append
|
||||
(project-roots pr)
|
||||
(project-library-roots pr)))))
|
||||
|
||||
(defun elisp--xref-find-apropos (regexp)
|
||||
(apply #'nconc
|
||||
@ -846,7 +849,7 @@ non-nil result supercedes the xrefs produced by
|
||||
(cl-defmethod xref-location-group ((l xref-elisp-location))
|
||||
(xref-elisp-location-file l))
|
||||
|
||||
(defun elisp-search-path ()
|
||||
(defun elisp-library-roots ()
|
||||
(defvar package-user-dir)
|
||||
(cons package-user-dir load-path))
|
||||
|
||||
|
@ -2098,7 +2098,10 @@ for \\[find-tag] (which see)."
|
||||
(cl-mapcan
|
||||
(lambda (dir)
|
||||
(xref-collect-references symbol dir))
|
||||
(project-search-path (project-current))))
|
||||
(let ((pr (project-current t)))
|
||||
(append
|
||||
(project-roots pr)
|
||||
(project-library-roots pr)))))
|
||||
|
||||
(defun etags--xref-find-definitions (pattern &optional regexp?)
|
||||
;; This emulates the behaviour of `find-tag-in-order' but instead of
|
||||
@ -2154,7 +2157,7 @@ for \\[find-tag] (which see)."
|
||||
(with-slots (tag-info) l
|
||||
(nth 1 tag-info)))
|
||||
|
||||
(defun etags-search-path ()
|
||||
(defun etags-library-roots ()
|
||||
(mapcar #'file-name-directory tags-table-list))
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
;; projects, and a number of public functions: finding the current
|
||||
;; root, related project directories, search path, etc.
|
||||
;;
|
||||
;; The goal is to make it easy for Lisp programs to operate on the
|
||||
;; The goal is to make it easier for Lisp programs to operate on the
|
||||
;; current project, without having to know which package handles
|
||||
;; detection of that project type, parsing its config files, etc.
|
||||
|
||||
@ -31,63 +31,93 @@
|
||||
|
||||
(require 'cl-generic)
|
||||
|
||||
(defvar project-find-functions (list #'project-try-vc
|
||||
#'project-ask-user)
|
||||
(defvar project-find-functions (list #'project-try-vc)
|
||||
"Special hook to find the project containing a given directory.
|
||||
Each functions on this hook is called in turn with one
|
||||
argument (the directory) and should return either nil to mean
|
||||
that it is not applicable, or a project instance.")
|
||||
|
||||
(declare-function etags-search-path "etags" ())
|
||||
;; FIXME: Using the current approach, we don't have access to the
|
||||
;; "library roots" of language A from buffers of language B, which
|
||||
;; seems desirable in multi-language projects, at least for some
|
||||
;; potential uses, like "jump to a file in project or library".
|
||||
;;
|
||||
;; We can add a second argument to this function: a file extension, or
|
||||
;; a language name. Some projects will know the set of languages used
|
||||
;; in them; for others, like VC-based projects, we'll need
|
||||
;; auto-detection. I see two options:
|
||||
;;
|
||||
;; - That could be implemented as a separate second hook, with a
|
||||
;; list of functions that return file extensions.
|
||||
;;
|
||||
;; - This variable will be turned into a hook with "append" semantics,
|
||||
;; and each function in it will perform auto-detection when passed
|
||||
;; nil instead of an actual file extension. Then this hook will, in
|
||||
;; general, be modified globally, and not from major mode functions.
|
||||
(defvar project-library-roots-function 'etags-library-roots
|
||||
"Function that returns a list of library roots.
|
||||
|
||||
(defvar project-search-path-function #'etags-search-path
|
||||
"Function that returns a list of source root directories.
|
||||
It should return a list of directories that contain source files
|
||||
related to the current buffer. Depending on the language, it
|
||||
should include the headers search path, load path, class path,
|
||||
and so on.
|
||||
|
||||
The directories in which we can recursively look for the
|
||||
declarations or other references to the symbols used in the
|
||||
current buffer. Depending on the language, it should include the
|
||||
headers search path, load path, class path, or so on.
|
||||
|
||||
The directory names should be absolute. This variable is
|
||||
normally set by the major mode. Used in the default
|
||||
implementation of `project-search-path'.")
|
||||
The directory names should be absolute. Used in the default
|
||||
implementation of `project-library-roots'.")
|
||||
|
||||
;;;###autoload
|
||||
(defun project-current (&optional dir)
|
||||
"Return the project instance in DIR or `default-directory'."
|
||||
(defun project-current (&optional maybe-prompt dir)
|
||||
"Return the project instance in DIR or `default-directory'.
|
||||
When no project found in DIR, and MAYBE-PROMPT is non-nil, ask
|
||||
the user for a different directory to look in."
|
||||
(unless dir (setq dir default-directory))
|
||||
(let ((pr (project--find-in-directory dir)))
|
||||
(cond
|
||||
(pr)
|
||||
(maybe-prompt
|
||||
(setq dir (read-directory-name "Choose the project directory: " dir nil t)
|
||||
pr (project--find-in-directory dir))
|
||||
(unless pr
|
||||
(user-error "No project found in `%s'" dir))))
|
||||
pr))
|
||||
|
||||
(defun project--find-in-directory (dir)
|
||||
(run-hook-with-args-until-success 'project-find-functions dir))
|
||||
|
||||
;; FIXME: Add MODE argument, like in `ede-source-paths'?
|
||||
(cl-defgeneric project-search-path (project)
|
||||
"Return the list of source root directories.
|
||||
Any directory roots where source (or header, etc) files used by
|
||||
the current project may be found, inside or outside of the
|
||||
current project tree(s). The directory names should be absolute.
|
||||
(cl-defgeneric project-library-roots (project)
|
||||
"Return the list of library roots for PROJECT.
|
||||
|
||||
Unless it really knows better, a specialized implementation
|
||||
should take into account the value returned by
|
||||
`project-search-path-function' and call
|
||||
`project-prune-directories' on the result."
|
||||
(project-prune-directories
|
||||
(append
|
||||
;; We don't know the project layout, like where the sources are,
|
||||
;; so we simply include the roots.
|
||||
(project-roots project)
|
||||
(funcall project-search-path-function))))
|
||||
It's the list of directories outside of the project that contain
|
||||
related source files.
|
||||
|
||||
Project-specific version of `project-library-roots-function',
|
||||
which see. Unless it knows better, a specialized implementation
|
||||
should use the value returned by that function."
|
||||
(project-subtract-directories
|
||||
(project-combine-directories
|
||||
(funcall project-library-roots-function))
|
||||
(project-roots project)))
|
||||
|
||||
(cl-defgeneric project-roots (project)
|
||||
"Return the list of directory roots related to the current project.
|
||||
It should include the current project root, as well as the roots
|
||||
of any other currently open projects, if they're meant to be
|
||||
edited together. The directory names should be absolute.")
|
||||
"Return the list of directory roots belonging to the current project.
|
||||
|
||||
Most often it's just one directory, which contains the project
|
||||
file and everything else in the project. But in more advanced
|
||||
configurations, a project can span multiple directories.
|
||||
|
||||
The rule of tumb for whether to include a directory here, and not
|
||||
in `project-library-roots', is whether its contents are meant to
|
||||
be edited together with the rest of the project.
|
||||
|
||||
The directory names should be absolute.")
|
||||
|
||||
(cl-defgeneric project-ignores (_project _dir)
|
||||
"Return the list of glob patterns to ignore inside DIR.
|
||||
Patterns can match both regular files and directories.
|
||||
To root an entry, start it with `./'. To match directories only,
|
||||
end it with `/'. DIR must be either one of `project-roots', or
|
||||
an element of `project-search-path'."
|
||||
end it with `/'. DIR must be one of `project-roots' or
|
||||
`project-library-roots'."
|
||||
(require 'grep)
|
||||
(defvar grep-find-ignored-files)
|
||||
(nconc
|
||||
@ -101,8 +131,8 @@ an element of `project-search-path'."
|
||||
"Project implementation using the VC package."
|
||||
:group 'tools)
|
||||
|
||||
(defcustom project-vc-search-path nil
|
||||
"List ot directories to include in `project-search-path'.
|
||||
(defcustom project-vc-library-roots nil
|
||||
"List ot directories to include in `project-library-roots'.
|
||||
The file names can be absolute, or relative to the project root."
|
||||
:type '(repeat file)
|
||||
:safe 'listp)
|
||||
@ -121,13 +151,16 @@ The file names can be absolute, or relative to the project root."
|
||||
(cl-defmethod project-roots ((project (head vc)))
|
||||
(list (cdr project)))
|
||||
|
||||
(cl-defmethod project-search-path ((project (head vc)))
|
||||
(append
|
||||
(let ((root (cdr project)))
|
||||
(mapcar
|
||||
(lambda (dir) (expand-file-name dir root))
|
||||
(project--value-in-dir 'project-vc-search-path root)))
|
||||
(cl-call-next-method)))
|
||||
(cl-defmethod project-library-roots ((project (head vc)))
|
||||
(project-subtract-directories
|
||||
(project-combine-directories
|
||||
(append
|
||||
(let ((root (cdr project)))
|
||||
(mapcar
|
||||
(lambda (dir) (file-name-as-directory (expand-file-name dir root)))
|
||||
(project--value-in-dir 'project-vc-library-roots root)))
|
||||
(funcall project-library-roots-function)))
|
||||
(project-roots project)))
|
||||
|
||||
(cl-defmethod project-ignores ((project (head vc)) dir)
|
||||
(let* ((root (cdr project))
|
||||
@ -144,19 +177,16 @@ The file names can be absolute, or relative to the project root."
|
||||
(project--value-in-dir 'project-vc-ignores root)
|
||||
(cl-call-next-method))))
|
||||
|
||||
(defun project-ask-user (dir)
|
||||
(cons 'user (read-directory-name "Project root: " dir nil t)))
|
||||
|
||||
(cl-defmethod project-roots ((project (head user)))
|
||||
(list (cdr project)))
|
||||
|
||||
(defun project-prune-directories (dirs)
|
||||
"Returns a copy of DIRS sorted, without subdirectories or non-existing ones."
|
||||
(defun project-combine-directories (&rest lists-of-dirs)
|
||||
"Return a sorted and culled list of directory names.
|
||||
Appends the elements of LISTS-OF-DIRS together, removes
|
||||
non-existing directories, as well as directories a parent of
|
||||
whose is already in the list."
|
||||
(let* ((dirs (sort
|
||||
(mapcar
|
||||
(lambda (dir)
|
||||
(file-name-as-directory (expand-file-name dir)))
|
||||
dirs)
|
||||
(apply #'append lists-of-dirs))
|
||||
#'string<))
|
||||
(ref dirs))
|
||||
;; Delete subdirectories from the list.
|
||||
@ -166,11 +196,66 @@ The file names can be absolute, or relative to the project root."
|
||||
(setq ref (cdr ref))))
|
||||
(cl-delete-if-not #'file-exists-p dirs)))
|
||||
|
||||
(defun project-subtract-directories (files dirs)
|
||||
"Return a list of elements from FILES that are outside of DIRS.
|
||||
DIRS must contain directory names."
|
||||
;; Sidestep the issue of expanded/abbreviated file names here.
|
||||
(cl-set-difference files dirs :test #'file-in-directory-p))
|
||||
|
||||
(defun project--value-in-dir (var dir)
|
||||
(with-temp-buffer
|
||||
(setq default-directory dir)
|
||||
(hack-dir-local-variables-non-file-buffer)
|
||||
(symbol-value var)))
|
||||
|
||||
(declare-function grep-read-files "grep")
|
||||
(declare-function xref-collect-matches "xref")
|
||||
(declare-function xref--show-xrefs "xref")
|
||||
|
||||
;;;###autoload
|
||||
(defun project-find-regexp (regexp)
|
||||
"Find all matches for REGEXP in the current project.
|
||||
With \\[universal-argument] prefix, you can specify the directory
|
||||
to search in, and the file name pattern to search for."
|
||||
(interactive (list (project--read-regexp)))
|
||||
(let* ((pr (project-current t))
|
||||
(dirs (if current-prefix-arg
|
||||
(list (read-directory-name "Base directory: "
|
||||
nil default-directory t))
|
||||
(project-roots pr))))
|
||||
(project--find-regexp-in dirs regexp pr)))
|
||||
|
||||
;;;###autoload
|
||||
(defun project-or-libraries-find-regexp (regexp)
|
||||
"Find all matches for REGEXP in the current project or libraries.
|
||||
With \\[universal-argument] prefix, you can specify the file name
|
||||
pattern to search for."
|
||||
(interactive (list (project--read-regexp)))
|
||||
(let* ((pr (project-current t))
|
||||
(dirs (append
|
||||
(project-roots pr)
|
||||
(project-library-roots pr))))
|
||||
(project--find-regexp-in dirs regexp pr)))
|
||||
|
||||
(defun project--read-regexp ()
|
||||
(defvar xref-identifier-at-point-function)
|
||||
(require 'xref)
|
||||
(read-regexp "Find regexp"
|
||||
(funcall xref-identifier-at-point-function)))
|
||||
|
||||
(defun project--find-regexp-in (dirs regexp project)
|
||||
(require 'grep)
|
||||
(let* ((files (if current-prefix-arg
|
||||
(grep-read-files regexp)
|
||||
"*"))
|
||||
(xrefs (cl-mapcan
|
||||
(lambda (dir)
|
||||
(xref-collect-matches regexp files dir
|
||||
(project-ignores project dir)))
|
||||
dirs)))
|
||||
(unless xrefs
|
||||
(user-error "No matches for: %s" regexp))
|
||||
(xref--show-xrefs xrefs nil)))
|
||||
|
||||
(provide 'project)
|
||||
;;; project.el ends here
|
||||
|
@ -414,20 +414,6 @@ WINDOW controls how the buffer is displayed:
|
||||
(defvar-local xref--display-history nil
|
||||
"List of pairs (BUFFER . WINDOW), for temporarily displayed buffers.")
|
||||
|
||||
(defvar-local xref--temporary-buffers nil
|
||||
"List of buffers created by xref code.")
|
||||
|
||||
(defvar-local xref--current nil
|
||||
"Non-nil if this buffer was once current, except while displaying xrefs.
|
||||
Used for temporary buffers.")
|
||||
|
||||
(defvar xref--inhibit-mark-current nil)
|
||||
|
||||
(defun xref--mark-selected ()
|
||||
(unless xref--inhibit-mark-current
|
||||
(setq xref--current t))
|
||||
(remove-hook 'buffer-list-update-hook #'xref--mark-selected t))
|
||||
|
||||
(defun xref--save-to-history (buf win)
|
||||
(let ((restore (window-parameter win 'quit-restore)))
|
||||
;; Save the new entry if the window displayed another buffer
|
||||
@ -449,15 +435,9 @@ Used for temporary buffers.")
|
||||
|
||||
(defun xref--show-location (location)
|
||||
(condition-case err
|
||||
(let ((bl (buffer-list))
|
||||
(xref--inhibit-mark-current t)
|
||||
(marker (xref-location-marker location)))
|
||||
(let ((buf (marker-buffer marker)))
|
||||
(unless (memq buf bl)
|
||||
;; Newly created.
|
||||
(add-hook 'buffer-list-update-hook #'xref--mark-selected nil t)
|
||||
(push buf xref--temporary-buffers))
|
||||
(xref--display-position marker t buf)))
|
||||
(let* ((marker (xref-location-marker location))
|
||||
(buf (marker-buffer marker)))
|
||||
(xref--display-position marker t buf))
|
||||
(user-error (message (error-message-string err)))))
|
||||
|
||||
(defun xref-show-location-at-point ()
|
||||
@ -594,8 +574,7 @@ Used for temporary buffers.")
|
||||
(defun xref-quit (&optional kill)
|
||||
"Bury temporarily displayed buffers, then quit the current window.
|
||||
|
||||
If KILL is non-nil, kill all buffers that were created in the
|
||||
process of showing xrefs, and also kill the current buffer.
|
||||
If KILL is non-nil, also kill the current buffer.
|
||||
|
||||
The buffers that the user has otherwise interacted with in the
|
||||
meantime are preserved."
|
||||
@ -607,13 +586,6 @@ meantime are preserved."
|
||||
(when (and (window-live-p win)
|
||||
(eq buf (window-buffer win)))
|
||||
(quit-window nil win)))
|
||||
(when kill
|
||||
(let ((xref--inhibit-mark-current t)
|
||||
kill-buffer-query-functions)
|
||||
(dolist (buf xref--temporary-buffers)
|
||||
(unless (buffer-local-value 'xref--current buf)
|
||||
(kill-buffer buf)))
|
||||
(setq xref--temporary-buffers nil)))
|
||||
(quit-window kill window)))
|
||||
|
||||
(defconst xref-buffer-name "*xref*"
|
||||
@ -687,15 +659,13 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)."
|
||||
(pop-to-buffer (current-buffer))
|
||||
(goto-char (point-min))
|
||||
(setq xref--window (assoc-default 'window alist))
|
||||
(setq xref--temporary-buffers (assoc-default 'temporary-buffers alist))
|
||||
(dolist (buf xref--temporary-buffers)
|
||||
(with-current-buffer buf
|
||||
(add-hook 'buffer-list-update-hook #'xref--mark-selected nil t)))
|
||||
(current-buffer)))))
|
||||
|
||||
|
||||
;; This part of the UI seems fairly uncontroversial: it reads the
|
||||
;; identifier and deals with the single definition case.
|
||||
;; (FIXME: do we really want this case to be handled like that in
|
||||
;; "find references" and "find regexp searches"?)
|
||||
;;
|
||||
;; The controversial multiple definitions case is handed off to
|
||||
;; xref-show-xrefs-function.
|
||||
@ -707,21 +677,15 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)."
|
||||
|
||||
(defvar xref--read-pattern-history nil)
|
||||
|
||||
(defun xref--show-xrefs (input kind arg window)
|
||||
(let* ((bl (buffer-list))
|
||||
(xrefs (funcall xref-find-function kind arg))
|
||||
(tb (cl-set-difference (buffer-list) bl)))
|
||||
(cond
|
||||
((null xrefs)
|
||||
(user-error "No %s found for: %s" (symbol-name kind) input))
|
||||
((not (cdr xrefs))
|
||||
(xref-push-marker-stack)
|
||||
(xref--pop-to-location (car xrefs) window))
|
||||
(t
|
||||
(xref-push-marker-stack)
|
||||
(funcall xref-show-xrefs-function xrefs
|
||||
`((window . ,window)
|
||||
(temporary-buffers . ,tb)))))))
|
||||
(defun xref--show-xrefs (xrefs window)
|
||||
(cond
|
||||
((not (cdr xrefs))
|
||||
(xref-push-marker-stack)
|
||||
(xref--pop-to-location (car xrefs) window))
|
||||
(t
|
||||
(xref-push-marker-stack)
|
||||
(funcall xref-show-xrefs-function xrefs
|
||||
`((window . ,window))))))
|
||||
|
||||
(defun xref--prompt-p (command)
|
||||
(or (eq xref-prompt-for-identifier t)
|
||||
@ -749,8 +713,14 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)."
|
||||
|
||||
;;; Commands
|
||||
|
||||
(defun xref--find-xrefs (input kind arg window)
|
||||
(let ((xrefs (funcall xref-find-function kind arg)))
|
||||
(unless xrefs
|
||||
(user-error "No %s found for: %s" (symbol-name kind) input))
|
||||
(xref--show-xrefs xrefs window)))
|
||||
|
||||
(defun xref--find-definitions (id window)
|
||||
(xref--show-xrefs id 'definitions id window))
|
||||
(xref--find-xrefs id 'definitions id window))
|
||||
|
||||
;;;###autoload
|
||||
(defun xref-find-definitions (identifier)
|
||||
@ -784,36 +754,7 @@ display the list in a buffer."
|
||||
"Find references to the identifier at point.
|
||||
With prefix argument, prompt for the identifier."
|
||||
(interactive (list (xref--read-identifier "Find references of: ")))
|
||||
(xref--show-xrefs identifier 'references identifier nil))
|
||||
|
||||
;; TODO: Rename and move to project-find-regexp, as soon as idiomatic
|
||||
;; usage of xref from other packages has stabilized.
|
||||
;;;###autoload
|
||||
(defun xref-find-regexp (regexp)
|
||||
"Find all matches for REGEXP.
|
||||
With \\[universal-argument] prefix, you can specify the directory
|
||||
to search in, and the file name pattern to search for."
|
||||
(interactive (list (xref--read-identifier "Find regexp: ")))
|
||||
(require 'grep)
|
||||
(let* ((proj (project-current))
|
||||
(files (if current-prefix-arg
|
||||
(grep-read-files regexp)
|
||||
"*"))
|
||||
(dirs (if current-prefix-arg
|
||||
(list (read-directory-name "Base directory: "
|
||||
nil default-directory t))
|
||||
(project-prune-directories
|
||||
(append
|
||||
(project-roots proj)
|
||||
(project-search-path proj)))))
|
||||
(xref-find-function
|
||||
(lambda (_kind regexp)
|
||||
(cl-mapcan
|
||||
(lambda (dir)
|
||||
(xref-collect-matches regexp files dir
|
||||
(project-ignores proj dir)))
|
||||
dirs))))
|
||||
(xref--show-xrefs regexp 'matches regexp nil)))
|
||||
(xref--find-xrefs identifier 'references identifier nil))
|
||||
|
||||
(declare-function apropos-parse-pattern "apropos" (pattern))
|
||||
|
||||
@ -825,7 +766,7 @@ The argument has the same meaning as in `apropos'."
|
||||
"Search for pattern (word list or regexp): "
|
||||
nil 'xref--read-pattern-history)))
|
||||
(require 'apropos)
|
||||
(xref--show-xrefs pattern 'apropos
|
||||
(xref--find-xrefs pattern 'apropos
|
||||
(apropos-parse-pattern
|
||||
(if (string-equal (regexp-quote pattern) pattern)
|
||||
;; Split into words
|
||||
@ -869,7 +810,6 @@ and just use etags."
|
||||
|
||||
(declare-function semantic-symref-find-references-by-name "semantic/symref")
|
||||
(declare-function semantic-find-file-noselect "semantic/fw")
|
||||
(declare-function grep-read-files "grep")
|
||||
(declare-function grep-expand-template "grep")
|
||||
|
||||
(defun xref-collect-references (symbol dir)
|
||||
|
@ -1433,8 +1433,9 @@ Argument BACKEND is the backend you are using."
|
||||
(lambda (str)
|
||||
;; Commented or empty lines.
|
||||
(string-match-p "\\`\\(?:#\\|[ \t\r\n]*\\'\\)" str))
|
||||
(vc--read-lines
|
||||
(vc-call-backend backend 'find-ignore-file file))))
|
||||
(let ((file (vc-call-backend backend 'find-ignore-file file)))
|
||||
(and (file-exists-p file)
|
||||
(vc--read-lines file)))))
|
||||
|
||||
(defun vc--read-lines (file)
|
||||
"Return a list of lines of FILE."
|
||||
|
@ -117,8 +117,8 @@
|
||||
(should (equal (cl-set-difference b b) e))
|
||||
;; Note: this test (and others) is sensitive to the order of the
|
||||
;; result, which is not documented.
|
||||
(should (equal (cl-set-difference a b) (list c2 "x" "" nil 'a)))
|
||||
(should (equal (cl-set-difference b a) (list 'x 'y)))
|
||||
(should (equal (cl-set-difference a b) (list 'a nil "" "x" c2)))
|
||||
(should (equal (cl-set-difference b a) (list 'y 'x)))
|
||||
|
||||
;; We aren't testing whether this is really using `eq' rather than `eql'.
|
||||
(should (equal (cl-set-difference e e :test 'eq) e))
|
||||
@ -128,8 +128,8 @@
|
||||
(should (equal (cl-set-difference b e :test 'eq) b))
|
||||
(should (equal (cl-set-difference e b :test 'eq) e))
|
||||
(should (equal (cl-set-difference b b :test 'eq) e))
|
||||
(should (equal (cl-set-difference a b :test 'eq) (list c2 "x" "" nil 'a)))
|
||||
(should (equal (cl-set-difference b a :test 'eq) (list 'x 'y)))
|
||||
(should (equal (cl-set-difference a b :test 'eq) (list 'a nil "" "x" c2)))
|
||||
(should (equal (cl-set-difference b a :test 'eq) (list 'y 'x)))
|
||||
|
||||
(should (equal (cl-union e e) e))
|
||||
(should (equal (cl-union a e) a))
|
||||
|
Loading…
Reference in New Issue
Block a user