Vim Keymaps
Vim custom keymaps⚑
I'm assuming you control the next concepts, otherwise read those sections first:
LazyVim comes with some sane default keybindings, you can see them here. You don't need to remember them all, it also comes with which-key to help you remember your keymaps. Just press any key like
- default
<leader>
is<space>
- default
<localleader>
is\
General editor bindings⚑
- Save file:
<C-s>
- Quit all:
<leader>qq
- Open a floating terminal:
<C-/>
Movement keybindings⚑
- Split the windows:
- Vertically:
<C-|
- Horizontally:
<C--
- Delete window:
<leader>wd
- To move around the windows you can use:
, , , . - To resize the windows use:
, , , - To move between buffers:
- Next and previous with
, - Switch to the previously opened buffer:
<leader>bb
Coding keybindings⚑
Diagnostics⚑
<leader>cd>
: Shows you the diagnostics message of the current line in a floating window]d
and[d
: iterates over all diagnostics]e
and[e
: iterates over all error diagnostics]w
and[w
: iterates over all warning diagnostics
Setting keymaps in lua⚑
If you need to set keymaps in lua you can use vim.keymap.set
. For example:
vim.keymap.set('n', '<space>w', '<cmd>write<cr>', {desc = 'Save'})
After executing this, the sequence Space + w
will call the write
command. Basically, we can save changes made to a file with Space + w
.
Let's dive into what does the vim.keymap.set
parameters mean.
vim.keymap.set({mode}, {lhs}, {rhs}, {opts})
{mode}
: mode where the keybinding should execute. It can be a list of modes. We need to specify the mode's short name. Here are some of the most common.n
: Normal mode.i
: Insert mode.x
: Visual mode.s
: Selection mode.v
: Visual + Selection.t
: Terminal mode.o
: Operator-pending.-
''
: Yes, an empty string. Is the equivalent ofn + v + o
. -
{lhs}
: is the key we want to bind. {rhs}
is the action we want to execute. It can be a string with a command or an expression. You can also provide a lua function.-
{opts}
this must be a lua table. If you don't know what is a "lua table" just think is a way of storing several values in one place. Anyway, it can have these properties. -
desc
: A string that describes what the keybinding does. You can write anything you want. remap
: A boolean that determines if our keybinding can be recursive. The default value isfalse
. Recursive keybindings can cause some conflicts if used incorrectly. Don't enable it unless you know what you're doing.buffer
: It can be a boolean or a number. If we assign the booleantrue
it means the keybinding will only be effective in the current file. If we assign a number, it needs to be the "id" of an open buffer.silent
: A boolean. Determines whether or not the keybindings can show a message. The default value isfalse
.expr
: A boolean. If enabled it gives the chance to use vimscript or lua to calculate the value of{rhs}
. The default value isfalse
.
The leader key⚑
When creating keybindings we can use the special sequence <leader>
in the {lhs}
parameter, it'll take the value of the global variable mapleader
.
So mapleader
is a global variable in vimscript that can be string. For example.
vim.g.mapleader = ' '
After defining it we can use it as a prefix in our keybindings.
vim.keymap.set('n', '<leader>w', '<cmd>write<cr>')
This will make <space key>
+ w
save the current file.
There are different opinions on what key to use as the <leader>
key. The <space>
is the most comfortable as it's always close to your thumbs, and it works well with both hands. Nevertheless, you can only use it in normal mode, because in insert <space><whatever>
will be triggered as you write. An alternative is to use ;
which is also comfortable (if you use the english key distribution) and you can use it in insert mode.
If you want to define more than one leader key you can either:
- Change the
mapleader
many times in your file: As the value ofmapleader
is used at the moment the mapping is defined, you can indeed change that while plugins are loading. For that, you have to explicitly:runtime
the plugins in your~/.vimrc
(and count on the canonical include guard to prevent redefinition later):
let mapleader = ','
runtime! plugin/NERD_commenter.vim
runtime! ...
let mapleader = '\'
runime! plugin/mark.vim
...
<leader>
" editing mappings
nnoremap ,a <something>
nnoremap ,k <something else>
nnoremap ,d <and something else>
" window management mappings
nnoremap gw <something>
nnoremap gb <something else>
Defining mapleader
and/or using <leader>
may be useful if you change your mind often on what key to use a leader but it won't be of any use if your mappings are stable.
Tips⚑
Tell the user not to use the keymap⚑
If you're moving away from a keymap or set of keymaps you can show a notice:
-- Save key strokes (now we do not need to press shift to enter command mode).
keymap.set({ "n", "x" }, ";", ":")
keymap.set({ "n", "x" }, ":", function()
vim.notify("Use ; instead")
end)
Set custom keymaps on specific filetypes⚑
Use autocomands on the FileType
pattern. For example to add a keymap to the gitcommit
filetype:
vim.api.nvim_create_autocmd("FileType", {
pattern = "gitcommit",
group = augroup("gitcommit"),
callback = function()
local keymap = vim.keymap
keymap.set("i", "jj", "<esc>:wincmd l<cr>j", { desc = "Go to normal, changes window and down", silent = true, buffer = true })
})
It's important to set the buffer = true
if you don't want the bindings to be permanent for all buffers once it's been loaded.