Here’s a fun gotcha. I had this snippet in my vimrc, which kills trailing whitespace in buffers full of programming code, right before the buffer gets written out…

autocmd FileType c,css,cabal,cpp,haskell,javascript,php,python,readme,text
   autocmd BufWritePre <buffer>
   :call setline(1,map(getline(1,"$"),'substitute(v:val,"\s\+$","","")'))

Which is all well and good. Except when your kind of anal like me, and you end up editing your vimrc often, and you have a keymap just for re-executing your vimrc. The fun thing about autocmd’s is that they don’t replace previous autocmd (there’s no way for vim to tell that things should be replaced, since there’s no naming). So each time I re-ran my vimrc, yet another filetype hook which sets up the pre-write hook.

That’s not so bad in it of itself, except that elsewhere in my vimrc, I had similarly accumulating autocmds which set the filetype based on the buffer. Lots of refreshes and reloads later, I discovered that some files literally had hundreds of passes of the white-space munging routine attached to it, causing saves to take 10+ seconds.

Anyhow, long story short, if you like autocmds (and who doesn’t!?) make sure you use the augroupĀ facility to group them together, name them, and clear old ones out each time you define a bunch in a script. This will keep things from accumulating and leading to weird problems.

Here’s an example:

augroup kill_trailing_whitespace
  au!
  autocmd FileType c,css,cabal,cpp,haskell,javascript,php,python,readme,text
     autocmd BufWritePre <buffer>
     :call setline(1,map(getline(1,"$"),'substitute(v:val,"\s\+$","","")'))
augroup END