Support using ripgrep in project-find-regexp and friends
Performance results vary here. Some projects and search terms don't see much of a change, but for some (including Emacs sources checkout and case-insensitive search) the switch to ripgrep shows ~2-3x speed improvement. Another piece of anecdata here: https://lists.gnu.org/archive/html/emacs-devel/2020-06/msg00802.html * lisp/progmodes/xref.el (xref-search-program-alist) (xref-search-program): New user options. (xref-matches-in-files): Use them.
This commit is contained in:
parent
25df2375db
commit
f2a3d6e28d
2 changed files with 58 additions and 7 deletions
3
etc/NEWS
3
etc/NEWS
|
|
@ -1187,6 +1187,9 @@ project's root directory, respectively.
|
|||
So typing 'C-u RET' in the "*xref*" buffer quits its window
|
||||
before navigating to the selected location.
|
||||
|
||||
*** New option xref-search-program.
|
||||
So far Grep and ripgrep are supported.
|
||||
|
||||
** json.el
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1262,12 +1262,56 @@ IGNORES is a list of glob patterns for files to ignore."
|
|||
(declare-function tramp-tramp-file-p "tramp")
|
||||
(declare-function tramp-file-local-name "tramp")
|
||||
|
||||
;; TODO: Experiment with 'xargs -P4' (or any other number).
|
||||
;; This speeds up either command, even more than rg's '-j4' does.
|
||||
;; Ripgrep gets jumbled output, though, even with --line-buffered.
|
||||
;; But Grep seems to be stable. Even without --line-buffered.
|
||||
(defcustom xref-search-program-alist
|
||||
'((grep
|
||||
.
|
||||
;; '-s' because 'git ls-files' can output broken symlinks.
|
||||
"xargs -0 grep <C> -snHE -e <R>")
|
||||
(ripgrep
|
||||
.
|
||||
;; Note: by default, ripgrep's output order is non-deterministic
|
||||
;; (https://github.com/BurntSushi/ripgrep/issues/152)
|
||||
;; because it does the search in parallel. You can use the template
|
||||
;; without the '| sort ...' part if GNU sort is not available on
|
||||
;; your system and/or stable ordering is not important to you.
|
||||
;; Note#2: '!*/' is there to filter out dirs (e.g. submodules).
|
||||
"xargs -0 rg <C> -nH --no-messages -g '!*/' -e <R> | sort -t: -k1 -k2n"
|
||||
))
|
||||
"Associative list mapping program identifiers to command templates.
|
||||
|
||||
Program identifier should be a symbol, named after the search program.
|
||||
|
||||
The command template must be a shell command (or usually a
|
||||
pipeline) that will search the list of files which will be piped
|
||||
from stdin. The template should have following fields:
|
||||
|
||||
<C> for extra arguments such as -i and --color
|
||||
<R> for the regexp itself (in Extended format)"
|
||||
:type '(repeat
|
||||
(cons (symbol :tag "Program identifier")
|
||||
(string :tag "Command template"))))
|
||||
|
||||
(defcustom xref-search-program 'grep
|
||||
"The program to use to search inside files.
|
||||
|
||||
This must reference a corresponding entry in `xref-search-program-alist'."
|
||||
:type `(choice
|
||||
(const :tag "Use Grep" grep)
|
||||
(const :tag "Use ripgrep" ripgrep)
|
||||
(symbol :tag "User defined")))
|
||||
|
||||
;;;###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."
|
||||
(cl-assert (consp files))
|
||||
(require 'grep)
|
||||
(defvar grep-highlight-matches)
|
||||
(pcase-let*
|
||||
((output (get-buffer-create " *project grep output*"))
|
||||
(`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist))
|
||||
|
|
@ -1277,13 +1321,17 @@ FILES must be a list of absolute file names."
|
|||
;; 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)))))
|
||||
;; The 'auto' default would be fine too, but ripgrep can't handle
|
||||
;; the options we pass in that case.
|
||||
(grep-highlight-matches nil)
|
||||
(command (grep-expand-template (cdr
|
||||
(or
|
||||
(assoc
|
||||
xref-search-program
|
||||
xref-search-program-alist)
|
||||
(user-error "Unknown search program `%s'"
|
||||
xref-search-program)))
|
||||
(xref--regexp-to-extended regexp))))
|
||||
(when remote-id
|
||||
(require 'tramp)
|
||||
(setq files (mapcar
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue