diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 85f3907..becccbb 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -154,6 +154,15 @@ project--find-in-directory vc-directory-exclusion-list) grep-find-ignored-files)) +(cl-defgeneric project--find-file-in (filename dirs project) + "Complete FILENAME (a string or nil) in directories DIRS; visit the file. +If non-nil, DIRS is a list of absolute directories; it should be some +subset of the project roots and external roots. If nil, the backend +uses all the directories it knows about. +PROJECT is used to find the project ignores and other project meta-data." + ;; dispatch on PROJECT + ) + (defgroup project-vc nil "Project implementation using the VC package." :version "25.1" @@ -312,31 +321,34 @@ project--find-regexp-in (xref--show-xrefs xrefs nil))) ;;;###autoload -(defun project-find-file () - "Visit a file in the current project's roots. - -This is like `find-file', but it limits the file-name completion -candidates to the files within the current project roots." - (interactive) +(defun project-find-file (filename) + "Visit FILENAME in the current project's roots. +FILENAME defaults to the filename at point (nil if none +recognized). +FILENAME is completed with the files within the current project +roots." + (interactive (list (when current-prefix-arg (thing-at-point 'filename)))) (let* ((pr (project-current t)) (dirs (project-roots pr))) - (project--find-file-in dirs pr))) + (project--find-file-in filename dirs pr))) ;;;###autoload -(defun project-or-external-find-file () - "Visit a file in the current project's roots or external roots. - -This is like `find-file', but it limits the file-name completion -candidates to the files within the current project roots and external roots." - (interactive) +(defun project-or-external-find-file (filename) + "Visit FILENAME in the current project's roots or external roots. +FILENAME defaults to the filename at point (nil if none +recognized). +FILENAME is completed with the files within the current project +roots and external roots." + (interactive (list (when current-prefix-arg (thing-at-point 'filename)))) (let* ((pr (project-current t)) (dirs (append (project-roots pr) (project-external-roots pr)))) - (project--find-file-in dirs pr))) + (project--find-file-in filename dirs pr))) -;; FIXME: Uniquely abbreviate the roots? -(defun project--find-file-in (dirs project) + ;; FIXME: Uniquely abbreviate the roots? +(cl-defmethod project--find-file-in (filename dirs project) + "Default implementation using `find-program'." (require 'xref) (let* ((all-files (cl-mapcan @@ -357,7 +369,7 @@ project--find-file-in (t (complete-with-action action all-files string pred)))))) (find-file - (completing-read "Find file: " table nil t)))) + (completing-read "Find file: " table nil t filename)))) (provide 'project) ;;; project.el ends here diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 267853d..ad7d6bb 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -948,6 +948,9 @@ xref--rgrep-command (xref--find-ignores-arguments ignores dir))) (defun xref--find-ignores-arguments (ignores dir) + "Convert IGNORES and DIR to a list of arguments for 'find'. +IGNORES is a list of glob patterns. DIR is an absolute +directory, used as the root of the ignore globs." ;; `shell-quote-argument' quotes the tilde as well. (cl-assert (not (string-match-p "\\`~" dir))) (when ignores