Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use M-x rgrep with the git grep command in Emacs?

Tags:

grep

emacs

elisp

I want to be able to use the normal M-x rgrep workflow (entering a path, a pattern and displaying the linked results in a *grep* buffer) but using git grep instead of the normal find command:

find . -type f -exec grep -nH -e  {} +

I tried directly setting the grep-find-command variable:

(setq grep-find-command "git grep")

and using grep-apply-setting

(grep-apply-setting 'grep-find-command "git grep")

but neither seems to work. When I run M-x rgrep it just uses the same find command as before.

In fact, I'm pretty sure now that rgrep doesn't even use the grep-find-command variable, but I can't figure out where it's command is stored.

like image 574
Tikhon Jelvis Avatar asked Sep 02 '14 22:09

Tikhon Jelvis


1 Answers

Turns out the relevant variable is actually grep-find-template. This takes a command with a few additional parameters:

  • <D> for the base directory
  • <X> for the find options to restrict directory list
  • <F> for the find options to limit the files matched
  • <C> for the place to put -i if the search is case-insensitive
  • <R> for the regular expression to search for

The default template looks like this:

find . <X> -type f <F> -exec grep <C> -nH -e <R> {} +

To make the command work with git grep, I had to pass in a few options to make sure git doesn't use a pager and outputs things in the right format. I also ignored a few of the template options because git grep already restricts the files searched in a natural way. However, it probably makes sense to add them back in somehow.

My new value for grep-find-template is

git --no-pager grep --no-color --line-number <C> <R>

After some cursory testing, it seems to work.

Note that you should set this variable using grep-apply-setting rather than modifying it directly:

(grep-apply-setting 'grep-find-template "git --no-pager grep --no-color --line-number <C> <R>")

Since I don't use two of the inputs to rgrep, I wrote my own git-grep command which temporarily stashes the old grep-find-template and replaces it with mine. This feels a bit hacky, but also seems to work.

(defcustom git-grep-command "git --no-pager grep --no-color --line-number <C> <R>"
  "The command to run with M-x git-grep.")
(defun git-grep (regexp)
  "Search for the given regexp using `git grep' in the current directory."
  (interactive "sRegexp: ")
  (unless (boundp 'grep-find-template) (grep-compute-defaults))
  (let ((old-command grep-find-template))
    (grep-apply-setting 'grep-find-template git-grep-command)
    (rgrep regexp "*" "")
    (grep-apply-setting 'grep-find-template old-command)))
like image 77
Tikhon Jelvis Avatar answered Sep 28 '22 18:09

Tikhon Jelvis