diff options
Diffstat (limited to 'lisp/progmodes/project.el')
-rw-r--r-- | lisp/progmodes/project.el | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index d77158761eb..2e3222f55dc 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -45,10 +45,12 @@ ;;; TODO: -;; * Commands `project-find-file' and `project-or-external-find-file'. -;; Currently blocked on adding a new completion style that would let -;; the user enter just the base file name (or a part of it), and get -;; it expanded to the absolute file name. +;; * Reliably cache the list of files in the project, probably using +;; filenotify.el (if supported) to invalidate. And avoiding caching +;; if it's not available (manual cache invalidation is not nice). +;; +;; * Allow the backend to override the file-listing logic? Maybe also +;; to delegate file name completion to an external tool. ;; ;; * Build tool related functionality. Start with a `project-build' ;; command, which should provide completions on tasks to run, and @@ -258,6 +260,7 @@ DIRS must contain directory names." (declare-function xref-collect-matches "xref") (declare-function xref--show-xrefs "xref") (declare-function xref-backend-identifier-at-point "xref") +(declare-function xref--find-ignores-arguments "xref") ;;;###autoload (defun project-find-regexp (regexp) @@ -302,5 +305,42 @@ pattern to search for." (user-error "No matches for: %s" regexp)) (xref--show-xrefs xrefs nil))) +(defun project-find-file () + (interactive) + (let* ((pr (project-current t)) + (dirs (project-roots pr))) + (project--find-file-in dirs pr))) + +(defun project-or-external-find-file () + (interactive) + (let* ((pr (project-current t)) + (dirs (append + (project-roots pr) + (project-external-roots pr)))) + (project--find-file-in dirs pr))) + +;; FIXME: Uniquely abbreviate the roots? +(defun project--find-file-in (dirs project) + (let* ((all-files + (cl-mapcan + (lambda (dir) + (let ((command + (format "%s %s %s -type f -print0" + find-program + dir + (xref--find-ignores-arguments + (project-ignores project dir) + (expand-file-name dir))))) + (split-string (shell-command-to-string command) "\0" t))) + dirs)) + (table (lambda (string pred action) + (cond + ((eq action 'metadata) + '(metadata . ((category . project-file)))) + (t + (complete-with-action action all-files string pred)))))) + (find-file + (completing-read "Find file: " table nil t)))) + (provide 'project) ;;; project.el ends here |