Vim Side Search: Making Search Fun Again

written in vim

The quickfix feature is nice, but it doesn’t give enough context around the search term that leads to use ag from terminal and switch back and forth between programs. I do this search dance every day and I’ve had it! There must be better way!

Problem

Look at the quickfix window above. It spends most of its space showing the file name of the hit, then the remainder is spent on text around it. In projects using Rails Engines with deeply nested directory structures, this often leaves me with just a bunch of paths in the quickfix.

Solution A – The Unix Way

Some may argue Vim isn’t suppose to do search. Vim rightly delegates to the Unix philosophy by allowing an external program do its searching. Let’s try that for this solution using grep, ack, and ag.

We’ve run the 3 separate programs (normally, I would only use ag) then browse the results to see if there’s an interesting file. At this point I start using my handy-dandy mouse to scroll around, precisely highlight the path of interest, copy, and type vim <Paste>. Intuitive? Yes. Fast? No!

Maybe I should use tmux or screen so I don’t need to mouse around, but trying to select a path is still pretty slow for me and requires more cognitive load than I have patience for. After all, I’m trying to concentrate on a refactor or something, not how to open a bunch of files. Should I practice more? Yes. Will I? No!

We’re going to use ag from now on, since it’s faster than ack, and has prettier output than grep. I really really really tried to get grep to output for humans, but couldn’t figure it out.

Solution B – Vim without Quickfix

Let Vim do some work for us.

1
vim `ag --ignore=\*.{css,scss} -l help` +'/help'

What’s that?!? Open Vim passing the result of ag command. ag is run with some file exclusions, -l only file names, and help is the search term. +'/help' tells Vim to immediately start searching for ‘help’.

After all that, Vim should have started with a bunch of buffers. View them with :ls. Take notice of the buffer numbers to see how many files were found. Use n and N to jump through search matches in the file. Use :bn to go to the next buffer and start hitting n again to cycle through the changes. If the number of files is small enough, you may be able to use :ball to open every buffer in its own window.

Thats a lot of work to jump through changes. Good thing the quickfix exists.

Solution C – Quickfix

This is here for posterity. quickfix DOES make cycling through changes easier than Solution B, but as I stated in the intro, it doesn’t give the context that we want.

Thoughtbot has a pretty good article about how to setup Vim to use ag. Once you do that, you can :grep help to get the following output:

Use :cnext, :cprev, :cfirst, :clast to go to next, previous, first, and last quickfix result respectively. Map those to keys to make it easier to navigate.

1
2
3
4
nnoremap [q :cprev<CR>
nnoremap ]q :cnext<CR>
nnoremap [Q :cfirst<CR>
nnoremap ]Q :clast<CR>

Get more help about quickfix using :help quickfix. Cry after realizing even :help quickfix can’t show more context. I’ll be here when you’re done.

Solution D – Side Search Plugin

So how do we get the best of both worlds? How do we enter the land of a thousand wives/husbands? How do we get ag output and quick navigation? For me, it was writing a plugin in. For you it’s using it. https://github.com/ddrscott/vim-side-search

After installing the plugin using your favorite package manager, you’ll have access to the following functionality:

Things to notice:

  • ag output is in a buffer with additional syntax highlighting!
  • n and N used to jump to matches. Regular Vim navigation works, too!
  • <CR> and <C-w><CR> used to open change and jump to change!
  • Number of matches shown in the buffer name!
  • I use too many exclamation points!!!

The plugin’s README has more details.

Closing

I’ve been using this plugin ever since its inception and don’t know where I’d be without it. It gets some inspiration from fugitive’s :Gstatus mode/buffer, and I wish there were more plugins that added functionality from stdout instead of transforming it into a different format. Unix tools makers spend a lot of time thinking about the output. Let’s use it to our advantage.

I’ve learn a lot creating this plugin and plan to write about it in a future post. Do you love it or hate it? Have more ideas for Side Search? Please let me know what you think of it. Have more ideas or issues for Side Search? Hit me up on Github.

References

In The News