Streamlining Vim's :grep
by |Vim’s most straightforward method of global search is its :grep
command, which invokes 'grepprg'
(often grep
or a drop-in replacement such as ag
). It’s awkward that Vim dumps the output of 'grepprg'
and prompts the user to return to editing by pressing Enter. It’s possible to eliminate that extraneous and disorienting step without creating a custom command by using a command-line-mode abbreviation:
cnoreabbrev <expr> grep (getcmdtype() ==# ':' && getcmdline() =~# '^grep') ? 'silent grep' : 'grep'
cnoreabbrev <expr> lgrep (getcmdtype() ==# ':' && getcmdline() =~# '^lgrep') ? 'silent lgrep' : 'lgrep'
The first line breaks down like so:
cnoreabbrev
— Define a non-recursive command-line abbreviation<expr>
— Interpret the right-hand side of the abbreviation as an expression instead of literallygrep
— The string to expandgetcmdtype() ==# ':'
— Is the context the command line (as opposed to a/
or?
search)?getcmdline() =~# '^grep'
— Does the content of the command line begin with “grep”?? 'silent grep'
— If so, expand “grep” to “silent grep”…: 'grep'
— …else expand “grep” to itself (i.e., do nothing)
And the second line does the same, but for :lgrep
, of course.
Now, when you run :grep
/:lgrep
, you won’t get any visual feedback. That can be improved by automatically showing the quickfix or location list window:
augroup init_quickfix
autocmd!
autocmd QuickFixCmdPost [^l]* cwindow
autocmd QuickFixCmdPost l* lwindow
augroup END
The QuickFixCmdPost
autocommand matches its pattern against the command run, so the first one will open the quickfix list window for commands not beginning with l
such as :grep
, and the second will open the location list window for commands beginning with l
such as :lgrep
.