Skip to content
Marco Hinz edited this page Aug 1, 2015 · 22 revisions

How to win at grep - with vim-grepper

vim-grepper

Installation

Use your favourite Vim plugin manager to install vim-grepper:

vimrc:

call plug#begin('~/.vim/bundle')
  Plug 'mhinz/vim-grepper'
call plug#end()

Afterwards reload your vimrc with :so %, then kick off the actual installation with :PlugInstall.

Minimal configuration

Now we need to set up the mappings for vim-grepper, as it doesn't come with any predefined mappings. "Why?", you ask? Because there's no right mapping. Use whatever you like. Personally I like these:

nmap <leader>g <plug>(Grepper)
xmap <leader>g <plug>(Grepper)
cmap <leader>g <plug>(GrepperNext)
nmap gs        <plug>(GrepperMotion)
xmap gs        <plug>(GrepperMotion)

If you don't understand these mappings, no worries, I'll guide you through it. This is all the configuration you need for starters. Restart Vim for getting vim-grepper recognized as a new plugin.

First steps

We mapped <plug>(Grepper) to <leader>g> for normal and visual mode, so let's try it!

Just hitting <leader>g will bring up the search prompt. The prompt itself will be set to the current grep tool, by default this is git grep -n (if git is installed, that is).

But what if you're not in a git repo? Just also mapped <plug>(GrepperNext) to <leader>g which simply switches to the next detected grep tool and is only active during the search prompt.

After you entered your search term, hit <cr> to start the search.

NOTE: Opposed to Neovim, you won't be able to do anything in Vim while the grep tool is running, because Vim is inherently single-threaded.

When the grep tool finished running, the results will be put into the quickfix list. By default the quickfix window opens automatically and the cursor jumps to that window. If you don't like this, I'll explain how to change that behaviour later. Play around with :cnext, :cprevious, :cclose, :copen and so on to navigate the quickfix list. (For learning all about quickfix navigation, read :h quickfix.)

If you hit <leader>g in visual mode, the search term will be populated with the current visual selection. Try it!

TIP: The search prompt supports basic file completion for relative and absolute paths via <tab>.

Well done!

The operator

Vim has this incredibly cool feature called "text objects". Before going any further, please read :h text-objects, if you haven't done so far. It will change your Vim life.

For selecting text objects, you need an operator and a motion. Default operators you should know are c for "changing" or d for "deleting" etc. Motions define the scope of the operator. E.g. iw basically means "select word under prompt" or i" means "select everything between double quotes on this line". Thus diw deletes the current word and ci" removes everything between parentheses and puts you into insert mode.

vim-grepper also defines an operator that we mapped as <plug>(GrepperMotion) to gs. And yes, it should have been called <plug>(GrepperOperator) instead, but that's another story.. Anyway, try it out! gsiw will open the search prompt and populate the search term with the current word.

This is nice when you're browsing a codebase and want to lookup all occurences of a certain error message or so. Motions are powerful, be creative!

More configuration

All configuration happens through a global dictionary called.. wait for it.. "grepper", so let's define it to be an empty dictionary first:

let g:grepper = {}

Now, some people prefer location lists over the more specific quickfix list. You only have one quickfix list, but you can have one location list per window. Otherwise they "feel" the same, but use slightly different commands for navigation. See :h location-list.

If you want vim-grepper to use a location list, add this line:

let g:grepper.use_quickfix = 0

Then some people prefer window not to open automatically and the cursor switching to it. Disable both via:

let g:grepper.do_open   = 0
let g:grepper.do_switch = 0

Other people might want to jump to the first entry in the list automatically:

let g:grepper.do_jump = 1

Although this plugin supports quick a few grep tools, you might don't want to use all of them. Or you don't want git grep to be the default one when starting a new search:

let g:grepper.programs = ['ag', 'git', 'grep']

<plug>(GrepperNext) will switch only between these listed tools, with the first element, ag, being the default tool now.

That's it. These are all the options for controlling the actual behaviour of vim-grepper. Now let's see how to extend it..

Adding a new grep tool

Adding a new tool is quite easy. Let's take a hypothetical tool called "finder". finder foo . recursively searches all files beginning from the current directory. Its output looks like this:

foo.prog:102:5 -> def foo:
dir/main.prog:234:22 -> if night == dark and foo("bar") == 'quux'

Then we would add it like this:

let g:grepper.programs = ['finder', 'git', grep']
let g:grepper.finder   = { 'grepprg': 'finder $* .', 'grepformat': '%f:%l:%c -> %m' }

The $* would be replaced by the entered search term and is only needed if certain things, a directory in this case, is needed after the search term. If the directory wasn't necessary, just 'grepprg': 'finder' would have been fine.

Read :h 'grepprg' and especially :h 'grepformat' for more information.

Example configuration

Here's the configuration I use:

nmap <leader>g <plug>(Grepper)
xmap <leader>g <plug>(Grepper)
cmap <leader>g <plug>(GrepperNext)
nmap gs        <plug>(GrepperMotion)
xmap gs        <plug>(GrepperMotion)

let g:grepper              = {}
let g:grepper.programs     = ['git', 'ag', 'grep']
let g:grepper.use_quickfix = 1
let g:grepper.do_open      = 1
let g:grepper.do_switch    = 1
let g:grepper.do_jump      = 0

Final words

I hope you enjoy the plugin! If you need help, have suggestions, or found a bug, don't hesitate to create an issue.

Thanks!

Clone this wiki locally