DEV Community

Peter Strøiman
Peter Strøiman

Posted on

3. Essential Keymapping and Settings

Now I am about to write a lot of neovim configuration code, the first configuration will be settings that help me working with the configuration itself.

Read more about keyboard sequences and leader keys

Open and re-source the configuration

As I already mentioned that the number one reason for why I structure my configuration the way I do is because I need to be able to changes, when I'm in my daily work, and I find that something is lacking in my configuration. I need to quickly make the change, and get back to where I was, which is why closing and reopening vim for these kinds of changes is something I really want to avoid.

So the first thing, I do is setup keyboard shortcuts to edit and rerun, or "re-source" the configuration. This tip, I learned from Learn Vimscript The Hard Way

I also want to map my leader key to something easily accessible, and my thumb is always resting on the space bar, so that will be my leader key.

local function reload()
  dofile(vim.env.MYVIMRC)
  print("Configuration reloaded")
end

vim.g.mapleader = " "
vim.g.maplocalleader = " "
vim.keymap.set("n", "<leader>ve", ":tabnew $MYVIMRC<cr>", { desc = "Open neovim configuration file" })
vim.keymap.set("n", "<leader>vs", reload, { desc = "Re-source neovim configuration file" })
Enter fullscreen mode Exit fullscreen mode

Note: while resourcing could have been achieved using :source $MYVIMRC, I will later need to add more behaviour to the reloading, which is why I already have made a function for the behaviour. For more info, see :help :source

For more information on leader keys and mapping sequences, see Leader keys and mapping keyboard sequences

Escape hatch

The default key for exiting insert-mode, <Esc> is a little far away. I have remapped that to jk, a sequence of keys that quick exits to normal mode, 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) - this was also a tip I learned from "Learn Vimscript ...".

vim.keymap.set("i", "jk", "<esc>", { desc = "Exit insert mode" })
Enter fullscreen mode Exit fullscreen mode

If you are used to vim, and want to adopt to this pattern, it can be helpful to remap <Esc>, to the no-op (see :help <nop>)

vim.keymap.set("i", "<esc>", "<nop>")
Enter fullscreen mode Exit fullscreen mode

I had this mapping setup when I first adopted this strategy. Now, it's no longer necessary for me.

Quicker save

After having used Windows for many years, I'm used to <Ctrl>+s for saving a file. And I have remapped the CAPS LOCK key to work as <Ctrl>, so that combination is one that only requires my left pinky to move slightly to the left to reach. I also want to have this mapping available in both normal and insert-mode, as every edit normally ends with a save anyway, i.e. after saving from insert-mode, I'll be back in normal mode for editing.

vim.keymap.set("n", "<C-s>", ":w<cr>", { desc = "Save current file" })
vim.keymap.set("i", "<C-s>", "<esc>:w<cr>", { desc = "Save current file" })
Enter fullscreen mode Exit fullscreen mode

Sensible indentation

While writing the reload function, vim by default inserted a tab. I want spaced, and I want two of them.

vim.opt.expandtab = true
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.softtabstop = 2
Enter fullscreen mode Exit fullscreen mode

Note, that these are now the default settings. Each file can overwrite the settings. E.g. in Go, I do want to have tabs1.

Disable swap file

Vim keeps a "swapfile" that serves as a backup while working, and can help recover unsaved work in the case of a crash. I don't find this very helpful. I save often, and I have version history in git.

The swapfile is not so much a nuisance in neovim as it was in vim, as neovim stores the swapfile away from your working directory. The vim versions I have used stored the swap file in the same folder as the edited file, making it a lot of noise in the file system.

vim.opt.swapfile = false
Enter fullscreen mode Exit fullscreen mode

When connecting to a remote server, a swapfile can be helpful to recover from a broken connection. But tmux can also solve the same problem.

Line numbers

Showing line numbers can be helpful, as it helps you navigate quickly to the desired line, e.g. 30gg or 30G both jump straight to line 30. Relative line numbers on the other hand will show how many lines above or below each line is, often making for a shorter input, e.g. 8j, rather then 128gg.

Combine relativenumber with number to show the absolute line number for the current line, and relative numbers for all other lines

vim.opt.number = true
vim.opt.relativenumber = true
Enter fullscreen mode Exit fullscreen mode

![[Pasted image 20240702110735.png|Screenshot showing the actual line number for the current line, and for all other lines, it shows the number of lines above or below]]

I have previously been a bit annoyed by the constant moving around of the numbers in the gutter, but right now I'm trying out relative numbers. I may disable it again in the future if I'm unhappy with it.

Note: Absolute line numbers may be more helpful for pair programming, as the navigator can quickly reference the concrete line, "I'm not sure the conditional logic on line 30 is correct" (the number remains correct even if the driver moves around at the same time).

Search options

By default, when searching with / or ?, the search is case sensitive. I generally don't want to be bothered with typing the right case. Just that the right letters are in the search should be enough. I set ignorecase to have case insensitive search

When searching, the search results are highlighted, and the command :nohighlight or :noh disables it again. I have setup a shortcut to more quickly dismiss this

vim.opt.ignorecase = true
vim.opt.smartcase = true
vim.keymap.set("n", "<leader>h", vim.cmd.nohlsearch)
Enter fullscreen mode Exit fullscreen mode

Remove useless functions

If the cursor is located on a number, the shortcuts <Ctrl>+a and <Ctrl>+x increments/decrements that number. Not only do I not have any use for this behaviour, <Ctrl>+a is also used to control tmux, which I normally use together with neovim.

When I am unexpectedly not in a tmux session, and I try to control tmux, I have on more than one occasion incremented a number, not realising it until I observe a bug in my code. So I get rid of these two useless mappings

vim.keymap.set("n", "<C-a>", "<nop>")
vim.keymap.set("n", "<C-x>", "<nop>")
Enter fullscreen mode Exit fullscreen mode

A note on termguicolors

Other tutorials often set the termguicolors. This shouldn't be necessary in neovim, only vim. By default neovim detects if your terminal supports 24-bit colours. If you find that colours are off if you don't enable this setting it's more likely that it's your terminal is misconfigured, not neovim. From :help termguicolors

Nvim will automatically attempt to determine if the host terminal
supports 24-bit color and will enable this option if it does
(unless explicitly disabled by the user).

Coming up

Now, I have the bare essentials up and running, and now is a good time to commit to the git repository. That's a task I want to perform from within neovim itself, so in the next part in the series, I will add git support to neovim, which again requires some kind of package management, so I'll also add a package manager rather than managing that by myself (although that is perfectly doable).


  1. Go is so opinionated about formatting that there is only one way to format indentation, and that is using tabs. You can configure your editor to how you want it to look. It still uses spaces for alignment, ensuring it is not dependent on editor settings. 

Top comments (0)