]> code.delx.au - gnu-emacs/commitdiff
Add project-find-file and project-or-external-find-file
authorDmitry Gutov <dgutov@yandex.ru>
Thu, 7 Jan 2016 17:14:40 +0000 (20:14 +0300)
committerDmitry Gutov <dgutov@yandex.ru>
Thu, 7 Jan 2016 17:56:09 +0000 (20:56 +0300)
* 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
lisp/progmodes/project.el
lisp/progmodes/xref.el

index 1251a4e1107b5aaecfaeb6c7ea6ebd14b699e095..ecac0aeb1352f9b2099fa01d4f720ae5f22cb705 100644 (file)
@@ -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:
index d77158761eb21c8a349b9b008e59381cc329962a..2e3222f55dc4f1cb6e8e22842f2f5f66fdadc424 100644 (file)
 
 ;;; 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
index ae5ec61520dd28f0708b10db7523355e5f3a46cd..597001158799d2e78af61213a29c2a9fd7790d48 100644 (file)
@@ -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