diff options
| author | Dmitry Gutov | 2015-12-28 06:17:19 +0200 |
|---|---|---|
| committer | Dmitry Gutov | 2015-12-28 06:17:37 +0200 |
| commit | 17ab0d10e1db9cc4924ceb778e5c4e6bb9a90c3d (patch) | |
| tree | 51c363d5a5c43ac10526b4ca715a097788291099 | |
| parent | a36c88806dcfc993e6af83b0d0f44b077293bc30 (diff) | |
| download | emacs-17ab0d10e1db9cc4924ceb778e5c4e6bb9a90c3d.tar.gz emacs-17ab0d10e1db9cc4924ceb778e5c4e6bb9a90c3d.zip | |
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.
| -rw-r--r-- | lisp/progmodes/elisp-mode.el | 8 | ||||
| -rw-r--r-- | lisp/progmodes/etags.el | 3 | ||||
| -rw-r--r-- | lisp/progmodes/project.el | 178 | ||||
| -rw-r--r-- | lisp/progmodes/xref.el | 4 |
4 files changed, 112 insertions, 81 deletions
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 12848fe02e0..4cc2aee9346 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el | |||
| @@ -228,7 +228,7 @@ Blank lines separate paragraphs. Semicolons start comments. | |||
| 228 | 228 | ||
| 229 | \\{emacs-lisp-mode-map}" | 229 | \\{emacs-lisp-mode-map}" |
| 230 | :group 'lisp | 230 | :group 'lisp |
| 231 | (defvar project-library-roots-function) | 231 | (defvar project-vc-external-roots-function) |
| 232 | (lisp-mode-variables nil nil 'elisp) | 232 | (lisp-mode-variables nil nil 'elisp) |
| 233 | (add-hook 'after-load-functions #'elisp--font-lock-flush-elisp-buffers) | 233 | (add-hook 'after-load-functions #'elisp--font-lock-flush-elisp-buffers) |
| 234 | (setq-local electric-pair-text-pairs | 234 | (setq-local electric-pair-text-pairs |
| @@ -238,7 +238,7 @@ Blank lines separate paragraphs. Semicolons start comments. | |||
| 238 | (add-function :before-until (local 'eldoc-documentation-function) | 238 | (add-function :before-until (local 'eldoc-documentation-function) |
| 239 | #'elisp-eldoc-documentation-function) | 239 | #'elisp-eldoc-documentation-function) |
| 240 | (add-hook 'xref-backend-functions #'elisp--xref-backend nil t) | 240 | (add-hook 'xref-backend-functions #'elisp--xref-backend nil t) |
| 241 | (setq-local project-library-roots-function #'elisp-library-roots) | 241 | (setq-local project-vc-external-roots-function #'elisp-load-path-roots) |
| 242 | (add-hook 'completion-at-point-functions | 242 | (add-hook 'completion-at-point-functions |
| 243 | #'elisp-completion-at-point nil 'local)) | 243 | #'elisp-completion-at-point nil 'local)) |
| 244 | 244 | ||
| @@ -795,7 +795,7 @@ non-nil result supercedes the xrefs produced by | |||
| 795 | 795 | ||
| 796 | xrefs)) | 796 | xrefs)) |
| 797 | 797 | ||
| 798 | (declare-function project-library-roots "project") | 798 | (declare-function project-external-roots "project") |
| 799 | 799 | ||
| 800 | (cl-defmethod xref-backend-apropos ((_backend (eql elisp)) regexp) | 800 | (cl-defmethod xref-backend-apropos ((_backend (eql elisp)) regexp) |
| 801 | (apply #'nconc | 801 | (apply #'nconc |
| @@ -832,7 +832,7 @@ non-nil result supercedes the xrefs produced by | |||
| 832 | (cl-defmethod xref-location-group ((l xref-elisp-location)) | 832 | (cl-defmethod xref-location-group ((l xref-elisp-location)) |
| 833 | (xref-elisp-location-file l)) | 833 | (xref-elisp-location-file l)) |
| 834 | 834 | ||
| 835 | (defun elisp-library-roots () | 835 | (defun elisp-load-path-roots () |
| 836 | (if (boundp 'package-user-dir) | 836 | (if (boundp 'package-user-dir) |
| 837 | (cons package-user-dir load-path) | 837 | (cons package-user-dir load-path) |
| 838 | load-path)) | 838 | load-path)) |
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index 306572510ef..dbb46a38381 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el | |||
| @@ -2154,9 +2154,6 @@ for \\[find-tag] (which see)." | |||
| 2154 | (with-slots (tag-info) l | 2154 | (with-slots (tag-info) l |
| 2155 | (nth 1 tag-info))) | 2155 | (nth 1 tag-info))) |
| 2156 | 2156 | ||
| 2157 | (defun etags-library-roots () | ||
| 2158 | (mapcar #'file-name-directory tags-table-list)) | ||
| 2159 | |||
| 2160 | 2157 | ||
| 2161 | (provide 'etags) | 2158 | (provide 'etags) |
| 2162 | 2159 | ||
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 40d7e03baf4..e00f143fd05 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el | |||
| @@ -20,13 +20,55 @@ | |||
| 20 | ;;; Commentary: | 20 | ;;; Commentary: |
| 21 | 21 | ||
| 22 | ;; This file contains generic infrastructure for dealing with | 22 | ;; This file contains generic infrastructure for dealing with |
| 23 | ;; projects, and a number of public functions: finding the current | 23 | ;; projects, some utility functions, and commands using that |
| 24 | ;; root, related project directories, and library directories. This | 24 | ;; infrastructure. |
| 25 | ;; list is to be extended in future versions. | ||
| 26 | ;; | 25 | ;; |
| 27 | ;; The goal is to make it easier for Lisp programs to operate on the | 26 | ;; The goal is to make it easier for Lisp programs to operate on the |
| 28 | ;; current project, without having to know which package handles | 27 | ;; current project, without having to know which package handles |
| 29 | ;; detection of that project type, parsing its config files, etc. | 28 | ;; detection of that project type, parsing its config files, etc. |
| 29 | ;; | ||
| 30 | ;; Infrastructure: | ||
| 31 | ;; | ||
| 32 | ;; Function `project-current', to determine the current project | ||
| 33 | ;; instance, and 3 (at the moment) generic functions that act on it. | ||
| 34 | ;; This list is to be extended in future versions. | ||
| 35 | ;; | ||
| 36 | ;; Utils: | ||
| 37 | ;; | ||
| 38 | ;; `project-combine-directories' and `project-subtract-directories', | ||
| 39 | ;; mainly for use in the aborementioned generics' implementations. | ||
| 40 | ;; | ||
| 41 | ;; Commands: | ||
| 42 | ;; | ||
| 43 | ;; `project-find-regexp' and `project-or-external-find-regexp' use the | ||
| 44 | ;; current API, and thus will work in any project that has an adapter. | ||
| 45 | |||
| 46 | ;;; TODO: | ||
| 47 | |||
| 48 | ;; * Commands `project-find-file' and `project-or-external-find-file'. | ||
| 49 | ;; Currently blocked on adding a new completion style that would let | ||
| 50 | ;; the user enter just the base file name (or a part of it), and get | ||
| 51 | ;; it expanded to the absolute file name. | ||
| 52 | ;; | ||
| 53 | ;; * Build tool related functionality. Start with a `project-build' | ||
| 54 | ;; command, which should provide completions on tasks to run, and | ||
| 55 | ;; maybe allow entering some additional arguments. This might | ||
| 56 | ;; be handled better with a separate API, though. Then we won't | ||
| 57 | ;; force every project backend to be aware of the build tool(s) the | ||
| 58 | ;; project is using. | ||
| 59 | ;; | ||
| 60 | ;; * Command to (re)build the tag files in all project roots. To that | ||
| 61 | ;; end, we might need to add a way to limit etags to certain files | ||
| 62 | ;; (e.g. have a whitelist, in addition to the blacklist provided by | ||
| 63 | ;; ignores), and/or allow specifying additional tag regexps. | ||
| 64 | ;; | ||
| 65 | ;; * UI for the user to be able to pick the current project for the | ||
| 66 | ;; whole Emacs session, independent of the current directory. Or, | ||
| 67 | ;; in the more advanced case, open a set of projects, and have some | ||
| 68 | ;; project-related commands to use them all. E.g., have a command | ||
| 69 | ;; to search for a regexp across all open projects. Provide a | ||
| 70 | ;; history of projects that were opened in the past (storing it as a | ||
| 71 | ;; list of directories should suffice). | ||
| 30 | 72 | ||
| 31 | ;;; Code: | 73 | ;;; Code: |
| 32 | 74 | ||
| @@ -38,35 +80,6 @@ Each functions on this hook is called in turn with one | |||
| 38 | argument (the directory) and should return either nil to mean | 80 | argument (the directory) and should return either nil to mean |
| 39 | that it is not applicable, or a project instance.") | 81 | that it is not applicable, or a project instance.") |
| 40 | 82 | ||
| 41 | ;; FIXME: Using the current approach, major modes are supposed to set | ||
| 42 | ;; this variable to a buffer-local value. So we don't have access to | ||
| 43 | ;; the "library roots" of language A from buffers of language B, which | ||
| 44 | ;; seems desirable in multi-language projects, at least for some | ||
| 45 | ;; potential uses, like "jump to a file in project or library". | ||
| 46 | ;; | ||
| 47 | ;; We can add a second argument to this function: a file extension, or | ||
| 48 | ;; a language name. Some projects will know the set of languages used | ||
| 49 | ;; in them; for others, like VC-based projects, we'll need | ||
| 50 | ;; auto-detection. I see two options: | ||
| 51 | ;; | ||
| 52 | ;; - That could be implemented as a separate second hook, with a | ||
| 53 | ;; list of functions that return file extensions. | ||
| 54 | ;; | ||
| 55 | ;; - This variable will be turned into a hook with "append" semantics, | ||
| 56 | ;; and each function in it will perform auto-detection when passed | ||
| 57 | ;; nil instead of an actual file extension. Then this hook will, in | ||
| 58 | ;; general, be modified globally, and not from major mode functions. | ||
| 59 | (defvar project-library-roots-function 'etags-library-roots | ||
| 60 | "Function that returns a list of library roots. | ||
| 61 | |||
| 62 | It should return a list of directories that contain source files | ||
| 63 | related to the current buffer. Depending on the language, it | ||
| 64 | should include the headers search path, load path, class path, | ||
| 65 | and so on. | ||
| 66 | |||
| 67 | The directory names should be absolute. Used in the default | ||
| 68 | implementation of `project-library-roots'.") | ||
| 69 | |||
| 70 | ;;;###autoload | 83 | ;;;###autoload |
| 71 | (defun project-current (&optional maybe-prompt dir) | 84 | (defun project-current (&optional maybe-prompt dir) |
| 72 | "Return the project instance in DIR or `default-directory'. | 85 | "Return the project instance in DIR or `default-directory'. |
| @@ -86,40 +99,35 @@ the user for a different directory to look in." | |||
| 86 | (defun project--find-in-directory (dir) | 99 | (defun project--find-in-directory (dir) |
| 87 | (run-hook-with-args-until-success 'project-find-functions dir)) | 100 | (run-hook-with-args-until-success 'project-find-functions dir)) |
| 88 | 101 | ||
| 89 | ;; FIXME: Add MODE argument, like in `ede-source-paths'? | 102 | (cl-defgeneric project-roots (project) |
| 90 | (cl-defgeneric project-library-roots (project) | 103 | "Return the list of directory roots of the current project. |
| 91 | "Return the list of library roots for PROJECT. | ||
| 92 | |||
| 93 | It's the list of directories outside of the project that contain | ||
| 94 | related source files. | ||
| 95 | 104 | ||
| 96 | Project-specific version of `project-library-roots-function', | 105 | Most often it's just one directory which contains the project |
| 97 | which see. Unless it knows better, a specialized implementation | 106 | build file and everything else in the project. But in more |
| 98 | should use the value returned by that function." | 107 | advanced configurations, a project can span multiple directories. |
| 99 | (project-subtract-directories | ||
| 100 | (project-combine-directories | ||
| 101 | (funcall project-library-roots-function)) | ||
| 102 | (project-roots project))) | ||
| 103 | 108 | ||
| 104 | (cl-defgeneric project-roots (project) | 109 | The directory names should be absolute.") |
| 105 | "Return the list of directory roots belonging to the current project. | ||
| 106 | 110 | ||
| 107 | Most often it's just one directory, which contains the project | 111 | ;; FIXME: Add MODE argument, like in `ede-source-paths'? |
| 108 | file and everything else in the project. But in more advanced | 112 | (cl-defgeneric project-external-roots (_project) |
| 109 | configurations, a project can span multiple directories. | 113 | "Return the list of external roots for PROJECT. |
| 110 | 114 | ||
| 111 | The rule of thumb for whether to include a directory here, and not | 115 | It's the list of directories outside of the project that are |
| 112 | in `project-library-roots', is whether its contents are meant to | 116 | still related to it. If the project deals with source code then, |
| 113 | be edited together with the rest of the project. | 117 | depending on the languages used, this list should include the |
| 118 | headers search path, load path, class path, and so on. | ||
| 114 | 119 | ||
| 115 | The directory names should be absolute.") | 120 | The rule of thumb for whether to include a directory here, and |
| 121 | not in `project-roots', is whether its contents are meant to be | ||
| 122 | edited together with the rest of the project." | ||
| 123 | nil) | ||
| 116 | 124 | ||
| 117 | (cl-defgeneric project-ignores (_project _dir) | 125 | (cl-defgeneric project-ignores (_project _dir) |
| 118 | "Return the list of glob patterns to ignore inside DIR. | 126 | "Return the list of glob patterns to ignore inside DIR. |
| 119 | Patterns can match both regular files and directories. | 127 | Patterns can match both regular files and directories. |
| 120 | To root an entry, start it with `./'. To match directories only, | 128 | To root an entry, start it with `./'. To match directories only, |
| 121 | end it with `/'. DIR must be one of `project-roots' or | 129 | end it with `/'. DIR must be one of `project-roots' or |
| 122 | `project-library-roots'." | 130 | `project-external-roots'." |
| 123 | (require 'grep) | 131 | (require 'grep) |
| 124 | (defvar grep-find-ignored-files) | 132 | (defvar grep-find-ignored-files) |
| 125 | (nconc | 133 | (nconc |
| @@ -133,17 +141,46 @@ end it with `/'. DIR must be one of `project-roots' or | |||
| 133 | "Project implementation using the VC package." | 141 | "Project implementation using the VC package." |
| 134 | :group 'tools) | 142 | :group 'tools) |
| 135 | 143 | ||
| 136 | (defcustom project-vc-library-roots nil | ||
| 137 | "List ot directories to include in `project-library-roots'. | ||
| 138 | The file names can be absolute, or relative to the project root." | ||
| 139 | :type '(repeat file) | ||
| 140 | :safe 'listp) | ||
| 141 | |||
| 142 | (defcustom project-vc-ignores nil | 144 | (defcustom project-vc-ignores nil |
| 143 | "List ot patterns to include in `project-ignores'." | 145 | "List ot patterns to include in `project-ignores'." |
| 144 | :type '(repeat string) | 146 | :type '(repeat string) |
| 145 | :safe 'listp) | 147 | :safe 'listp) |
| 146 | 148 | ||
| 149 | ;; FIXME: Using the current approach, major modes are supposed to set | ||
| 150 | ;; this variable to a buffer-local value. So we don't have access to | ||
| 151 | ;; the "external roots" of language A from buffers of language B, which | ||
| 152 | ;; seems desirable in multi-language projects, at least for some | ||
| 153 | ;; potential uses, like "jump to a file in project or external dirs". | ||
| 154 | ;; | ||
| 155 | ;; We could add a second argument to this function: a file extension, | ||
| 156 | ;; or a language name. Some projects will know the set of languages | ||
| 157 | ;; used in them; for others, like VC-based projects, we'll need | ||
| 158 | ;; auto-detection. I see two options: | ||
| 159 | ;; | ||
| 160 | ;; - That could be implemented as a separate second hook, with a | ||
| 161 | ;; list of functions that return file extensions. | ||
| 162 | ;; | ||
| 163 | ;; - This variable will be turned into a hook with "append" semantics, | ||
| 164 | ;; and each function in it will perform auto-detection when passed | ||
| 165 | ;; nil instead of an actual file extension. Then this hook will, in | ||
| 166 | ;; general, be modified globally, and not from major mode functions. | ||
| 167 | ;; | ||
| 168 | ;; The second option seems simpler, but the first one has the | ||
| 169 | ;; advantage that the user could override the list of languages used | ||
| 170 | ;; in a project via a directory-local variable, thus skipping | ||
| 171 | ;; languages they're not working on personally (in a big project), or | ||
| 172 | ;; working around problems in language detection (the detection logic | ||
| 173 | ;; might be imperfect for the project in question, or it might work | ||
| 174 | ;; too slowly for the user's taste). | ||
| 175 | (defvar project-vc-external-roots-function (lambda () tags-table-list) | ||
| 176 | "Function that returns a list of external roots. | ||
| 177 | |||
| 178 | It should return a list of directory roots that contain source | ||
| 179 | files related to the current buffer. | ||
| 180 | |||
| 181 | The directory names should be absolute. Used in the VC project | ||
| 182 | backend implementation of `project-external-roots'.") | ||
| 183 | |||
| 147 | (defun project-try-vc (dir) | 184 | (defun project-try-vc (dir) |
| 148 | (let* ((backend (ignore-errors (vc-responsible-backend dir))) | 185 | (let* ((backend (ignore-errors (vc-responsible-backend dir))) |
| 149 | (root (and backend (ignore-errors | 186 | (root (and backend (ignore-errors |
| @@ -153,15 +190,12 @@ The file names can be absolute, or relative to the project root." | |||
| 153 | (cl-defmethod project-roots ((project (head vc))) | 190 | (cl-defmethod project-roots ((project (head vc))) |
| 154 | (list (cdr project))) | 191 | (list (cdr project))) |
| 155 | 192 | ||
| 156 | (cl-defmethod project-library-roots ((project (head vc))) | 193 | (cl-defmethod project-external-roots ((project (head vc))) |
| 157 | (project-subtract-directories | 194 | (project-subtract-directories |
| 158 | (project-combine-directories | 195 | (project-combine-directories |
| 159 | (append | 196 | (mapcar |
| 160 | (let ((root (cdr project))) | 197 | #'file-name-as-directory |
| 161 | (mapcar | 198 | (funcall project-vc-external-roots-function))) |
| 162 | (lambda (dir) (file-name-as-directory (expand-file-name dir root))) | ||
| 163 | (project--value-in-dir 'project-vc-library-roots root))) | ||
| 164 | (funcall project-library-roots-function))) | ||
| 165 | (project-roots project))) | 199 | (project-roots project))) |
| 166 | 200 | ||
| 167 | (cl-defmethod project-ignores ((project (head vc)) dir) | 201 | (cl-defmethod project-ignores ((project (head vc)) dir) |
| @@ -217,7 +251,7 @@ DIRS must contain directory names." | |||
| 217 | 251 | ||
| 218 | ;;;###autoload | 252 | ;;;###autoload |
| 219 | (defun project-find-regexp (regexp) | 253 | (defun project-find-regexp (regexp) |
| 220 | "Find all matches for REGEXP in the current project. | 254 | "Find all matches for REGEXP in the current project's roots. |
| 221 | With \\[universal-argument] prefix, you can specify the directory | 255 | With \\[universal-argument] prefix, you can specify the directory |
| 222 | to search in, and the file name pattern to search for." | 256 | to search in, and the file name pattern to search for." |
| 223 | (interactive (list (project--read-regexp))) | 257 | (interactive (list (project--read-regexp))) |
| @@ -229,15 +263,15 @@ to search in, and the file name pattern to search for." | |||
| 229 | (project--find-regexp-in dirs regexp pr))) | 263 | (project--find-regexp-in dirs regexp pr))) |
| 230 | 264 | ||
| 231 | ;;;###autoload | 265 | ;;;###autoload |
| 232 | (defun project-or-libraries-find-regexp (regexp) | 266 | (defun project-or-external-find-regexp (regexp) |
| 233 | "Find all matches for REGEXP in the current project or libraries. | 267 | "Find all matches for REGEXP in the project roots or external roots. |
| 234 | With \\[universal-argument] prefix, you can specify the file name | 268 | With \\[universal-argument] prefix, you can specify the file name |
| 235 | pattern to search for." | 269 | pattern to search for." |
| 236 | (interactive (list (project--read-regexp))) | 270 | (interactive (list (project--read-regexp))) |
| 237 | (let* ((pr (project-current t)) | 271 | (let* ((pr (project-current t)) |
| 238 | (dirs (append | 272 | (dirs (append |
| 239 | (project-roots pr) | 273 | (project-roots pr) |
| 240 | (project-library-roots pr)))) | 274 | (project-external-roots pr)))) |
| 241 | (project--find-regexp-in dirs regexp pr))) | 275 | (project--find-regexp-in dirs regexp pr))) |
| 242 | 276 | ||
| 243 | (defun project--read-regexp () | 277 | (defun project--read-regexp () |
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 397f379d434..abb9cc6361d 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el | |||
| @@ -246,7 +246,7 @@ find a search tool; by default, this uses \"find | grep\" in the | |||
| 246 | (let ((pr (project-current t))) | 246 | (let ((pr (project-current t))) |
| 247 | (append | 247 | (append |
| 248 | (project-roots pr) | 248 | (project-roots pr) |
| 249 | (project-library-roots pr))))) | 249 | (project-external-roots pr))))) |
| 250 | 250 | ||
| 251 | (cl-defgeneric xref-backend-apropos (backend pattern) | 251 | (cl-defgeneric xref-backend-apropos (backend pattern) |
| 252 | "Find all symbols that match PATTERN. | 252 | "Find all symbols that match PATTERN. |
| @@ -886,7 +886,7 @@ IGNORES is a list of glob patterns." | |||
| 886 | hits))) | 886 | hits))) |
| 887 | (unwind-protect | 887 | (unwind-protect |
| 888 | (cl-mapcan (lambda (hit) (xref--collect-matches hit regexp)) | 888 | (cl-mapcan (lambda (hit) (xref--collect-matches hit regexp)) |
| 889 | (nreverse hits)) | 889 | hits) |
| 890 | ;; TODO: Same as above. | 890 | ;; TODO: Same as above. |
| 891 | (mapc #'kill-buffer | 891 | (mapc #'kill-buffer |
| 892 | (cl-set-difference (buffer-list) orig-buffers))))) | 892 | (cl-set-difference (buffer-list) orig-buffers))))) |