From 43f66c33684a11304c2e6b09003289fb46ae5d68 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 29 Dec 2019 15:11:53 +0300 Subject: [PATCH] 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. --- lisp/dired-aux.el | 3 +-- lisp/progmodes/project.el | 48 +------------------------------------ lisp/progmodes/xref.el | 50 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 49 deletions(-) diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index ce967b0735f..dbe69e54820 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -2958,7 +2958,6 @@ with the command \\[tags-loop-continue]." (declare-function xref--show-xrefs "xref") (declare-function xref-query-replace-in-results "xref") (declare-function project--files-in-directory "project") -(declare-function project--find-regexp-in-files "project") ;;;###autoload (defun dired-do-find-regexp (regexp) @@ -2994,7 +2993,7 @@ REGEXP should use constructs supported by your local `grep' command." (push mark files))) (nreverse marks)) (setq xrefs - (project--find-regexp-in-files regexp files)) + (xref-matches-in-files regexp files)) (unless xrefs (user-error "No matches for: %s" regexp)) xrefs)))) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 74c2bf91c41..6d6ede7e5d6 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -425,8 +425,6 @@ DIRS must contain directory names." (declare-function grep-read-files "grep") (declare-function xref--show-xrefs "xref") (declare-function xref--find-ignores-arguments "xref") -(declare-function xref--regexp-to-extended "xref") -(declare-function xref--convert-hits "xref") ;;;###autoload (defun project-find-regexp (regexp) @@ -479,51 +477,7 @@ pattern to search for." nil))) (defun project--find-regexp-in-files (regexp files) - (pcase-let* - ((output (get-buffer-create " *project grep output*")) - (`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist)) - (status nil) - (hits nil) - (xrefs 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))) - (setq xrefs (xref--convert-hits (nreverse hits) regexp)) + (let ((xrefs (xref-matches-in-files regexp files))) (unless xrefs (user-error "No matches for: %s" regexp)) xrefs)) 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) -- 2.39.2