0

I'm trying to use git grep as my grepprg, but I keep getting spurious files such as ~/fatal: Not a git repository (or any of the parent directories): .git. Is there a way to configure vim to correctly ignore diagnostic messages? I'm okay with general solutions for configuring grepprg and related options or solutions specific to git grep. However, I'd prefer a vim-only solution that doesn't involve writing wrapper programs around git grep.

Here's a snippet from my :browse oldfiles showing the spurious file.

1: ~/.vimrc.bak                                               
2: ~/.vimrc
3: ~/.bash_aliases
4: ~/.bashrc
5: /tmp/eee
6: /tmp/.vimrc
7: /tmp/.vimr
8: ~/fatal: Not a git repository (or any of the parent directories): .git

This problem is reproducible using the following vimrc.

set grepprg=git\ --no-pager\ grep\ --no-color\ -n\ $*
set grepformat=%f:%l:%m,%m\ %f\ match%ts,%f

The above vimrc is based on this answer.

The first thing I tried is set shellredir=>, but the behavior of the grep builtin command does not appear to change according to the value of shellredir.

I've confirmed experimentally that shellredir has no effect on the grep command. I can confirm that set shellredir="00000000" doesn't appear to affect the grep ex command.

The command ex_make is used for grep, make, and other commands that populate the quickfix list. Briefly looking at the code, though, I can't tell why stderr is always captured on Linux and also can't say definitively that shellredir isn't used at all.


One semi-solution that does work is using a wrapper around git grep that immediately discards stderr before vim can see it.

#!/usr/bin/perl

# ~/bin/gitgrep

open(STDERR, ">/dev/null");
exec("git", "--no-pager", "grep", "--no-color", "-n", @ARGV);

and the corresponding vimrc

set grepprg=$HOME/bin/gitgrep\ $*
set grepformat=%f:%l:%m,%m\ %f\ match%ts,%f
0

I solved this issue by removing the option consisting only of %f by itself. I'm not sure what %m %f match%ts means, since the original answer lacks explicit rationale for how the various grepformat strings were determined. I suspect it's related to git grep's output for binary file matches.

The presence of ,%f in the format string above means that, by default, any string that doesn't fit one of the other patterns will be interpreted as a filename.

Using the following lines to configure your .vimrc with git grep as the grepprg appears to solve the immediate problem.

let &grepprg="git --no-pager grep --no-color -n $*"                                                                                  
let &grepformat="%f:%l:%m,%m %f match%ts"                                                                                            

Note: I'm using let &grepprg=... instead of set grepprg=... because I think it makes it more obvious "where" the magic is.

grepprg and grepformat are just strings, but in the former $* (among other things) is handled specially and in the latter , (among other things) is handled specially.

0

I don't use git-grep as grepprg, and here's why:

  1. I mostly use :vimgrep /pattern/ ## to search my argument list.
  2. I mostly use ack to search at the command line, though git-grep is helpful. Combined with :Ack, I'm set.
  3. This function makes it easy to pop open vim with the quickfix ready to go:
vq () { 
    if (($# > 0)); then
        vim -q <("$@" 2>&1)
    else
        printf '%s\n' 'Usage: vq cmd' '' 'Use {cmd} output as quickfix list'
    fi
}
  1. The script in "$(git --exec-path)"/../../share/git-core/contrib/git-jump makes this even easier: git jump grep foo opens up my editor similarly to how vq above functions. It also has other neat functions.
  2. git-grep doesn't work well in non-git repos, as you've noticed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.