Thursday, July 12, 2012

Vim, you complete me, by 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.


^Pbasic tab completion, pulling from a variety of sources
^Nthe same as ^P but backward
^X ^Lwhole line completion
^X ^Osyntax-aware omnicompletion
Play with these to get a feel for them. I use this mapping:
imap <Tab> <C-P>


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


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'


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, and SQL. They are autoloaded for the relavant 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 in SQL.
Many other omnifunc definitions exist for other languages, and you can write your own. For more details see :h complete-functions


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!