3. Essential Keymapping and Settings
Tags: neovim, vim
Published: 2024-07-03 09:29:30

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](https://dev.to/stroiman/leader-keys-and-mapping-keyboard-sequences-3ehm)

## 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](https://learnvimscriptthehardway.stevelosh.com/chapters/07.html)

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.

```lua
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" })
```

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, <kbd>&lt;Esc&gt;</kbd> is a little far away. I have remapped that to <kbd>jk</kbd>, 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 ...".

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

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

```lua
vim.keymap.set("i", "<esc>", "<nop>")
```

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 <kbd>&lt;Ctrl&gt;+s</kbd> for saving a file. And I have remapped the <kbd>CAPS LOCK</kbd> key to work as <kbd>&lt;Ctrl&gt;</kbd>, 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_.

```lua
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" })
```

## Sensible indentation

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

```lua
vim.opt.expandtab = true
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.softtabstop = 2
```

Note, that these are now the default settings. Each file can overwrite the settings. E.g. in Go, I do want to have tabs[^1].

## 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.

```lua
vim.opt.swapfile = false
```

When connecting to a remote server, a swapfile _can_ be helpful to recover from a broken connection. But [tmux](https://github.com/tmux/tmux/wiki) 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. <kbd>30gg</kbd> or <kbd>30G</kbd> 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. <kbd>8j</kbd>, rather then <kbd>128gg</kbd>.

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

```lua
vim.opt.number = true
vim.opt.relativenumber = true
```

![[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 <kbd>/</kbd> or <kbd>?</kbd>, 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)
```

## Remove useless functions

If the cursor is located on a number, the shortcuts <kbd>&lt;Ctrl&gt;+a</kbd> and <kbd>&lt;Ctrl&gt;+x</kbd> increments/decrements that number. Not only do I not have any use for this behaviour, <kbd>&lt;Ctrl&gt;+a</kbd> is also used to control [tmux](https://github.com/tmux/tmux/wiki), 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

```lua
vim.keymap.set("n", "<C-a>", "<nop>")
vim.keymap.set("n", "<C-x>", "<nop>")
```


## 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.