summaryrefslogtreecommitdiff
path: root/lisp/progmodes/xref.el
diff options
context:
space:
mode:
authorDmitry Gutov <dgutov@yandex.ru>2019-12-29 15:11:53 +0300
committerDmitry Gutov <dgutov@yandex.ru>2019-12-29 15:46:44 +0300
commit43f66c33684a11304c2e6b09003289fb46ae5d68 (patch)
tree6b60f0581ec4968ffaafb78c292d03be94d07418 /lisp/progmodes/xref.el
parent65af18d86eed140100c98c1bf3076f805f2bcc06 (diff)
downloademacs-43f66c33684a11304c2e6b09003289fb46ae5d68.tar.gz
emacs-43f66c33684a11304c2e6b09003289fb46ae5d68.tar.bz2
emacs-43f66c33684a11304c2e6b09003289fb46ae5d68.zip
Extract xref-matches-in-files from project--find-regexp-in-files
* lisp/progmodes/xref.el (xref-matches-in-files): Extract from project--find-regexp-in-files. * lisp/dired-aux.el (dired-do-find-regexp): Also use it here.
Diffstat (limited to 'lisp/progmodes/xref.el')
-rw-r--r--lisp/progmodes/xref.el50
1 files changed, 50 insertions, 0 deletions
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 9f010eb83bf..3b1b49674fa 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -1217,6 +1217,56 @@ IGNORES is a list of glob patterns for files to ignore."
#'xref-matches-in-directory
"27.1")
+;;;###autoload
+(defun xref-matches-in-files (regexp files)
+ "Find all matches for REGEXP in FILES.
+Return a list of xref values.
+FILES must be a list of absolute file names."
+ (pcase-let*
+ ((output (get-buffer-create " *project grep output*"))
+ (`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist))
+ (status nil)
+ (hits nil)
+ ;; Support for remote files. The assumption is that, if the
+ ;; first file is remote, they all are, and on the same host.
+ (dir (file-name-directory (car files)))
+ (remote-id (file-remote-p dir))
+ ;; 'git ls-files' can output broken symlinks.
+ (command (format "xargs -0 grep %s -snHE -e %s"
+ (if (and case-fold-search
+ (isearch-no-upper-case-p regexp t))
+ "-i"
+ "")
+ (shell-quote-argument (xref--regexp-to-extended regexp)))))
+ (when remote-id
+ (setq files (mapcar #'file-local-name files)))
+ (with-current-buffer output
+ (erase-buffer)
+ (with-temp-buffer
+ (insert (mapconcat #'identity files "\0"))
+ (setq default-directory dir)
+ (setq status
+ (project--process-file-region (point-min)
+ (point-max)
+ shell-file-name
+ output
+ nil
+ shell-command-switch
+ command)))
+ (goto-char (point-min))
+ (when (and (/= (point-min) (point-max))
+ (not (looking-at grep-re))
+ ;; TODO: Show these matches as well somehow?
+ (not (looking-at "Binary file .* matches")))
+ (user-error "Search failed with status %d: %s" status
+ (buffer-substring (point-min) (line-end-position))))
+ (while (re-search-forward grep-re nil t)
+ (push (list (string-to-number (match-string line-group))
+ (match-string file-group)
+ (buffer-substring-no-properties (point) (line-end-position)))
+ hits)))
+ (xref--convert-hits (nreverse hits) regexp)))
+
(defun xref--rgrep-command (regexp files dir ignores)
(require 'find-dired) ; for `find-name-arg'
(defvar grep-find-template)