Rename project-library-roots to project-external-roots
* lisp/progmodes/project.el (project-library-roots): Rename to project-external-roots. (project-library-roots-function): Rename to project-vc-external-roots-function. Only use it in the VC backend, for now. Update project-external-roots accordingly. (project-vc-library-roots): Remove. (project-or-libraries-find-regexp): Rename to project-or-external-find-regexp. * lisp/progmodes/elisp-mode.el (elisp-library-roots): Rename to elisp-load-path-roots. * lisp/progmodes/etags.el (etags-library-roots): Remove. Use an anonymous function for the default value of project-vc-external-roots-function.
This commit is contained in:
parent
a36c88806d
commit
17ab0d10e1
4 changed files with 113 additions and 82 deletions
|
@ -228,7 +228,7 @@ Blank lines separate paragraphs. Semicolons start comments.
|
|||
|
||||
\\{emacs-lisp-mode-map}"
|
||||
:group 'lisp
|
||||
(defvar project-library-roots-function)
|
||||
(defvar project-vc-external-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
|
||||
|
@ -238,7 +238,7 @@ Blank lines separate paragraphs. Semicolons start comments.
|
|||
(add-function :before-until (local 'eldoc-documentation-function)
|
||||
#'elisp-eldoc-documentation-function)
|
||||
(add-hook 'xref-backend-functions #'elisp--xref-backend nil t)
|
||||
(setq-local project-library-roots-function #'elisp-library-roots)
|
||||
(setq-local project-vc-external-roots-function #'elisp-load-path-roots)
|
||||
(add-hook 'completion-at-point-functions
|
||||
#'elisp-completion-at-point nil 'local))
|
||||
|
||||
|
@ -795,7 +795,7 @@ non-nil result supercedes the xrefs produced by
|
|||
|
||||
xrefs))
|
||||
|
||||
(declare-function project-library-roots "project")
|
||||
(declare-function project-external-roots "project")
|
||||
|
||||
(cl-defmethod xref-backend-apropos ((_backend (eql elisp)) regexp)
|
||||
(apply #'nconc
|
||||
|
@ -832,7 +832,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-library-roots ()
|
||||
(defun elisp-load-path-roots ()
|
||||
(if (boundp 'package-user-dir)
|
||||
(cons package-user-dir load-path)
|
||||
load-path))
|
||||
|
|
|
@ -2154,9 +2154,6 @@ for \\[find-tag] (which see)."
|
|||
(with-slots (tag-info) l
|
||||
(nth 1 tag-info)))
|
||||
|
||||
(defun etags-library-roots ()
|
||||
(mapcar #'file-name-directory tags-table-list))
|
||||
|
||||
|
||||
(provide 'etags)
|
||||
|
||||
|
|
|
@ -20,13 +20,55 @@
|
|||
;;; Commentary:
|
||||
|
||||
;; This file contains generic infrastructure for dealing with
|
||||
;; projects, and a number of public functions: finding the current
|
||||
;; root, related project directories, and library directories. This
|
||||
;; list is to be extended in future versions.
|
||||
;; projects, some utility functions, and commands using that
|
||||
;; infrastructure.
|
||||
;;
|
||||
;; 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.
|
||||
;;
|
||||
;; Infrastructure:
|
||||
;;
|
||||
;; Function `project-current', to determine the current project
|
||||
;; instance, and 3 (at the moment) generic functions that act on it.
|
||||
;; This list is to be extended in future versions.
|
||||
;;
|
||||
;; Utils:
|
||||
;;
|
||||
;; `project-combine-directories' and `project-subtract-directories',
|
||||
;; mainly for use in the aborementioned generics' implementations.
|
||||
;;
|
||||
;; Commands:
|
||||
;;
|
||||
;; `project-find-regexp' and `project-or-external-find-regexp' use the
|
||||
;; current API, and thus will work in any project that has an adapter.
|
||||
|
||||
;;; TODO:
|
||||
|
||||
;; * Commands `project-find-file' and `project-or-external-find-file'.
|
||||
;; Currently blocked on adding a new completion style that would let
|
||||
;; the user enter just the base file name (or a part of it), and get
|
||||
;; it expanded to the absolute file name.
|
||||
;;
|
||||
;; * Build tool related functionality. Start with a `project-build'
|
||||
;; command, which should provide completions on tasks to run, and
|
||||
;; maybe allow entering some additional arguments. This might
|
||||
;; be handled better with a separate API, though. Then we won't
|
||||
;; force every project backend to be aware of the build tool(s) the
|
||||
;; project is using.
|
||||
;;
|
||||
;; * Command to (re)build the tag files in all project roots. To that
|
||||
;; end, we might need to add a way to limit etags to certain files
|
||||
;; (e.g. have a whitelist, in addition to the blacklist provided by
|
||||
;; ignores), and/or allow specifying additional tag regexps.
|
||||
;;
|
||||
;; * UI for the user to be able to pick the current project for the
|
||||
;; whole Emacs session, independent of the current directory. Or,
|
||||
;; in the more advanced case, open a set of projects, and have some
|
||||
;; project-related commands to use them all. E.g., have a command
|
||||
;; to search for a regexp across all open projects. Provide a
|
||||
;; history of projects that were opened in the past (storing it as a
|
||||
;; list of directories should suffice).
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
@ -38,35 +80,6 @@ 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.")
|
||||
|
||||
;; FIXME: Using the current approach, major modes are supposed to set
|
||||
;; this variable to a buffer-local value. So 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.
|
||||
|
||||
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 directory names should be absolute. Used in the default
|
||||
implementation of `project-library-roots'.")
|
||||
|
||||
;;;###autoload
|
||||
(defun project-current (&optional maybe-prompt dir)
|
||||
"Return the project instance in DIR or `default-directory'.
|
||||
|
@ -86,40 +99,35 @@ the user for a different directory to look in."
|
|||
(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-library-roots (project)
|
||||
"Return the list of library roots for PROJECT.
|
||||
|
||||
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 belonging to the current project.
|
||||
"Return the list of directory roots of 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 thumb 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.
|
||||
Most often it's just one directory which contains the project
|
||||
build file and everything else in the project. But in more
|
||||
advanced configurations, a project can span multiple directories.
|
||||
|
||||
The directory names should be absolute.")
|
||||
|
||||
;; FIXME: Add MODE argument, like in `ede-source-paths'?
|
||||
(cl-defgeneric project-external-roots (_project)
|
||||
"Return the list of external roots for PROJECT.
|
||||
|
||||
It's the list of directories outside of the project that are
|
||||
still related to it. If the project deals with source code then,
|
||||
depending on the languages used, this list should include the
|
||||
headers search path, load path, class path, and so on.
|
||||
|
||||
The rule of thumb for whether to include a directory here, and
|
||||
not in `project-roots', is whether its contents are meant to be
|
||||
edited together with the rest of the project."
|
||||
nil)
|
||||
|
||||
(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 one of `project-roots' or
|
||||
`project-library-roots'."
|
||||
`project-external-roots'."
|
||||
(require 'grep)
|
||||
(defvar grep-find-ignored-files)
|
||||
(nconc
|
||||
|
@ -133,17 +141,46 @@ end it with `/'. DIR must be one of `project-roots' or
|
|||
"Project implementation using the VC package."
|
||||
:group 'tools)
|
||||
|
||||
(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)
|
||||
|
||||
(defcustom project-vc-ignores nil
|
||||
"List ot patterns to include in `project-ignores'."
|
||||
:type '(repeat string)
|
||||
:safe 'listp)
|
||||
|
||||
;; FIXME: Using the current approach, major modes are supposed to set
|
||||
;; this variable to a buffer-local value. So we don't have access to
|
||||
;; the "external 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 external dirs".
|
||||
;;
|
||||
;; We could 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.
|
||||
;;
|
||||
;; The second option seems simpler, but the first one has the
|
||||
;; advantage that the user could override the list of languages used
|
||||
;; in a project via a directory-local variable, thus skipping
|
||||
;; languages they're not working on personally (in a big project), or
|
||||
;; working around problems in language detection (the detection logic
|
||||
;; might be imperfect for the project in question, or it might work
|
||||
;; too slowly for the user's taste).
|
||||
(defvar project-vc-external-roots-function (lambda () tags-table-list)
|
||||
"Function that returns a list of external roots.
|
||||
|
||||
It should return a list of directory roots that contain source
|
||||
files related to the current buffer.
|
||||
|
||||
The directory names should be absolute. Used in the VC project
|
||||
backend implementation of `project-external-roots'.")
|
||||
|
||||
(defun project-try-vc (dir)
|
||||
(let* ((backend (ignore-errors (vc-responsible-backend dir)))
|
||||
(root (and backend (ignore-errors
|
||||
|
@ -153,15 +190,12 @@ 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-library-roots ((project (head vc)))
|
||||
(cl-defmethod project-external-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)))
|
||||
(mapcar
|
||||
#'file-name-as-directory
|
||||
(funcall project-vc-external-roots-function)))
|
||||
(project-roots project)))
|
||||
|
||||
(cl-defmethod project-ignores ((project (head vc)) dir)
|
||||
|
@ -217,7 +251,7 @@ DIRS must contain directory names."
|
|||
|
||||
;;;###autoload
|
||||
(defun project-find-regexp (regexp)
|
||||
"Find all matches for REGEXP in the current project.
|
||||
"Find all matches for REGEXP in the current project's roots.
|
||||
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)))
|
||||
|
@ -229,15 +263,15 @@ to search in, and the file name pattern to search for."
|
|||
(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.
|
||||
(defun project-or-external-find-regexp (regexp)
|
||||
"Find all matches for REGEXP in the project roots or external roots.
|
||||
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-external-roots pr))))
|
||||
(project--find-regexp-in dirs regexp pr)))
|
||||
|
||||
(defun project--read-regexp ()
|
||||
|
|
|
@ -246,7 +246,7 @@ find a search tool; by default, this uses \"find | grep\" in the
|
|||
(let ((pr (project-current t)))
|
||||
(append
|
||||
(project-roots pr)
|
||||
(project-library-roots pr)))))
|
||||
(project-external-roots pr)))))
|
||||
|
||||
(cl-defgeneric xref-backend-apropos (backend pattern)
|
||||
"Find all symbols that match PATTERN.
|
||||
|
@ -886,7 +886,7 @@ IGNORES is a list of glob patterns."
|
|||
hits)))
|
||||
(unwind-protect
|
||||
(cl-mapcan (lambda (hit) (xref--collect-matches hit regexp))
|
||||
(nreverse hits))
|
||||
hits)
|
||||
;; TODO: Same as above.
|
||||
(mapc #'kill-buffer
|
||||
(cl-set-difference (buffer-list) orig-buffers)))))
|
||||
|
|
Loading…
Add table
Reference in a new issue