Vim, You Complete Me

Mike Burns

Ever watch someone else type at a shell, spelling out every filename, even making typos and fixing them, very slowly? “Hit tab!”, you yell, helpfully.

I do that when watching someone use vim.

The Quick Rundown

key description
^P basic tab completion, pulling from a variety of sources
^N the same as ^P but backward
^X ^L whole line completion
^X ^O syntax-aware omnicompletion

Play with these to get a feel for them. I use this mapping:

imap <Tab> <C-P>

The Keyboard Details

When using completion, a helpful menu pops up, showing all the potential matches. Within this menu you can press ^P or ^N to insert the next or prior word, respectively, or you can press one of those hard-to-reach arrow keys. The arrow key will select the word from the menu but will not replace your text with the selected word; at this point you can press ^L to enter the next character from the selected word.

When you’re happy with the selected word you can press ^Y; to give up entirely, press ^E. When you’re happy with the selected word but ready to keep typing other stuff, just keep typing. It’ll figure it out.

You can also insert the tokens after a completion, which is useful for when you forget that we invented abstractions 40 years ago. For example, let’s say you have this Gherkin:

Scenario: paint a wall blue
  Given I have some paint
  And I have a white wall
  When I paint the wall blue
  Then I should see "success"

And now you want to make a similar scenario, but for red:

Scenario: paint a wall red

The Configurations

You can change all of this. Here are three useful options with the settings that make me happy:

set complete=.,b,u,]

^P and ^N pull from a list of words computed by vim; the source of these completions is determined by the complete setting. In the above example it will pull from keywords in the current file, other buffers (closed or still open), and from the current tags file. More details: :h 'complete'

set wildmode=longest,list:longest

How vim should go about replacing your text. The above setting is closest to the default for zsh, which might be what you want. Other possiblities are listed at :h 'wildmode'.

set completeopt=menu,preview

This is the default, and it works just fine. It shows a menu and, if available, any additional tips such as the method signature or defining file. If you really want to change it, read up on the details at :h 'completeopt'.

Be Smarter

While the above configurations are useful for simple pleasures, we can make the configuration more intelligent by writing functions in vimscript. For example, in HTML vim should know that you can’t nest a div inside an a or that class is a valid attribute name but classic is not. Enter omnifunc.

There are five relevant omnifuncs that ship with vim: CSS, HTML, JavaScript, Ruby, andSQL. They are autoloaded for the relevant filetype, slower than ^P, and totally brilliant. They can fill in defined method names after . in Ruby, complete property names in CSS, automatically close the correct tag in HTML, or guess at table and column names inSQL.

Many other omnifunc definitions exist for other languages, and you can write your own. For more details see :h complete-functions.

But Wait, There’s More

This blog post is a tiny fraction of what’s available. Dictionaries, thesauri, tags, filenames, vim command names, and so much more are all documented under :h ins-completion.

So next time, hit tab!

What’s next

If you found this useful, you might also enjoy: