aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Gutov2015-12-28 06:17:19 +0200
committerDmitry Gutov2015-12-28 06:17:37 +0200
commit17ab0d10e1db9cc4924ceb778e5c4e6bb9a90c3d (patch)
tree51c363d5a5c43ac10526b4ca715a097788291099
parenta36c88806dcfc993e6af83b0d0f44b077293bc30 (diff)
downloademacs-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.el8
-rw-r--r--lisp/progmodes/etags.el3
-rw-r--r--lisp/progmodes/project.el178
-rw-r--r--lisp/progmodes/xref.el4
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
38argument (the directory) and should return either nil to mean 80argument (the directory) and should return either nil to mean
39that it is not applicable, or a project instance.") 81that 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
62It should return a list of directories that contain source files
63related to the current buffer. Depending on the language, it
64should include the headers search path, load path, class path,
65and so on.
66
67The directory names should be absolute. Used in the default
68implementation 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
93It's the list of directories outside of the project that contain
94related source files.
95 104
96Project-specific version of `project-library-roots-function', 105Most often it's just one directory which contains the project
97which see. Unless it knows better, a specialized implementation 106build file and everything else in the project. But in more
98should use the value returned by that function." 107advanced 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) 109The directory names should be absolute.")
105 "Return the list of directory roots belonging to the current project.
106 110
107Most often it's just one directory, which contains the project 111;; FIXME: Add MODE argument, like in `ede-source-paths'?
108file and everything else in the project. But in more advanced 112(cl-defgeneric project-external-roots (_project)
109configurations, a project can span multiple directories. 113 "Return the list of external roots for PROJECT.
110 114
111The rule of thumb for whether to include a directory here, and not 115It's the list of directories outside of the project that are
112in `project-library-roots', is whether its contents are meant to 116still related to it. If the project deals with source code then,
113be edited together with the rest of the project. 117depending on the languages used, this list should include the
118headers search path, load path, class path, and so on.
114 119
115The directory names should be absolute.") 120The rule of thumb for whether to include a directory here, and
121not in `project-roots', is whether its contents are meant to be
122edited 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.
119Patterns can match both regular files and directories. 127Patterns can match both regular files and directories.
120To root an entry, start it with `./'. To match directories only, 128To root an entry, start it with `./'. To match directories only,
121end it with `/'. DIR must be one of `project-roots' or 129end 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'.
138The 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
178It should return a list of directory roots that contain source
179files related to the current buffer.
180
181The directory names should be absolute. Used in the VC project
182backend 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.
221With \\[universal-argument] prefix, you can specify the directory 255With \\[universal-argument] prefix, you can specify the directory
222to search in, and the file name pattern to search for." 256to 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.
234With \\[universal-argument] prefix, you can specify the file name 268With \\[universal-argument] prefix, you can specify the file name
235pattern to search for." 269pattern 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)))))