A few chapters ago we learned about autocommands. Run the following command:
:autocmd BufWrite * :echom "Writing buffer!"
Now write the current buffer with :write
and run :messages
to view the
message log. You should see the Writing buffer!
message in the list.
Now write the current buffer again and run :messages
to view the message log.
You should see the Writing buffer!
message in the list twice.
Now run the exact same autocommand again:
:autocmd BufWrite * :echom "Writing buffer!"
Write the current buffer one more time and run :messages
. You will see the
Writing buffer!
message in the list four times. What happened?
When you create an autocommand like this Vim has no way of knowing if you want it to replace an existing one. In our case, Vim created two separate autocommands that each happen to do the same thing.
Now that you know it's possible to create duplicate autocommands, you may be thinking: "So what? Just don't do that!"
The problem is that sourcing your ~/.vimrc
file rereads the entire file,
including any autocommands you've defined! This means that every time you
source your ~/.vimrc
you'll be duplicating autocommands, which will make Vim
run slower because it executes the same commands over and over.
To simulate this, try running the following command:
:autocmd BufWrite * :sleep 200m
Now write the current buffer. You may or may not notice a slight sluggishness in Vim's writing time. Now run the command three more times:
:autocmd BufWrite * :sleep 200m
:autocmd BufWrite * :sleep 200m
:autocmd BufWrite * :sleep 200m
Write the file again. This time the slowness will be more apparent.
Obviously you won't have any autocommands that do nothing but sleep, but the
~/.vimrc
of a seasoned Vim user can easily reach 1,000 lines, many of which will
be autocommands. Combine that with autocommands defined in any installed
plugins and it can definitely affect performance.
Vim has a solution to the problem. The first step is to group related autocommands into named groups.
Open a fresh instance of Vim to clear out the autocommands from before, then run the following commands:
:augroup testgroup
: autocmd BufWrite * :echom "Foo"
: autocmd BufWrite * :echom "Bar"
:augroup END
The indentation in the middle two lines is insignificant. You don't have to type it if you don't want to.
Write a buffer and check :messages
. You should see both Foo
and Bar
. Now
run the following commands:
:augroup testgroup
: autocmd BufWrite * :echom "Baz"
:augroup END
Try to guess what will happen when you write the buffer again. Once you have
a guess in mind, write the buffer and check :messages
to see if you were
correct.
What happened when you wrote the file? Was it what you expected?
If you thought Vim would replace the group, you can see that you guessed wrong. Don't worry, most people think the same thing at first (I know I did).
When you use augroup
multiple times Vim will combine the groups each time.
If you want to clear a group you can use autocmd!
inside the group. Run the
following commands:
:augroup testgroup
: autocmd!
: autocmd BufWrite * :echom "Cats"
:augroup END
Now try writing your file and checking :messages
. This time Vim only echoed
Cats
when you wrote the file.
Now that we know how to group autocommands and clear those groups, we can use
this to add autocommands to ~/.vimrc
that don't add a duplicate every time we
source it.
Add the following to your ~/.vimrc
file:
augroup filetype_html
autocmd!
autocmd FileType html nnoremap <buffer> <localleader>f Vatzf
augroup END
We enter the filetype_html
group, immediately clear it, define an autocommand,
and leave the group. If we source ~/.vimrc
again the clearing will prevent
Vim from adding duplicate autocommands.
Go through your ~/.vimrc
file and wrap every autocommand you have in groups
like this. You can put multiple autocommands in the same group if it makes
sense to you.
Try to figure out what the mapping in the last example does.
Read :help autocmd-groups
.