Keymaps in Neovim 0.5 with Lua

·

5 min read

Hopefully you have read my last post on the basics of configuring Neovim. You must already be having a lua/ folder, so let's start by creating a keymaps.lua file inside it.

Make sure to execute the command below in your nvim configuration directory.

touch lua/keymaps.lua

Let's go to init.lua file and add the following line -

require('keymaps')

Now let's go back to the keymaps.lua file, as usual you can use :e lua/keymaps.lua to quickly go to the file.

First Keymap

Something we have been often doing till now is using the command :luafile % let's make a keymap for it.

What about using ctrl+r to source the current lua file?

Add the following line -

vim.api.nvim_set_keymap("n", "<C-r>", ":luafile %<CR>", { noremap = true, silent = true })

and do :luafile %, now try adding a print("foo") and use CTRL+R to confirm your mapping works.

Let's break down the above lua code.

vim.api.nvim_set_keymap() is a function which is used to define keymaps in Neovim.
The function takes 4 parameters -

  1. Mode
  2. LHS (Left Hand Side)
  3. RHS (Right Hand Side)
  4. opts (options)

Modes

One of the first thing you learn in vim is modes, and if you have forgotten about it, then vim has various modes like - Normal Mode, Insert Model, Visual Mode etc.

Normal Mode is the mode which we are in after pressing the escape (esc) key.
Insert Mode is the mode which we are in after pressing a key like i or a.
Visual Mode.. you get the idea, the key is v.
To learn about other modes you can do :help map-modes.

Each of the mode has a short name to it, for example — the normal mode has 'n' as a short name. So we pass in 'n' as the first parameter above.

LHS and RHS

LHS

One of the first thing we think of in a keymap is what key shortcut will we be using, that's what LHS is for
<C-r> stands for CTRL+r, similarly if you want to map something for the alt key you can do <A-r>.

To be honest I have no idea where to get a list of these shortcuts, I just search them up on google and find the shortcuts through Stackoverflow or reading configurations of other people.

RHS

RHS is the command that's going to be called when LHS is used.
Let's break down ":luafile %<CR>"
:luafile % is the command built inside Neovim, it is used to source the luafile, this is pretty straight forward.
<CR> stands for the Enter key, after typing the command :luafile % we press the enter key.
That's oddly precise but it has implications like if you want to execute multiple commands you could do :luafile %<CR> :CustomCommad.

Opts (Options)

There is a table we are passing as the 4rth argument, in case you're unfamilar with lua, lua doesn't have arrays or objects (or dictionaries if you come from Python). It has one single data structure called a table for it all.

The argument looks like { noremap = true, silent = true }, the first parameter noremap stands for no-recursive-map, say you map the key j to jj, so pressing j goes down two lines intead of one (which is a pretty bad keymap), and you don't have noremap true then the mapping will start calling itself like a recursive function and will result in a stack overflow, but with a noremap set to true, j will only go down one line.

The next argument silent = true tells neovim to execute the keymap silently, for e.g. - if we execute a command like :help then after the command is executed we can see the output of the command below the footer of Neovim which is at the bottom. With silent = true the command is simply visible to us after the map is executed.

You can find the official documentation of the nvim_set_keymap function by doing :help nvim_set_keymap().

Abstracting It Out

If you have known anything about syntax used in vimscript for keymaps, then you might think that this is quite a lot of work to define a simple keymap compared to vim.

But we are using Lua, which is a programming language, so let's use this to our advantage and make a few functions that make keymaps easy.

function noremap(mode, lhs, rhs)
    vim.api.nvim_set_keymap(mode, lhs, rhs, { noremap = true, silent = true })
end

function nnoremap(lhs, rhs) noremap('n', lhs, rhs) end

Here we are creating two functions — noremap and nnoremap. I encourage you to add these functions in your keymaps.lua file.

I assume you're familiar with how functions work, if you have some experience with programming the above functions are pretty easy to read.

Now you can just do -

nnoremap"<C-r>", ":luafile %<CR>")

Which is pretty short and sweet. This is exactly what I do in my config.

I import functions like we just made from a file called utils.lua in my config.

You can find other useful keymap functions inside the utils.lua file that I use.

Obligatory explanation of Lua modules

Let's talk about how I import functions from utils.lua now. On the top of utils.lua I make a lua table called M, I have talked about tables in the starting of the Opts (options) section.

This variable has to be a capital letter. At the bottom of the utils.lua file I return this table.

When I do function M.map(...) it the function gets added in the table M.
Let's go to the keymaps.lua file now, the importing is pretty simple.

local Utils = require("utils") lets us get the M table we exported in the utils.lua file. The table contains our useful functions.
I further extract out the functions from Utils by doing local nnoremap = Utils.nnoremap.

I am opininated

A lot of people will have different ways to configure Neovim. Some prefer a single file, some prefer a single file configuration, some mix vimscript with lua, and none of them are wrong. If you feel like you don't want to extract the utility to functions for keymaps to a seperate file then it's totally fine.

Thank You

I am usually not a big fan of huge posts, but I wanted everything about keymaps basics to be in the same post. Hence here we are. Please go on Twitter and tweet about how you felt about this post and tag me @yashguptaz. If you're too shy to tweet then please message me on Twitter. It really helps me with motivation <3