Setting Neovim Key Mappings

As Neovim has rolled out its lua API it has offered several methods of setting key mappings. A quick internet search will bring up several of them, which has led to some confusion for new users. Since then, Neovim's lua APIs have evolved and become more stable. We recommend that users use the latest API, which is as-follows:

vim.keymap.set(
{mode}, -- string or table
{lhs}, -- string
{rhs}, -- string or function
{opts} -- optional table
)

{mode}:

The first argument is a string or list of strings specifying the mode(s) for which this mapping should apply. Each mode is specified using its short name. Here are several examples of mode specifications:

"n"         -- apply in normal mode only
{"n"} -- apply in normal mode only
{"n", "i") -- apply in normal and insert modes

{lhs}:

"lhs" is short for the "left-hand side", which specifies which keys should invoke the key mapping. Whether a key mapping creates a new operation or overrides an existing operation, it should be specified as the lhs.

Ambiguous Key Mappings

Internet forums are full of questions asking "why is the ab command so slow on my computer". In many cases, the issue is an ambiguous key mapping; if key mappings ab and abc are both defined, when ab is typed Neovim has to wait to see if the user is typing abc, or if the user intended to type only ab. This pause creates a noticeable delay.

In most cases the solution is to review the key mappings and re-map any that are ambiguous. Another option for some could be to reduce the timeoutlen option from the default (1000 msec) to a shorter length.

Mapleader

A tool to help prevent ambiguous mappings is to use the mapleader, or often referred to simply as leader. Hitting the leader key tells Neovim to expect a key mapping that has been defined with the <leader> prefix. Since no operators or commands begin with the leader, this provides extra flexibility for creating unambiguous key mappings. Note that it is still possible to create ambiguous mappings with the <leader>.

We should note that there are two types of leaders, the first is <mapleader>, which applies to global key mappings, and <maplocalleader>, which applies to buffer-local mappings. Although these are generally set to the same value, they can be set to different values.

By default the leader is \, but can be changed in your configuration files as follows:

vim.g.mapleader = " "
vim.g.maplocalleader = " "

In this example, both leaders are set to the <space> key, which is a popular leader key since it can easily be hit with the thumb. The local and global leaders can be set to separate keys to allow different behaviors between global and buffer-local key mappings by changing the values above. When both buffer-local and global mappings are defined for an lhs, the buffer-local key mapping take precedence.

{rhs}:

"rhs" is short for "right-hand side", which specifies the action to be taken when the lhs is invoked. Neovim accepts several rhs formats:

keys

In the simplest case, the rhs of a key mapping is a simple string of keys that should substitute those of the lhs. An example of a simple key mapping and be found in the improved-J tip.

command

Another common use case is to use key mappings to execute command-line mode commands. The Moving Lines tip provides a good example of defining key mappings that implement a command.

Note that Neovim still implements the key mapping as literal key presses, so executing the command-line command (rather than simply type the command into the command-line) requires inserting a <CR> into the correct location.

User Command

After defining a user-command, it can be used in a key mapping just like any other command-line command.

lua function

Finally, key maps can also be defined to call custom lua functions, which can implement essentially any desired logic using Neovim's lua API.

The basic pattern for implementing a key mapping with lua functions is:

local callback = function()
vim.print("Hello World!")
end

vim.keymap.set("n", "test", callback)

Which defines the test key mapping to call the callback lua function.

{opts}:

Neovim supports several options when defining key mappings, which can all be found in the Neovim docs. These options have sensible default values, so that only two of them need to be used in most cases:

buffer

The buffer option is used to define a buffer-local key mapping.

Value Meaning
false Create a global key mapping. This is the default
true Create the keymap for the current buffer only
0 Create the keymap for the current buffer only
[digit] Create the keymap for only the buffer with the specific buffer number

desc

Text description of what the keymap does. What this does will become more clear when we get to the listing keymaps section.