aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Gutov2016-01-30 07:21:31 +0300
committerDmitry Gutov2016-01-30 07:21:31 +0300
commit2b87dea0b8ccbfe4faf13a8f2d6c955c2756e161 (patch)
tree1dc4b3cdf66b764a53bf8e0c3408d7229fb98178
parent06083cf41c473404d246de9b91a0116f38c5485f (diff)
downloademacs-2b87dea0b8ccbfe4faf13a8f2d6c955c2756e161.tar.gz
emacs-2b87dea0b8ccbfe4faf13a8f2d6c955c2756e161.zip
Improve project-find-file yet again!
* lisp/progmodes/project.el (project--completing-read-strict): New function. (project-find-file-in): Use it. (project-file-completion-table): Move the default implementation inside the cl-defgeneric form. (http://lists.gnu.org/archive/html/emacs-devel/2016-01/msg01720.html)
-rw-r--r--lisp/progmodes/project.el87
1 files changed, 51 insertions, 36 deletions
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 2cc76aa6af7..0b05de29089 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -154,12 +154,33 @@ end it with `/'. DIR must be one of `project-roots' or
154 vc-directory-exclusion-list) 154 vc-directory-exclusion-list)
155 grep-find-ignored-files)) 155 grep-find-ignored-files))
156 156
157(cl-defgeneric project-file-completion-table (_project _dirs) 157(cl-defgeneric project-file-completion-table (project dirs)
158 "Return a completion table for files in directories DIRS in PROJECT. 158 "Return a completion table for files in directories DIRS in PROJECT.
159DIRS is a list of absolute directories; it should be some 159DIRS is a list of absolute directories; it should be some
160subset of the project roots and external roots. 160subset of the project roots and external roots.
161PROJECT is used to find the project ignores and other project meta-data." 161
162 ) 162The default implementation uses `find-program'. PROJECT is used
163to find the list of ignores for each directory."
164 ;; FIXME: Uniquely abbreviate the roots?
165 (require 'xref)
166 (let ((all-files
167 (cl-mapcan
168 (lambda (dir)
169 (let ((command
170 (format "%s %s %s -type f -print0"
171 find-program
172 dir
173 (xref--find-ignores-arguments
174 (project-ignores project dir)
175 (expand-file-name dir)))))
176 (split-string (shell-command-to-string command) "\0" t)))
177 dirs)))
178 (lambda (string pred action)
179 (cond
180 ((eq action 'metadata)
181 '(metadata . ((category . project-file))))
182 (t
183 (complete-with-action action all-files string pred))))))
163 184
164(defgroup project-vc nil 185(defgroup project-vc nil
165 "Project implementation using the VC package." 186 "Project implementation using the VC package."
@@ -340,40 +361,34 @@ recognized."
340 (project-external-roots pr)))) 361 (project-external-roots pr))))
341 (project-find-file-in (thing-at-point 'filename) dirs pr))) 362 (project-find-file-in (thing-at-point 'filename) dirs pr)))
342 363
343;; FIXME: Uniquely abbreviate the roots?
344(cl-defmethod project-file-completion-table (project dirs)
345 "Default implementation using `find-program'."
346 (require 'xref)
347 (let ((all-files
348 (cl-mapcan
349 (lambda (dir)
350 (let ((command
351 (format "%s %s %s -type f -print0"
352 find-program
353 dir
354 (xref--find-ignores-arguments
355 (project-ignores project dir)
356 (expand-file-name dir)))))
357 (split-string (shell-command-to-string command) "\0" t)))
358 dirs)))
359 (lambda (string pred action)
360 (cond
361 ((eq action 'metadata)
362 '(metadata . ((category . project-file))))
363 (t
364 (complete-with-action action all-files string pred))))
365 ))
366
367(defun project-find-file-in (filename dirs project) 364(defun project-find-file-in (filename dirs project)
368 "Complete FILENAME in DIRS in PROJECT, visit the file." 365 "Complete FILENAME in DIRS in PROJECT and visit the result."
369 ;; FIXME: verify that filename is accepted by the completion table 366 (let* ((table (project-file-completion-table project dirs))
370 (find-file 367 (file (project--completing-read-strict
371 (completing-read 368 "Find file" table nil nil
372 (if filename 369 filename)))
373 (format "Find file (%s): " filename) 370 (if (string= file "")
374 "Find file: ") 371 (user-error "You didn't specify the file")
375 (project-file-completion-table project dirs) 372 (find-file file))))
376 nil t nil nil filename))) 373
374(defun project--completing-read-strict (prompt
375 collection &optional predicate
376 hist default inherit-input-method)
377 (when (and default (not (test-completion default collection predicate)))
378 (setq default (car (completion-try-completion
379 default collection predicate (length default)))))
380 (let* ((new-prompt (if default
381 (format "%s (default %s): " prompt default)
382 (format "%s: " prompt)))
383 (res (completing-read new-prompt
384 collection predicate t
385 nil hist default inherit-input-method)))
386 (if (and (equal res default)
387 (not (test-completion res collection predicate)))
388 (completing-read (format "%s: " prompt)
389 collection predicate t res hist nil
390 inherit-input-method)
391 res)))
377 392
378(provide 'project) 393(provide 'project)
379;;; project.el ends here 394;;; project.el ends here