emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] emacs-25 ed41d11: Add project-find-file and project-or-ext


From: Dmitry Gutov
Subject: [Emacs-diffs] emacs-25 ed41d11: Add project-find-file and project-or-external-find-file
Date: Thu, 07 Jan 2016 17:57:09 +0000

branch: emacs-25
commit ed41d117a434abd28df4585663c2311c87160d1c
Author: Dmitry Gutov <address@hidden>
Commit: Dmitry Gutov <address@hidden>

    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'.
---
 lisp/minibuffer.el        |    3 +-
 lisp/progmodes/project.el |   48 +++++++++++++++++++++++++++++++++++++++++---
 lisp/progmodes/xref.el    |   43 +++++++++++++++++++++++----------------
 3 files changed, 71 insertions(+), 23 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 1251a4e..ecac0ae 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -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:
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index d771587..2e3222f 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
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index ae5ec61..5970011 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]