Add project-find-file and project-or-external-find-file
* lisp/minibuffer.el (completion-category-defaults): Add `project-file' category. * lisp/progmodes/project.el (project-find-file) (project-or-external-find-file): New commands. (project--find-file-in): New private function. * lisp/progmodes/xref.el (xref-collect-matches): Use `expand-file-name' on DIR, to expand the tildes. (xref--find-ignores-arguments): Extract from `xref--rgrep-command'.
This commit is contained in:
parent
056da45d2c
commit
ed41d117a4
3 changed files with 71 additions and 23 deletions
|
@ -831,7 +831,8 @@ styles for specific categories, such as files, buffers, etc."
|
|||
|
||||
(defvar completion-category-defaults
|
||||
'((buffer (styles . (basic substring)))
|
||||
(unicode-name (styles . (basic substring))))
|
||||
(unicode-name (styles . (basic substring)))
|
||||
(project-file (styles . (basic substring))))
|
||||
"Default settings for specific completion categories.
|
||||
Each entry has the shape (CATEGORY . ALIST) where ALIST is
|
||||
an association list that can specify properties such as:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -876,7 +876,9 @@ IGNORES is a list of glob patterns."
|
|||
grep-find-template t t))
|
||||
(grep-highlight-matches nil)
|
||||
(command (xref--rgrep-command (xref--regexp-to-extended regexp)
|
||||
files dir ignores))
|
||||
files
|
||||
(expand-file-name dir)
|
||||
ignores))
|
||||
(orig-buffers (buffer-list))
|
||||
(buf (get-buffer-create " *xref-grep*"))
|
||||
(grep-re (caar grep-regexp-alist))
|
||||
|
@ -912,23 +914,28 @@ IGNORES is a list of glob patterns."
|
|||
" "
|
||||
(shell-quote-argument ")"))
|
||||
dir
|
||||
(concat
|
||||
(shell-quote-argument "(")
|
||||
" -path "
|
||||
(mapconcat
|
||||
(lambda (ignore)
|
||||
(when (string-match-p "/\\'" ignore)
|
||||
(setq ignore (concat ignore "*")))
|
||||
(if (string-match "\\`\\./" ignore)
|
||||
(setq ignore (replace-match dir t t ignore))
|
||||
(unless (string-prefix-p "*" ignore)
|
||||
(setq ignore (concat "*/" ignore))))
|
||||
(shell-quote-argument ignore))
|
||||
ignores
|
||||
" -o -path ")
|
||||
" "
|
||||
(shell-quote-argument ")")
|
||||
" -prune -o ")))
|
||||
(xref--find-ignores-arguments ignores dir)))
|
||||
|
||||
(defun xref--find-ignores-arguments (ignores dir)
|
||||
;; `shell-quote-argument' quotes the tilde as well.
|
||||
(cl-assert (not (string-match-p "\\`~" dir)))
|
||||
(concat
|
||||
(shell-quote-argument "(")
|
||||
" -path "
|
||||
(mapconcat
|
||||
(lambda (ignore)
|
||||
(when (string-match-p "/\\'" ignore)
|
||||
(setq ignore (concat ignore "*")))
|
||||
(if (string-match "\\`\\./" ignore)
|
||||
(setq ignore (replace-match dir t t ignore))
|
||||
(unless (string-prefix-p "*" ignore)
|
||||
(setq ignore (concat "*/" ignore))))
|
||||
(shell-quote-argument ignore))
|
||||
ignores
|
||||
" -o -path ")
|
||||
" "
|
||||
(shell-quote-argument ")")
|
||||
" -prune -o "))
|
||||
|
||||
(defun xref--regexp-to-extended (str)
|
||||
(replace-regexp-in-string
|
||||
|
|
Loading…
Add table
Reference in a new issue