git-grep in Emacs

There is a vc-git-grep mode in Emacs already (once you load the appropriate git.el etc.). However, I found it obnoxious for a number of reasons, such as being interactive and no control of the parameters to give git (e.g. to turn off the global Pager option). So, I hacked up a trivial little Lisp command:

(defun git-grep (search)
  "git-grep the entire current repo"
  (interactive (list (completing-read "Search for: " nil nil nil (current-word))))
  (grep-find (concat "git --no-pager grep -P -n " search " `git rev-parse --show-toplevel`")))

Two comments on this code:

  1. It is still interactive, and will default the search to whatever is under the cursor currently. You can edit that in the mini-buffer, of course. In addition, it turns off the global Pager.
  2. More important (to me at least) is that it searches the entire git repository, and not just whatever the current directory is. That is the git rev-parse piece of the code.

With this defined, it's easy to create a global key, e.g.

(define-key esc-map "[" 'git-grep)

Comments

This is very useful, thanks!

This is very useful, thanks! I made some tweaks to this for my use:

(defun git-grep-prompt ()
  (let* ((default (current-word))
         (prompt (if default
                     (concat "Search for: (default " default ") ")
                   "Search for: "))
         (search (read-from-minibuffer prompt nil nil nil nil default)))
    (if (> (length search) 0)
        search
      (or default ""))))

(defun git-grep (search)
  "git-grep the entire current repo"
  (interactive (list (git-grep-prompt)))
  (grep-find (concat "git --no-pager grep -P -n "
                     (shell-quote-argument search)
                     " `git rev-parse --show-toplevel`")))

It now just uses read-from-minibuffer instead of completing-read with a nil completion list because otherwise it's hard to type spaces in the search. Instead of setting the INITIAL argument it now puts the word at point in the DEFAULT argument. That way if you want the default you can just press enter, but if you want something completely different you don't have to awkwardly remove the suggested text. You can still press M-n to get the suggestion if you want to edit it. I've also made it call shell-quote-argument on the string so that it will work if the search string has spaces.