[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] project-next 9776972 1/3: Rename "search path" to "library
From: |
Dmitry Gutov |
Subject: |
[Emacs-diffs] project-next 9776972 1/3: Rename "search path" to "library roots" |
Date: |
Sun, 08 Nov 2015 01:41:04 +0000 |
branch: project-next
commit 977697203f7f063b2f26a9f25bff933e6c939765
Author: Dmitry Gutov <address@hidden>
Commit: Dmitry Gutov <address@hidden>
Rename "search path" to "library roots"
* lisp/emacs-lisp/cl-seq.el (cl-set-difference): Retain the order
of the elements from CL-LIST1.
* test/automated/cl-lib-tests.el (cl-lib-test-set-functions):
Update WRT to the above change.
* lisp/progmodes/project.el (project-search-path-function): Rename
to project-library-roots-function, update the documentation and
references.
(project-search-path): Likewise, to project-library-roots.
(project-roots): Clarify documentation.
(project-vc-search-path): Likewise, to project-vc-library-roots.
(project-library-roots): In addition to the renames, thread the
results through file-name-as-directory.
(project-prune-directories): Accept a variable number of
arguments. Rename to project-combine-directories.
(project-subtract-directories): New function.
* lisp/progmodes/elisp-mode.el (elisp--xref-find-references):
Append project-roots and project-library-roots together.
* lisp/progmodes/etags.el (etags--xref-find-references): Ditto.
---
lisp/emacs-lisp/cl-seq.el | 2 +-
lisp/progmodes/elisp-mode.el | 13 +++--
lisp/progmodes/etags.el | 7 ++-
lisp/progmodes/project.el | 109 +++++++++++++++++++++++++---------------
lisp/progmodes/xref.el | 7 +--
test/automated/cl-lib-tests.el | 8 ++--
6 files changed, 89 insertions(+), 57 deletions(-)
diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el
index 3aea67a..5f0f088 100644
--- a/lisp/emacs-lisp/cl-seq.el
+++ b/lisp/emacs-lisp/cl-seq.el
@@ -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)
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index bdc304e..298c7a7 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -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)))
+ (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))
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index 0d5fc3a..2d7537a 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -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)))
+ (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))
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 186840a..ba83120 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -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.
@@ -38,19 +38,33 @@ 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" ())
-
-(defvar project-search-path-function #'etags-search-path
- "Function that returns a list of source root directories.
+;; 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.
-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.
+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. 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)
@@ -59,35 +73,39 @@ implementation of `project-search-path'.")
(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)
+(cl-defgeneric project-library-roots (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.
-
-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 current 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 +119,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,12 +139,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-search-path ((project (head vc)))
+(cl-defmethod project-library-roots ((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)))
+ (lambda (dir) (file-name-as-directory (expand-file-name dir root)))
+ (project--value-in-dir 'project-vc-library-roots root)))
(cl-call-next-method)))
(cl-defmethod project-ignores ((project (head vc)) dir)
@@ -150,13 +168,16 @@ The file names can be absolute, or relative to the
project root."
(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,6 +187,12 @@ 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."
+ (cl-set-difference files dirs
+ :test (lambda (file dir) (string-prefix-p dir file))))
+
(defun project--value-in-dir (var dir)
(with-temp-buffer
(setq default-directory dir)
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index a222533..360d1ba 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -802,10 +802,9 @@ to search in, and the file name pattern to search for."
(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)))))
+ (append
+ (project-roots proj)
+ (project-library-roots proj))))
(xref-find-function
(lambda (_kind regexp)
(cl-mapcan
diff --git a/test/automated/cl-lib-tests.el b/test/automated/cl-lib-tests.el
index 1bdc6d7..d6e6bef 100644
--- a/test/automated/cl-lib-tests.el
+++ b/test/automated/cl-lib-tests.el
@@ -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))