aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Gutov2020-05-23 04:38:27 +0300
committerDmitry Gutov2020-05-23 04:54:42 +0300
commit5044c19001fe608f2eac621add2e05cbca6c804b (patch)
tree386c9c390c0ee739fc8584b9c297505fd56c46df
parent813e42c63bcd9f285daae6737c4ae7a9adae90d7 (diff)
downloademacs-5044c19001fe608f2eac621add2e05cbca6c804b.tar.gz
emacs-5044c19001fe608f2eac621add2e05cbca6c804b.zip
project.el: A project has only one main root now
Practice shows that the vast majority of projects only use one main root. The users of this API very often make this assumption as well. The rest of the "roots" should be possible to express through project-external-roots. * lisp/progmodes/project.el: Update the commentary. Only 4 non-obsolete generics now. (project-root): Replacement for `project-roots'. All callers updated. Implementations too. (project-roots): Declare obsolete. (project-external-roots): Simplify the docstring. (project-ignores): Update the docstring. (project-find-regexp): Omit the second arg to project-files. (project--dir-ignores): Simplify. (project-compile): Simplify, remove outdated comment. * lisp/cedet/ede.el: Add a FIXME.
-rw-r--r--lisp/cedet/ede.el7
-rw-r--r--lisp/progmodes/project.el78
-rw-r--r--lisp/progmodes/xref.el4
3 files changed, 48 insertions, 41 deletions
diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el
index 8c336117c92..41252815734 100644
--- a/lisp/cedet/ede.el
+++ b/lisp/cedet/ede.el
@@ -1515,8 +1515,11 @@ It does not apply the value to buffers."
1515 (when project-dir 1515 (when project-dir
1516 (ede-directory-get-open-project project-dir 'ROOT)))) 1516 (ede-directory-get-open-project project-dir 'ROOT))))
1517 1517
1518(cl-defmethod project-roots ((project ede-project)) 1518(cl-defmethod project-root ((project ede-project))
1519 (list (ede-project-root-directory project))) 1519 (ede-project-root-directory project))
1520
1521;;; FIXME: Could someone look into implementing `project-ignores' for
1522;;; EDE and/or a faster `project-files'?
1520 1523
1521(add-hook 'project-find-functions #'project-try-ede) 1524(add-hook 'project-find-functions #'project-try-ede)
1522 1525
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 41e34a37507..c72e9d94b1c 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -40,7 +40,7 @@
40;; Infrastructure: 40;; Infrastructure:
41;; 41;;
42;; Function `project-current', to determine the current project 42;; Function `project-current', to determine the current project
43;; instance, and 5 (at the moment) generic functions that act on it. 43;; instance, and 4 (at the moment) generic functions that act on it.
44;; This list is to be extended in future versions. 44;; This list is to be extended in future versions.
45;; 45;;
46;; Utils: 46;; Utils:
@@ -122,14 +122,25 @@ is not a part of a detectable project either, return a
122(defun project--find-in-directory (dir) 122(defun project--find-in-directory (dir)
123 (run-hook-with-args-until-success 'project-find-functions dir)) 123 (run-hook-with-args-until-success 'project-find-functions dir))
124 124
125(cl-defgeneric project-roots (project) 125(cl-defgeneric project-root (project)
126 "Return the list of directory roots of the current project. 126 "Return root directory of the current project.
127
128It usually contains the main build file, dependencies
129configuration file, etc. Though neither is mandatory.
130
131The directory name must be absolute."
132 (car (project-roots project)))
127 133
128Most often it's just one directory which contains the project 134(cl-defgeneric project-roots (project)
129build file and everything else in the project. But in more 135 "Return the list containing the current project root.
130advanced configurations, a project can span multiple directories.
131 136
132The directory names should be absolute.") 137The function is obsolete, all projects have one main root anyway,
138and the rest should be possible to express through
139`project-external-roots'."
140 ;; FIXME: Can we specify project's version here?
141 ;; FIXME: Could we make this affect cl-defmethod calls too?
142 (declare (obsolete project-root "0.3.0"))
143 (list (project-root project)))
133 144
134;; FIXME: Add MODE argument, like in `ede-source-paths'? 145;; FIXME: Add MODE argument, like in `ede-source-paths'?
135(cl-defgeneric project-external-roots (_project) 146(cl-defgeneric project-external-roots (_project)
@@ -138,18 +149,14 @@ The directory names should be absolute.")
138It's the list of directories outside of the project that are 149It's the list of directories outside of the project that are
139still related to it. If the project deals with source code then, 150still related to it. If the project deals with source code then,
140depending on the languages used, this list should include the 151depending on the languages used, this list should include the
141headers search path, load path, class path, and so on. 152headers search path, load path, class path, and so on."
142
143The rule of thumb for whether to include a directory here, and
144not in `project-roots', is whether its contents are meant to be
145edited together with the rest of the project."
146 nil) 153 nil)
147 154
148(cl-defgeneric project-ignores (_project _dir) 155(cl-defgeneric project-ignores (_project _dir)
149 "Return the list of glob patterns to ignore inside DIR. 156 "Return the list of glob patterns to ignore inside DIR.
150Patterns can match both regular files and directories. 157Patterns can match both regular files and directories.
151To root an entry, start it with `./'. To match directories only, 158To root an entry, start it with `./'. To match directories only,
152end it with `/'. DIR must be one of `project-roots' or 159end it with `/'. DIR must be either `project-root' or one of
153`project-external-roots'." 160`project-external-roots'."
154 ;; TODO: Document and support regexp ignores as used by Hg. 161 ;; TODO: Document and support regexp ignores as used by Hg.
155 ;; TODO: Support whitelist entries. 162 ;; TODO: Support whitelist entries.
@@ -170,13 +177,13 @@ end it with `/'. DIR must be one of `project-roots' or
170 (t 177 (t
171 (complete-with-action action all-files string pred))))) 178 (complete-with-action action all-files string pred)))))
172 179
173(cl-defmethod project-roots ((project (head transient))) 180(cl-defmethod project-root ((project (head transient)))
174 (list (cdr project))) 181 (cdr project))
175 182
176(cl-defgeneric project-files (project &optional dirs) 183(cl-defgeneric project-files (project &optional dirs)
177 "Return a list of files in directories DIRS in PROJECT. 184 "Return a list of files in directories DIRS in PROJECT.
178DIRS is a list of absolute directories; it should be some 185DIRS is a list of absolute directories; it should be some
179subset of the project roots and external roots. 186subset of the project root and external roots.
180 187
181The default implementation uses `find-program'. PROJECT is used 188The default implementation uses `find-program'. PROJECT is used
182to find the list of ignores for each directory." 189to find the list of ignores for each directory."
@@ -184,7 +191,8 @@ to find the list of ignores for each directory."
184 (lambda (dir) 191 (lambda (dir)
185 (project--files-in-directory dir 192 (project--files-in-directory dir
186 (project--dir-ignores project dir))) 193 (project--dir-ignores project dir)))
187 (or dirs (project-roots project)))) 194 (or dirs
195 (list (project-root project)))))
188 196
189(defun project--files-in-directory (dir ignores &optional files) 197(defun project--files-in-directory (dir ignores &optional files)
190 (require 'find-dired) 198 (require 'find-dired)
@@ -322,8 +330,8 @@ backend implementation of `project-external-roots'.")
322 t) 330 t)
323 (t nil)))) 331 (t nil))))
324 332
325(cl-defmethod project-roots ((project (head vc))) 333(cl-defmethod project-root ((project (head vc)))
326 (list (cdr project))) 334 (cdr project))
327 335
328(cl-defmethod project-external-roots ((project (head vc))) 336(cl-defmethod project-external-roots ((project (head vc)))
329 (project-subtract-directories 337 (project-subtract-directories
@@ -331,7 +339,7 @@ backend implementation of `project-external-roots'.")
331 (mapcar 339 (mapcar
332 #'file-name-as-directory 340 #'file-name-as-directory
333 (funcall project-vc-external-roots-function))) 341 (funcall project-vc-external-roots-function)))
334 (project-roots project))) 342 (list (project-root project))))
335 343
336(cl-defmethod project-files ((project (head vc)) &optional dirs) 344(cl-defmethod project-files ((project (head vc)) &optional dirs)
337 (cl-mapcan 345 (cl-mapcan
@@ -349,7 +357,8 @@ backend implementation of `project-external-roots'.")
349 (project--files-in-directory 357 (project--files-in-directory
350 dir 358 dir
351 (project--dir-ignores project dir))))) 359 (project--dir-ignores project dir)))))
352 (or dirs (project-roots project)))) 360 (or dirs
361 (list (project-root project)))))
353 362
354(declare-function vc-git--program-version "vc-git") 363(declare-function vc-git--program-version "vc-git")
355(declare-function vc-git--run-command-string "vc-git") 364(declare-function vc-git--run-command-string "vc-git")
@@ -492,7 +501,7 @@ requires quoting, e.g. `\\[quoted-insert]<space>'."
492 (let* ((pr (project-current t)) 501 (let* ((pr (project-current t))
493 (files 502 (files
494 (if (not current-prefix-arg) 503 (if (not current-prefix-arg)
495 (project-files pr (project-roots pr)) 504 (project-files pr)
496 (let ((dir (read-directory-name "Base directory: " 505 (let ((dir (read-directory-name "Base directory: "
497 nil default-directory t))) 506 nil default-directory t)))
498 (project--files-in-directory dir 507 (project--files-in-directory dir
@@ -503,9 +512,8 @@ requires quoting, e.g. `\\[quoted-insert]<space>'."
503 nil))) 512 nil)))
504 513
505(defun project--dir-ignores (project dir) 514(defun project--dir-ignores (project dir)
506 (let* ((roots (project-roots project)) 515 (let ((root (project-root project)))
507 (root (cl-find dir roots :test #'file-in-directory-p))) 516 (if (not (file-in-directory-p dir root))
508 (if (not root)
509 (project-ignores nil nil) ;The defaults. 517 (project-ignores nil nil) ;The defaults.
510 (let ((ignores (project-ignores project root))) 518 (let ((ignores (project-ignores project root)))
511 (if (file-equal-p root dir) 519 (if (file-equal-p root dir)
@@ -523,8 +531,8 @@ pattern to search for."
523 (require 'xref) 531 (require 'xref)
524 (let* ((pr (project-current t)) 532 (let* ((pr (project-current t))
525 (files 533 (files
526 (project-files pr (append 534 (project-files pr (cons
527 (project-roots pr) 535 (project-root pr)
528 (project-external-roots pr))))) 536 (project-external-roots pr)))))
529 (xref--show-xrefs 537 (xref--show-xrefs
530 (apply-partially #'project--find-regexp-in-files regexp files) 538 (apply-partially #'project--find-regexp-in-files regexp files)
@@ -562,23 +570,23 @@ pattern to search for."
562 570
563;;;###autoload 571;;;###autoload
564(defun project-find-file () 572(defun project-find-file ()
565 "Visit a file (with completion) in the current project's roots. 573 "Visit a file (with completion) in the current project.
566The completion default is the filename at point, if one is 574The completion default is the filename at point, if one is
567recognized." 575recognized."
568 (interactive) 576 (interactive)
569 (let* ((pr (project-current t)) 577 (let* ((pr (project-current t))
570 (dirs (project-roots pr))) 578 (dirs (list (project-root pr))))
571 (project-find-file-in (thing-at-point 'filename) dirs pr))) 579 (project-find-file-in (thing-at-point 'filename) dirs pr)))
572 580
573;;;###autoload 581;;;###autoload
574(defun project-or-external-find-file () 582(defun project-or-external-find-file ()
575 "Visit a file (with completion) in the current project's roots or external roots. 583 "Visit a file (with completion) in the current project or external roots.
576The completion default is the filename at point, if one is 584The completion default is the filename at point, if one is
577recognized." 585recognized."
578 (interactive) 586 (interactive)
579 (let* ((pr (project-current t)) 587 (let* ((pr (project-current t))
580 (dirs (append 588 (dirs (cons
581 (project-roots pr) 589 (project-root pr)
582 (project-external-roots pr)))) 590 (project-external-roots pr))))
583 (project-find-file-in (thing-at-point 'filename) dirs pr))) 591 (project-find-file-in (thing-at-point 'filename) dirs pr)))
584 592
@@ -686,11 +694,7 @@ loop using the command \\[fileloop-continue]."
686 "Run `compile' in the project root." 694 "Run `compile' in the project root."
687 (interactive) 695 (interactive)
688 (let* ((pr (project-current t)) 696 (let* ((pr (project-current t))
689 (roots (project-roots pr)) 697 (default-directory (project-root pr)))
690 ;; TODO: be more intelligent when choosing a directory. This
691 ;; currently isn't a priority, since no `project-roots'
692 ;; implementation returns more that one directory.
693 (default-directory (car roots)))
694 (call-interactively 'compile))) 698 (call-interactively 'compile)))
695 699
696(provide 'project) 700(provide 'project)
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 7d1ee705b80..2477884f1ab 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -268,8 +268,8 @@ find a search tool; by default, this uses \"find | grep\" in the
268 (lambda (dir) 268 (lambda (dir)
269 (xref-references-in-directory identifier dir)) 269 (xref-references-in-directory identifier dir))
270 (let ((pr (project-current t))) 270 (let ((pr (project-current t)))
271 (append 271 (cons
272 (project-roots pr) 272 (project-root pr)
273 (project-external-roots pr))))) 273 (project-external-roots pr)))))
274 274
275(cl-defgeneric xref-backend-apropos (backend pattern) 275(cl-defgeneric xref-backend-apropos (backend pattern)