Leader keys and mapping keyboard sequences
Published: 2024-07-03 11:23:17

As always, when I write "vim", the information is valid in both vim and neovim (to the best of my knowledge). When I write about a feature specific to neovim, I specifically write "neovim".

In vim, you can create keyboard mappings, not just to complex modified keys, like <kbd>ctrl</kbd>+<kbd>alt</kbd>+<kbd>shift</kbd>+<kbd>Q</kbd>, but _sequences of keys_. In fact, `:help map` uses the phrase "Map the key sequence", so the mapping of sequences is integral to vim, and mapping a single key is just a special case of mapping a sequence.

As _normal mode_, doesn't insert anything you don't need complex modifier combinations, but basic letter combinations can be mapped to a command. Most keys on the keyboard already have a function, so finding good key to start the sequence is tricky. The "leader key", is a special key for this purpose that by convention is used to start a sequence. So when you press the leader key, you tell vim, "hey, listen up, now comes a sequence of keys that should trigger a command".

It is common to structure sequences into groupings, e.g. I use <kbd>&lt;leader&gt;v</kbd> for **v**im related tasks, e.g. edit configuration, <kbd>&lt;leader&gt;s</kbd> for **s**earch (files, text, symbols), <kbd>&lt;leader&gt;c</kbd> for **c**ode (refactor, actions, toggle inlay hints).

Plugins can attach keyboard command prefixed with the leader key, making plugins respect _your choice_ of leader key.

By default, the leader key is <kbd>&#92;</kbd>[^1], but you can remap it - depending on your keyboard layout it can be a bit tricky to reach. Many remap it to <kbd>,</kbd> - but that also have a function (see `:help ,`), or they remap it to <kbd>&lt;space&gt;</kbd>.

I personally use <kbd>&lt;space&gt;</kbd>, as my thumb already rests on it by default, making it the most easy key to press.

## The leader is just a variable

The use of <kbd>&lt;leader&gt;</kbd> in a mapping basically just looks up the global variable at the time of creating the map`g:mapleader` (see `:help variable-scope`). As an example, I have mapped <kbd>&lt;leader&gt;ve</kbd> to edit my vim configuration ([V]im [E]dit configuration).

```lua
vim.g.mapleader = " "
vim.keymap.set("n", "<leader>ve", load_init_file)
```

Run `:map` to display the keyboard maps, it shows that <kbd>&lt;Space&gt;</kbd>, is mapped, not <kbd>&lt;leader&gt;</kbd>:

```
n  <Space>ve   * <Lua 27: ~/.config/nvim/init.lua:29>
```

So it is important that you set the leader _before_ any other keyboard mapping, or loading plugins that may setup keymaps.
## Vim waits for unfinished sequences

When you type in a keys which matches the beginning of a mapped sequence, but you don't complete the sequence, vim will wait to see if the sequence is completed. If it's not completed within one second (default value), the vim will behave as if the keys were typed without the mapping. For example, if I map <kbd>iii</kbd> in normal mode:

```vim
nnoremap iii :echo "Foo"<cr>
```

If I type <kbd>iii</kbd>, of course, "Foo" is written to the list of messages, (see `:help :messages`). Buf if I type, <kbd>ii</kbd>, after a second, vim will enter <kbd>insert</kbd>-mode (the first <kbd>i</kbd>), and insert an "i" (the second <kbd>i</kbd>)

### A real example

In insert mode, I have <kbd>j</kbd><kbd>k</kbd> mapped to <kbd>&lt;esc&gt;</kbd>, a sequence of keys that is extremely quick to type to exit to normal mode, as the two keys are be default just beneath my left index- and middle finger, and it's a sequence that is never used in real words or code sequences (I've used this mapping for about 8 years now, and the only time it conflicts with a real use case is when I write about my vim configuration)

So when I type <kbd>j</kbd>, doesn't write the letter to the buffer yet[^2]. If I wanted to type <kbd>jump</kbd>, the moment, I type <kbd>u</kbd>, "ju", is written to the buffer as now the sequence no longer matches a mapping. If I had continued to type <kbd>jk</kbd> vim would run the command; _except_ if there was an even longer sequence starting with  <kbd>jk</kbd> (Writing that sentence did result in a hickup because of my keyboard mapping).

For more information on this behaviour see, `:help map`, `:help timeout`, and `:help timeoutlen`. Also `:help nowait` can modify the behaviour when there are conflicting local and global mappings.

## Local and global mapping and localleader

Vim allows you to create global keyboard mappings, and "local" keyboard mappings. A local keyboard mapping is attached _only to a single buffer_. Often local mappings are setup by a plugin or "autocommand" (consider this an event handler, it's a topic I will explain in another post), resulting in 

Vim actually defines two types of leader keys, _leader_ and _localleader_. Leader is intended for global mappings, and _localleader_ is intended for local mappings.

So an example could be a command to "compile" a source code file. If you load a C or C++ file, you might have mapped <kbd>&lt;localleader&gt;cc</kbd> ([C]ode [C]ompile) to run `cc`, the C-compiler. If you load a Java file, you might map the same sequence to run `javac`, the Java compiler. By having these as local mappings, you can have the same sequence that semantically means the same thing, compile the current file, but is implemented differently depending on the open file, even in a project that includes both C and Java code.

The two leader keys can be the same or they can be different. By default they are both <kbd>\</kbd>, and I have yet to see a vim/neovim configuration that deliberately sets these 

Also, not all plugins even respect the distinction and use leader, where localleader is the "correct" key to use.

## unmap

The `unmap` family of commands, removes a _mapping_. Bear in mind that the build in shortcuts are not _mappings_, so to a shortcut, you need to remap it to a no-op. E.g. the buildin <kbd>&lt;Ctrl+a&gt;</kbd> is not only useless for me, it has caused me a few bugs, so I remap it to a no-op:

```vimscript
noremap <C-a> <nop>
```

You can remove all mappings with `:mapclear`

See also: `:help unmap`, `:help <nop>`, `:help mapclear`.
## map vs noremap

All `map` variants, i.e. `imap`, `nmap`, `xmap`, etc, have a `noremap` variant, e.g. `nnoremap`. The difference is that the `noremap` maps to the _build-in_ keyboard commands, where if a `map` references a command that you've created a map for itself, you will trigger that command.

E.g. as mentioned previously, I have an alternate shortcut <kbd>&lt;Esc&gt;</kbd>. In the beginning, to train my brain to use this, I had mapped escape to a no-op:

```vim
inoremap <esc> <nop>
inoremap jk <esc>
```

The use if `inoremap` makes the <kbd>jk</kbd> map to the _original_ escape function. Had I used `imap`, it would have mapped to a no-op, not very helpful.

You _almost always_ want to use `noremap`. I have never used a `map` in my vim configuration.

When using the lua function `vim.keymap.set`, it is by default the `noremap` version used. You can set the option `{ remap = true }` to use the `map` version.

[^1]: Actually, that wasn't factually correct. By default there is no leader key, <kbd>&#92;</kbd> is the fallback being used.

[^2]: The behaviour I observe in my current configuration is that the "j" is shown on screen but the cursor doesn't move until I type another character, or the timeout has completed.