Power Vim Usage

Tips & Tricks for Everyday Editing


UKUUG Linux 2004 Conference • 2004 August

This view lists all the slides from the talk in a continuous format. There is a PDF version available, suitable for printing on A4 paper.

The slides are also designed to be viewed as a slideshow from this file with Mozilla or a compatible browser. JavaScript is used to make pressing N progress to the next slide. The slides fit on a 1024 × 768 pixel display. To toggle full-screen mode in Mozilla press F11.

Switch to the slideshow view.

1 Intro

2 Learning Vim

The only way to get the hang of Vim is a bit at a time — learning some things you can make use of, getting comfortable with them, then learning some more.

Some of the most useful Vim features don’t require any VI knowledge. Much VI stuff is actually easier to pick up using Vim techniques.

3 Moving About

The slides use options’ long names for clarity, but they all have shorter forms that can be used when typing them, such as ic for ignorecase and scs for smartcase. Also, remember that Vim has tab completion for typing things such as option names and help topics.

incsearch makes searching considerably easier, because you can stop typing (and just press Enter) as soon as you see that you’re where you want to be.

Having searches be case-insensitive is a good default; the presence of any capital letters in the pattern triggers case-sensitive matching. Or put \C in the pattern to make a lower-case string case-sensitive.

To jump to somewhere else in a file use a search and go straight there rather than pressing Down till you see it. This also means that you can use Ctrl+O to jump back to where you were (much easier than the VI way with marks, because it doesn’t require you to remember to set a mark before jumping). Ctrl+O and Ctrl+I take you up and down the list of recent positions; I remember the keys by thinking of them moving ‘outwards’ and ‘inwards’.

f and t move you along the current line — better than pressing Right lots if you can see where you want to be.

Learning a few (more) movement commands helps with editing too, since so many commands such as d, c, and v can be followed by any movement command. For example type df> to delete up to the next right angle bracket, or ct" to change the text before the next quotes.

Capital F is similar to f but moves left instead of right. Guess what the left-moving variant of t is? See, once you know a few commands it becomes possible to infer others.

‘[ and ‘] move to either end of the chunk of text most recently modified (inserted, indented, whatever). ‘< moves to the start of the most recent selection; guess what moves to the end. These are useful for performing several operations on the same text.

[{ and friends is great if working in a language such as C or Perl with delimited blocks; it doesn’t just search for the preceding left brace, but for the one that starts the block you’re in — handy for discovering which function or if clause this is.

4 Visual Mode

This is a good example of a Vim feature making VI keystrokes easier to learn: trying out the various movement commands in visual mode is completely safe, then you can press d or c or whatever to act once the correct text has been highlighted.

5 Settings in .vimrc

Many excellent Vim features are hidden by default so that Vim behaves in a VI-compatible way and doesn’t confuse traditional VI users. But then it ships with a default system-wide config file that enables some Vim-specific features (such as the search highlighting that irritates so many people), which undermines the compatibility without provding maximum usability.

6 Indenting

Indenting when done correctly is one of those things that makes an editor a pleasure to use, automating a very tedious job. When left to indent manually many people don’t bother, or end up with an incoherent mess, a mixture of spaces and tabs and things that don’t line up right.

This is one of the things that Vim is terrible at by default — often you seem to be working against the editor rather than with it — which seems even more of a shame once you finally discover that with only a few settings things can be so much better.

7 Indenting Done Right

Highlighting a block of code and pressing = to reformat it is one of those things that can really impress your colleagues — especially if they’ve been struggling to do it by hand. :retab is a command worth knowing for changing tabs to spaces; you may need to adjust tabstop so that code looks ‘right’ first.

Some people dislike autoindent; if that’s you then don’t use it, but the other options are still worth having.

8 Pasting

This is something that many people find annoying; the behaviour can be quite puzzling until you realize what’s going on. It’s one of the things that gives automatic indenting a bad name (even though it isn’t really Vim’s fault). Again Vim has a solution, but there isn’t a keystroke mapped to it by default.

In a terminal when you’ve got autoindent turned on when you press Enter after an indented line Vim automatically adds some spaces at the beginning of that line. As a human being you see those spaces and don’t type any yourself, unless you want to increase the indent.

The problem is that when you’re pasting in already-indented text Vim still puts these default spaces in, but then some additional spaces from the pasted text get ‘typed’ in at the start of each line, increasing the indent on every line and leading to the ‘stepped’ effect down the page. The way that terminals work, Vim has no way of distinguishing text being pasted in from somebody just typing very fast.

This problem does not occur when using Vim’s own gui (started with the gvim command, for example), where Vim has full control of the input system and can spot when pasting is taking place.

9 Filetype-Dependent Settings

Wanting a different set-up for different types of files is a fairly basic requirement. Without this you’re often compromising the default set-up, and often putting up with inconvenient settings. For example, generally tab characters are evil, but in makefiles they’re a necessary evil so you don’t want expandtab enabled when editing makefiles.

One of the problems is that because Vim made this so hard for so long, many people are not aware of how simple it can be now. Another problem is that for backwards compatibility Vim still accepts the older ways of attempting to do this, which makes the documentation much more complicated — with the result that even after reading the built-in help, many people are still not aware of how simple this now is.

But the few people that did work it out went ahead and customized their environments for different types of files. A bunch of these plug-ins are shipped with Vim ready for use — they just aren’t enabled by default (is this sounding familiar?). So you can very easily take advantage of others’ work in setting up per-filetype settings without needing to know how to do this yourself.

10 Custom Filetype Settings

The first major feature Vim 6 has for filetype-specific settings is using completely separate file for each filetype’s settings. You just have to save the settings in a suitably named file and Vim loads them at the appropriate time. The example above specifies that double-hyphens can be used to denote single-line comments in SQL files.

If you create a plug-in file such as ~/.vim/ftplugin/perl.vim for a filetype which already has a system-wide plug-in then yours will be used instead. Alternatively you can put your options in a file under ~/.vim/after/, such as ~/.vim/after/ftplugin/perl.vim and then the system-wide file will be run first and then your file afterwards.

11 Easier Typing

Ctrl+P is arguably the thing that’s worth learning for impressing people looking over your shoulder: they can see words magically appearing on screen faster than you can type.

12 Spelling Help

Inserting correctly spelt words is better than having to check them later. Even when you can spell, only having to type the first few letters of a long word then press Ctrl+N a few times to fill in the rest can often be easier than typing it out.

13 Working with Text

For some time after becoming a fan of Vim for editing code, I was sceptical of its utility in writing plain, human-readable text files; they don’t seem to require many of Vim’s features, and some actually get in the way. Actually Vim is very good for dealing with text, and once you’re familiar with it can be used much more efficiently than simpler editors.

However working comfortably with text requires different options being set. This is most easily achieved by creating a filetype for such files. Then you can customize the environment like for any other filetype; the above is just an example of a few options that are useful.

Vim already has a mail filetype, which is likely to want your text settings too. You can achieve this by starting mail.vim with this command:

runtime! human.vim

Further settings are added afterwards, and can of course override import settings. For example you probably want a narrower textwidth on e-mails.

You can use your filetype.vim to define a custom filetype for anything that Vim doesn’t already support, or to persuade a non-standard extension to be treated as one of the existing filetypes.

14 Spelling Checking

To set up this style of spelling-checking, include all of the following in your ~/.vim/ftplugin/human.vim file. You need to have ISpell installed, and may need to alter the global variables at the start.

nnoremap <F9> :silent call HighlightSpellingErrors()<Enter>
nnoremap <F10> :syntax clear SpellingError<Enter>

nnoremap <F8> :silent call AddWordToDictionary()<Enter>

" global variables used in these functions (PersonalDict is also handy for
" setting the complete option):
let ISpellLang = 'british'
let PersonalDict = '~/.ispell_' . ISpellLang

function! s:HighlightSpellingErrors()
" highlights spelling errors in the current window

  " Remove any previously-identified spelling errors (and corrections):
  silent! syntax clear SpellingError
  silent! syntax clear Normal

  " Pipe buffer contents  through 'ISpell' to generate a list of misspelt words
  " and store it in a temporary file:
  let ErrorsFile = tempname()
  let SpellerCmd = 'ispell -l -d ' . g:ISpellLang
  execute 'w ! ' . SpellerCmd . ' | sort -u > ' . ErrorsFile

  " Open that list of words in another window:
  execute 'split ' . ErrorsFile

  " For every word in that list ending with "'s", check if the root form
  " without the "'s" is in the dictionary, and if so remove the word from the
  " list:
  g /'s$/ execute 'r ! echo ' . expand('<cword>') . ' | ' . SpellerCmd | delete
  " (If the root form is in the dictionary, ispell -l will have no output so
  " nothing will be read in, the cursor will remain in the same place and the
  " :delete will delete the word from the list.  If the root form is not in the
  " dictionary, then ispell -l will output it and it will be read on to a new
  " line; the delete command will then remove that misspelt root form, leaving
  " the original possessive form in the list!)

  " Turn each mistake into a 'Vim' command to place it in the SpellingError
  " syntax highlighting group:
  %s/.*/syntax match SpellingError #\\v<&>#/

  " Save and close that file (so switch back to the one being checked):

  " Make syntax highlighting case-sensitive, then execute all the match
  " commands that have just been set up in that temporary file, delete it, and
  " highlight all those words in red:
  syntax case match
  execute 'source ' . ErrorsFile
  call delete(ErrorsFile)
  highlight SpellingError term=reverse ctermfg=DarkRed guifg=Red

endfunction " HighlightSpellingErrors()

function! s:AddWordToDictionary()
" adds the word under the cursor to the personal dictonary

  " Get the word under the cursor, including the apostrophe as a word character
  " to allow for words like "won't", but then ignoring any apostrophes at the
  " start or end of the word:
  setlocal iskeyword+='
  let Word = substitute(expand('<cword>'), "^'\\+", '', '')
  let Word = substitute(Word, "'\\+$", '', '')
  setlocal iskeyword-='

  " Override any SpellingError highlighting that might exist for this word,
  " 'highlighting' it as normal text:
  execute 'syntax match Normal #\v<' . Word . '>#'

  " Remove any final "'s" so that possessive forms don't end up in the
  " dictionary, then add the word to the dictionary:
  let Word = substitute(Word, "'s$", '', '')
  execute '!echo "' . Word . '" >> ' . g:PersonalDict

endfunction " AddWordToDictionary()

15 Reflowing Text

With the above mapping you can press Q every time you alter something in a paragraph, and the line-breaks get sorted out. The default meaning of Q is not useful, and anyway gQ makes a better job of it.

16 Vim in Mozilla

It would be nice if this were integrated slightly more, but it’s better than nothing.

17 CVS

Putting interaction with commonly used external programs in the editor greatly reduces the hassle of dealing with them. The above mappings are just examples of things you can do.

The % in the above cvs commit command gets replaced with the current filename. Using this mapping reduces the chance of committing a whole directory when you only wanted to commit one file. CVS will invoke $EDITOR for typing the commit message. Note that Vim’s gui doesn’t emulate a terminal well enough to run Vim inside it. It’s a good idea to put the following setting in ~/.gvimrc to prevent this from happening:

let $EDITOR = 'gvim -f'

18 Working with Multiple Files

Often people have a bunch of files to work with at once. There are several ways of specifying them to Vim, but switching between them is a tad tedious. Fortunately the keystrokes Ctrl+N and Ctrl+P don’t do anything useful by default (they duplicate j and k), so they can be co-opted for something more useful.

confirm is another one of those options that almost everybody wants all the time, and yet it’s beginners who have to make do without it. If you try to close a file with unsaved changes you probably wish to save them first; you may also wish to abandon the changes; but it’s much less likely that you suddenly decide not to close that file at all.

By default Vim presumes the latter case, aborting your action with zero further keystrokes from you. Saving the changes involves about seven keystrokes (:w<Enter>:<Up><Up><Enter>); abandoning them usually requires inserting an exclamation mark somewhere in the previous command, which sometimes isn’t possible. That’s definitely not optimized for the common case. confirm instead prompts you, making it exactly one keystroke for each choice, and with saving being conveniently available just by pressing Enter.

19 Loading Files

Ctrl+W f is handy with #include-type statements, for opening a related file in another window.

20 Repetitive Shell Commands

When you’ve got a large number of files that need processing in some way, entering the commands by hand is far too tedious. Often using a shell for loop isn’t much better. First there’s the syntax to remember: not just the actual loop construct, but the variable expansion like ${f#gif} for extracting bits from filenames.

Also of concern is the one-shot approach: you write all of your loop, then run it and see what happens. For anything even slightly complicated it can seem quite risky to chance that all the syntax is correct.

It isn’t particularly obvious, but Vim can be used as a loop. First pipe the list of filenames, preferably one per line, into Vim. Then use as many commands as needed to transform each line into the Unix command to run on that file, and pipe the list into a hell.

This is safer because you get to preview exactly which commands will be run. It’s often easier, because you can use multiple steps to transform the filenames into commands, and if you get a step wrong you can simply undo it.

21 Complex Transformations

Old-style Ex (“colon”) commands are not easy to learn even by Vim standards, but if you bother to get familiar with them they are useful much more often than you’d think.

The last two lines in the :g// example above puts <h3> HTML tags around lines that are ‘underlined’ with a row of equals signs, then removes the equals signs. The first two :g// commands are merely exploratory :print statements, checking that the lines selected by the regexp are the appropriate ones.

Many sorts of transformations are possible in this way. If the bits between the subheadings are bullet lists denototed with asterisks, then they could be HTMLified with somegthing like the following.

22 Summary

© Copyright Smylers 2004
This material may not be distributed without explicit permission.