Learn Vimscript the Hard Way

Buffer-Local Options and Mappings

Now we're going to take a few minutes to revisit three things we've already talked about: mappings, abbreviations, and options, but with a twist. We're going to set each of them in a single buffer at a time.

The true power of this idea will become apparent in the next chapter, but we need to lay the groundwork for it now.

For this chapter you'll need to open two files in Vim, each in its own split. I'll call them foo and bar, but you can name them whatever you like. Put some text into each of them.

Mappings

Switch to file foo and run the following commands:

:nnoremap          <leader>d dd
:nnoremap <buffer> <leader>x dd

Now stay in file foo, make sure you're in normal mode, and type <leader>d. Vim will delete a line. This is nothing new.

Still in file foo, type <leader>x. Vim will delete a line again. This makes sense because we mapped <leader>x to dd as well.

Now move over to file bar. While in normal mode, type <leader>d. Again, Vim deletes the current line. Nothing surprising here either.

Now for the twist: while still in file bar, type <leader>x.

Instead of deleting the entire line, Vim just deleted a single character! What happened?

The <buffer> in the second nnoremap command told Vim to only consider that mapping when we're in the buffer where we defined it.

When you typed <leader>x in file bar Vim couldn't find a mapping that matched it, so it treated it as two commands: <leader> (which does nothing on its own) and x (the normal command to delete a single character).

Local Leader

In our example we used <leader>x for our buffer-local mapping, but this is bad form. In general, when you create a mapping that only applies to specific buffers you should use <localleader> instead of <leader>.

Using two separate leader keys provides a sort of "namespacing" that will help you keep all your various mappings straight in your head.

It's even more important when you're writing a plugin for other people to use. The convention of using <localleader> for local mappings will prevent your plugin from overwriting someone else's <leader> mapping that they've painstakingly burned into their fingers over time.

Settings

In one of the earliest chapters of the book we talked about settings options with set. Some options always apply to all of Vim, but others can be set on a per-buffer basis.

Switch to file foo and run the following command:

:setlocal wrap

Now switch to file bar and run this command:

:setlocal nowrap

Make your Vim window smaller and you'll see that the lines in foo wrap, but the lines in bar don't.

Let's try another option. Switch to foo and run this command:

:setlocal number

Now switch over to bar and run this command:

:setlocal nonumber

You now have line numbers in foo but not in bar.

Not all options can be used with setlocal. To see if you can set a particular option locally, read its :help.

I've glossed over a bit of detail about how local options actually work for now. In the exercises you'll learn more about the gory details.

Shadowing

Before we move on, let's look at a particularly interesting property of local mappings. Switch over to foo and run the following commands:

:nnoremap <buffer> Q x
:nnoremap          Q dd

Now type Q. What happens?

When you press Q, Vim will run the first mapping, not the second, because the first mapping is more specific than the second.

Switch to file bar and type Q to see that Vim uses the second mapping, because it's not shadowed by the first in this buffer.

Exercises

Read :help local-options.

Read :help setlocal.

Read :help map-local.