2023-12-25 16:46:56 +00:00
|
|
|
|
---
|
|
|
|
|
Title: Setup Neovim with kickstart.nvim
|
2023-12-25 17:14:41 +00:00
|
|
|
|
Date: 2023-12-25 17:15
|
2023-12-25 16:46:56 +00:00
|
|
|
|
Lang: en
|
|
|
|
|
Author: Fabrice
|
|
|
|
|
Category: software
|
|
|
|
|
Tags: vim, neovim, setup
|
|
|
|
|
Slug: nvim-kickstart
|
|
|
|
|
table-of-contents: true
|
|
|
|
|
Header_Cover: ../images/covers/antennae.jpg
|
|
|
|
|
Summary: How to create a sane Neovim configuration with kickstart.nvim as a
|
|
|
|
|
starting point.
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# Introduction
|
|
|
|
|
|
|
|
|
|
## How I managed my configuration
|
|
|
|
|
|
|
|
|
|
When I started using Vim, I started editing my `.vimrc` bit by bit and
|
|
|
|
|
incrementally before it starts getting too big for me to find anything inside
|
|
|
|
|
it and not using even half of the plugins I installed. That goes without saying,
|
|
|
|
|
there were quite a bit on conflicting keymaps as well as I'm using
|
|
|
|
|
[bépo](http://bepo.fr/) as my keyboard layout with [partial remaps
|
|
|
|
|
(fr)](https://cdn.bepo.fr/Vim-bepo-066.png).
|
|
|
|
|
|
|
|
|
|
Obviously, it slowly became quite a mess. To address this issue, I
|
|
|
|
|
decided to reorganise my `$HOME/.config/vim` directory using the [vim directory
|
|
|
|
|
structure](www.panozzaj.com/blog/2011/09/09/vim-directory-structure/) and did
|
|
|
|
|
some cleanup at this point of time. I think it was also around this period that
|
|
|
|
|
I discovered that Vim8 added a native package manager that I started to use.
|
|
|
|
|
Thus, at this point, I started organising my configuration with semantic files,
|
|
|
|
|
such as `$VIMHOME/plugin/spelling.vim` to manage my spelling configuration for
|
|
|
|
|
instance. This approach makes debugging easier, and also checking custom
|
|
|
|
|
keyboard shortcuts easier, as I just have to check
|
|
|
|
|
`$VIMHOME/plugin/omnicomplete.vim` for instance to know which shortcuts I set up
|
|
|
|
|
when I'm still getting the habits of using them.
|
|
|
|
|
|
|
|
|
|
At some point of time, I moved to Neovim, and I simply moved my configuration
|
|
|
|
|
from Vim to Neovim and continue on adding more and more plugins on top of each
|
|
|
|
|
other depending on my hype, especially because the world of Neovim plugins
|
|
|
|
|
opened up to me. Needless to say that less than half of these plugins were put
|
|
|
|
|
into good use. Which leads to my first configuration big cleanup.
|
|
|
|
|
|
|
|
|
|
Six months ago, I wiped my frankenconfig, and started back from scratch in
|
|
|
|
|
[lua](https://lua.org/about.html), with the same structural approach as
|
|
|
|
|
previously, but now wondering if the plugin would be useful or not. Since my
|
|
|
|
|
first time using Vim, there were some big changes in the vim ecosystem,
|
|
|
|
|
especially in language management with
|
|
|
|
|
[tree-sitter](https://tree-sitter.github.io/tree-sitter/) and
|
|
|
|
|
[lsp](https://en.wikipedia.org/wiki/Language_Server_Protocol). These two bring
|
|
|
|
|
into the environment a unified way to manage languages without having to depend
|
|
|
|
|
on language-specific plugins, henceforth I didn't need specific plugins to have
|
|
|
|
|
nice syntax coloration for obscure languages anymore, or get frustrated with
|
|
|
|
|
[omnicomplete](https://vim.fandom.com/wiki/Omni_completion) which decided not to
|
|
|
|
|
work for some languages… While it's not an absolute rule (for instance, I'm
|
|
|
|
|
using [vimtex]({filename}./nvim-latex.md) for latex, which includes a more
|
|
|
|
|
accurate syntax coloring than tree-sitter). I also moved from the native vim way
|
|
|
|
|
of managing plugins to use [`Lazy`](https://github.com/folke/lazy.nvim) as a
|
|
|
|
|
proper plugin manager, which helped me synchronize my configuration between my
|
|
|
|
|
different computers. It was working nice and well, with some weird bugs (see
|
|
|
|
|
below) on first install, but as it was punctual… I just ignored it.
|
|
|
|
|
|
|
|
|
|
```plain
|
|
|
|
|
E5113: Error while calling lua chunk:
|
|
|
|
|
$VIMHOME/nvim/init.lua:13: E21: Cannot make changes, 'modifiable' is off
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
However, I was unhappy with some of my configurations, and if I managed to have
|
|
|
|
|
something functional, there were many details that annoy me that stemmed for
|
|
|
|
|
some configuration I wrote some times ago and of course didn't document. This
|
|
|
|
|
leads us to today, where I just decided to use
|
|
|
|
|
[`kickstart.nvim`](https://github.com/nvim-lua/kickstart.nvim), which is a
|
|
|
|
|
well-documented vim starting configuration (it's not a distribution, it still
|
|
|
|
|
requires your input to obtain something that fits your needs), which was exactly
|
|
|
|
|
what I needed to start anew… but not fully from scratch.
|
|
|
|
|
|
|
|
|
|
## The migration
|
|
|
|
|
|
|
|
|
|
To move my configuration from `kickstart.nvim`, I wanted to get the best of both
|
|
|
|
|
world. For instance, I didn't want to have an
|
|
|
|
|
[`init.lua`](https://github.com/nvim-lua/kickstart.nvim/blob/master/init.lua)
|
|
|
|
|
that is over 600 lines long. I thus decided to split it into short files that
|
|
|
|
|
manages a specific part of the configuration: completion, lsps, treesitter,
|
|
|
|
|
mappings after reading the different configuration default from nvim-kickstart
|
|
|
|
|
and changing what I disliked. To do that, I started with using the
|
|
|
|
|
[`NVIM_APP`](https://practical.li/neovim/configuration/) environment option in
|
|
|
|
|
order to make the move in a non-destructive way. After installing the bare
|
|
|
|
|
minimum to make it usable for me (as a bépo user), I exported the `NVIM_APP`
|
|
|
|
|
variable to start using my configuration to help me debug it on the fly.
|
|
|
|
|
I also decided to write this blog post to remember the process and maybe helped
|
|
|
|
|
some people who want to configure their text editor.
|
|
|
|
|
|
|
|
|
|
Note that in the following, we will assume that the reader is already familiar
|
|
|
|
|
with Neovim and lua.
|
|
|
|
|
|
|
|
|
|
# Configuring Neovim
|
|
|
|
|
|
|
|
|
|
My (in use) configuration for Neovim is available [here](https://git.epheme.re/fmouhart/nvim-config-kickstart).
|
|
|
|
|
|
|
|
|
|
I started using git from the start in order to remember what I did by using its
|
|
|
|
|
[history](https://git.epheme.re/fmouhart/nvim-config-kickstart/commits/branch/master).
|
|
|
|
|
As it's not the easier thing to read however, here follows my rationals, and
|
|
|
|
|
thought during this process in a chronological order.
|
|
|
|
|
|
|
|
|
|
## kickstart.nvim
|
|
|
|
|
|
|
|
|
|
`kickstart.nvim` is a starting Neovim configuration file which was created by
|
|
|
|
|
[TJ DeVries](https://github.com/tjdevries), a core developer of Neovim, author
|
|
|
|
|
of [telescope.nvim](https://github.com/nvim-lua/telescope.nvim) and content
|
|
|
|
|
creator about Neovim. You can see a quick presentation on his YouTube channel
|
|
|
|
|
[[here]](https://www.youtube.com/watch?v=stqUbv-5u2s).
|
|
|
|
|
|
|
|
|
|
To summarise, it is a starting configuration including a minimal set of plugins
|
|
|
|
|
that helps to have a modern editor, that has a working and customizable LSP
|
|
|
|
|
configuration with [Mason](https://github.com/williamboman/mason.nvim) to help
|
|
|
|
|
install LSP servers, git helpers, completion, telescope, and a choice of
|
|
|
|
|
shortcuts that are quite natural to learn (unlike what I used previously because
|
|
|
|
|
I was simply adding shortcuts one after another without thinking of the
|
|
|
|
|
compatibility between them).
|
|
|
|
|
|
|
|
|
|
Note that it is made for educational purpose, and thus is not modularised as is
|
|
|
|
|
(hence the single self-contained `init.lua` file). Which leads us to our first
|
|
|
|
|
step after simply pasting the content of `init.lua` into the `$VIMHOME/init.lua`
|
|
|
|
|
file.
|
|
|
|
|
|
|
|
|
|
## Modular configuration
|
|
|
|
|
|
|
|
|
|
When in doubt about some shortcuts, I'm under the habit of going to read the
|
|
|
|
|
corresponding configuration file in my `$VIMHOME/plugin` directory.
|
|
|
|
|
`kickstart.nvim` includes `which-key`, that is a plugin that pops a helper when
|
|
|
|
|
waiting for a command as shown hereunder.
|
|
|
|
|
|
|
|
|
|
[![which-key plugin
|
|
|
|
|
illustration](../images/nvim-which-keys.png)](../images/nvim-which-keys.png)
|
|
|
|
|
|
|
|
|
|
Thanks to that, I start getting rid of this habit. However, having a modular
|
|
|
|
|
configuration helps debugging it. Usually, when an error spawns, the filename
|
|
|
|
|
and location of what has triggered it appears in the stack trace, and it's
|
|
|
|
|
easier to search in a short file than a thousand-line long one.
|
|
|
|
|
|
|
|
|
|
After a first read of the configuration file, I decided to split it into smaller
|
|
|
|
|
files. Note that if you want to start directly from there a project that does
|
|
|
|
|
exactly that exists:
|
|
|
|
|
|
|
|
|
|
* [kickstart-modular.nvim](https://github.com/dam9000/kickstart-modular.nvim)
|
|
|
|
|
|
|
|
|
|
However, I find it easier for educational purpose to have everything in one
|
|
|
|
|
place to linearly read it first.
|
|
|
|
|
|
|
|
|
|
The process was quite simple, as the file was already divided logically into
|
|
|
|
|
components that make sense, I just had to take the content of those sections and
|
|
|
|
|
move them into the `$VIMHOME/lua` folder before including them in `init.lua`. I
|
|
|
|
|
hesitated to continue using the `$VIMHOME/plugin` directory for that, but I then
|
|
|
|
|
realised that having it inside init.lua allows having a structure that allows
|
|
|
|
|
using `init.lua` as an index, and I can start
|
|
|
|
|
[jumping](https://vimhelp.org/motion.txt.html) from there to access my
|
|
|
|
|
specific configurations.
|
|
|
|
|
|
|
|
|
|
To illustrate it, let's take the example of completion. In `kickstart.nvim`,
|
|
|
|
|
there is a section called "Configure nvim-cmp", that deleted and pasted into a
|
|
|
|
|
file `$VIMHOME/lua/complete.lua` before adding the line `require('complete')` to
|
|
|
|
|
load it. You can see the result in this
|
|
|
|
|
[commit](https://git.epheme.re/fmouhart/nvim-config-kickstart/commit/7ce423fade9d6877b2e9174dd9b9dea36254ac19).
|
|
|
|
|
|
|
|
|
|
## Survival
|
|
|
|
|
|
|
|
|
|
Now that it's done, I need my basic keymaps for using Vim/Neovim in bépo. I
|
|
|
|
|
added the file `$VIMHOME/lua/bepo.lua` and simply load it with a line
|
|
|
|
|
`require('bepo')` in my `$VIMHOME/init.lua` file.
|
|
|
|
|
|
|
|
|
|
I also merged my personal remap inside the `$VIMHOME/lua/mappings.lua` file
|
|
|
|
|
which already contained the ones imported from `kickstart.nvim` from the
|
|
|
|
|
previous step. These mappings are convenient ones such as the following one to
|
|
|
|
|
easily open folds to a given level.
|
|
|
|
|
|
|
|
|
|
```lua
|
|
|
|
|
local keymap = vim.keymap.set
|
|
|
|
|
|
|
|
|
|
-- z0…z9 to open folds to a certain level
|
|
|
|
|
for i=0,9 do
|
|
|
|
|
keymap('n', 'z' .. i , ':set fdl=' .. i .. '<CR>', {noremap = true, silent = false})
|
|
|
|
|
end
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
I also merged and cleaned redundant general options in the
|
|
|
|
|
`$VIMHOME/lua/general-options.lua` file. For instance to ignore folded content
|
|
|
|
|
when jumping between paragraphs for instance, there is the following line in the
|
|
|
|
|
aforementioned file:
|
|
|
|
|
|
|
|
|
|
```lua
|
|
|
|
|
-- folds
|
|
|
|
|
vim.g.ip_skipfold=true
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Once all of that is done, at this point of time, I started moving to use the
|
|
|
|
|
configuration by exporting `NVIM_APP=new_nvim` inside my `.zshrc`. The idea is
|
|
|
|
|
that now I bootstrapped my Neovim config to proficiently edit the configuration,
|
|
|
|
|
which in lua also uses LSP and many of `kickstart.nvim` features. During this
|
|
|
|
|
process I notice what I liked and disliked to know how to edit the configuration
|
|
|
|
|
while editing the configuration.
|
|
|
|
|
|
|
|
|
|
## Importing my former configuration
|
|
|
|
|
|
|
|
|
|
After having the minimal setup top edit a configuration, I now need to make
|
|
|
|
|
things work for other things as well.
|
|
|
|
|
|
|
|
|
|
That is dependent of your workflow. For reference, I personally use Neovim to:
|
|
|
|
|
|
|
|
|
|
* Write text in [markdown](https://daringfireball.net/projects/markdown/) (such as what I'm currently doing)
|
|
|
|
|
for different purposes;
|
|
|
|
|
* blog post, emails or more generally text blocks that will be exported in
|
|
|
|
|
html.
|
|
|
|
|
* Read text written in Markdown;
|
|
|
|
|
* Try to organise my life using [neorg](https://github.com/nvim-neorg/neorg);
|
|
|
|
|
* [LaTeX](https://en.wikipedia.org/wiki/LaTeX) documents and slideshows;
|
|
|
|
|
* Write code in a variety of languages.
|
|
|
|
|
|
|
|
|
|
To do that I went to my previous configuration (which fortunately was already
|
|
|
|
|
using [`Lazy`](https://github.com/folke/lazy.nvim) as a plugin manager). To do
|
|
|
|
|
that, I picked my specific plugins, for instance `Neorg`, to import the
|
|
|
|
|
configuration. For the example of `Neorg` it has multiple steps as I had a
|
|
|
|
|
`$VIMHOME/plugin/neorg.lua` that contained my general configuration and
|
|
|
|
|
`$VIMHOME/ftplugin/norg.lua` which has specific configuration when editing a
|
|
|
|
|
note in `Neorg`.
|
|
|
|
|
|
|
|
|
|
After asking `Lazy` to install `Neorg`, I first imported the general
|
|
|
|
|
configuration from my previous `plugin` folder in my new `lua` folder, as
|
|
|
|
|
depicted by this
|
|
|
|
|
[commit](https://git.epheme.re/fmouhart/nvim-config-kickstart/commit/0e8587b461b67082c1e34ef9cb07180ccfee9f8b).
|
|
|
|
|
|
|
|
|
|
After wondering if I should create a `ftplugin` directory, I finally decided to
|
|
|
|
|
move to autocommands to manage different filetypes. The reason behind that was
|
|
|
|
|
that I had a limited amount of lines in total in my former `ftplugin` directory,
|
|
|
|
|
and the subdivision with `augroup` and `autocmd` in Vim makes it reasonably
|
|
|
|
|
readable. Which brought me to this
|
|
|
|
|
[commit](https://git.epheme.re/fmouhart/nvim-config-kickstart/commit/c506a7ea7868ba80dc053a59cbb66c5efa666e2c).
|
|
|
|
|
|
|
|
|
|
Then some sanity and cleanup have been made. For example, adding a description
|
|
|
|
|
field to my key maps so that `which-key` nicely prints them. See this
|
|
|
|
|
[commit](https://git.epheme.re/fmouhart/nvim-config-kickstart/commit/689bb2024d97fdc9e5e656517f00e446e95ae198).
|
|
|
|
|
|
|
|
|
|
Now, rinse and repeat for each plugin/specific configuration set: `vimtex`,
|
|
|
|
|
`vim-pandoc-syntax` (which I mainly use for the
|
|
|
|
|
[concealer](https://vimhelp.org/syntax.txt.html#conceal)), spelling
|
|
|
|
|
configuration, etc.
|
|
|
|
|
|
|
|
|
|
All the while keeping a critical eye on what I'm moving. For instance, I have a
|
|
|
|
|
mapping on the following command to fix typo on a misspelled word under the
|
|
|
|
|
cursor when writing text: <code>mz[s1z=\`z</code>. However, the key was bound at
|
|
|
|
|
anytime, even when spelling was not enabled. To fix that, we changed the way the
|
|
|
|
|
binding was called: instead of being called everytime, we embedded it inside an
|
|
|
|
|
[`autocmd`](https://vimhelp.org/autocmd.txt.html#autocommands) which [triggers
|
|
|
|
|
when the option](https://vimhelp.org/autocmd.txt.html#OptionSet) `spell` is set.
|
|
|
|
|
To see the resulting configuration, see these two files:
|
|
|
|
|
[`autocommands.lua`](https://git.epheme.re/fmouhart/nvim-config-kickstart/src/commit/d0afa1066cabab3d2b0aa7e2e84a267ce0532c61/lua/autocommands.lua#L32-L37)
|
|
|
|
|
for the autocommand setting, and
|
|
|
|
|
[`spelling.lua`](https://git.epheme.re/fmouhart/nvim-config-kickstart/src/commit/d0afa1066cabab3d2b0aa7e2e84a267ce0532c61/lua/spelling.lua)
|
|
|
|
|
for the utils module.
|
|
|
|
|
|
|
|
|
|
Just for the record, this is what it does:
|
|
|
|
|
|
|
|
|
|
1. Store the current cursor location: `mz` [sets a
|
|
|
|
|
mark](https://vimhelp.org/motion.txt.html#mark) z on current position;
|
|
|
|
|
2. [Go to the previous spelling error](https://vimhelp.org/spell.txt.html#%5Bs): `[s`;
|
|
|
|
|
3. [Pick the first spelling suggestion](https://vimhelp.org/spell.txt.html#z%3D): `1z=`;
|
|
|
|
|
4. Go back to the stored location: <code>\`z</code> [jumps to
|
|
|
|
|
mark](https://vimhelp.org/motion.txt.html#%60) z at the right column.
|
|
|
|
|
|
|
|
|
|
## Adjusting the configuration
|
|
|
|
|
|
|
|
|
|
While testing the default behaviour of `kickstart.nvim`, which changes quite a
|
|
|
|
|
few things for me, I realised that some of them were quite smart, such as
|
|
|
|
|
<Space> as the leader key, which was on `,` before because of its accessibility
|
|
|
|
|
in bépo, disabling quite a [useful motion
|
|
|
|
|
binding](https://vimhelp.org/motion.txt.html#%2C), some are more personal
|
|
|
|
|
tastes, such as the default register to be the system one or not.
|
|
|
|
|
|
|
|
|
|
I thus tried some of these options and decided while editing the configuration
|
|
|
|
|
and writing this blog post which one where working nicely for me (with the help
|
|
|
|
|
of `which-key` to help me during this whole process), and which one were not
|
|
|
|
|
quite working (`unnamedplus` as default clipboard, I really use both separately,
|
|
|
|
|
and I don't want to have my system clipboard polluted)
|
|
|
|
|
|
|
|
|
|
Moreover, `:healthcheck which-keys` was really helpful to debug some colliding
|
|
|
|
|
key bindings, especially because of bépo, which has been incrementally fixed
|
|
|
|
|
while editing the configuration. I already wrote a blog post about how I handle
|
|
|
|
|
those in [vimtex]({filename}./nvim-latex.md).
|
|
|
|
|
|
|
|
|
|
My former configuration also featured LSP, but Mason was not used, which made me
|
|
|
|
|
install my LSP server from my system package manager. However, I still prefer
|
|
|
|
|
using the system one for some languages that features some changes between
|
|
|
|
|
versions, which I [also
|
|
|
|
|
configured](https://git.epheme.re/fmouhart/nvim-config-kickstart/src/commit/d0afa1066cabab3d2b0aa7e2e84a267ce0532c61/lua/lsp.lua#L120-L149)
|
|
|
|
|
in the `$VIMHOME/lua/lsp-configure.lua` file.
|
|
|
|
|
|
|
|
|
|
# Final thoughts
|
|
|
|
|
|
|
|
|
|
To conclude, I would like to say thanks to the French
|
|
|
|
|
[tuppervim](https://tuppervim.org) community, which regularly organises meetings
|
|
|
|
|
where we can show our latest configuration file, or just exchange nice tips. I
|
|
|
|
|
discovered both [TJ DeVries](https://www.youtube.com/c/TJDeVries) and
|
|
|
|
|
[`kickstart.nvim`](https://github.com/nvim-lua/kickstart.nvim) there.
|
|
|
|
|
|
|
|
|
|
I still have to get rid of some habits (such as the comma as a leader key) and
|
|
|
|
|
get used to it, but I'm happy with the change so far, beside knowing exactly
|
|
|
|
|
what is in my configuration, it also helped me fix some weird key conflicts
|
|
|
|
|
while editing markdown, making writing this blog post quite pleasant.
|
|
|
|
|
|
|
|
|
|
While trying the Git-related key bindings utilities bundled with
|
|
|
|
|
`kickstart.nvim`, while being quite minimal, it still filled my needs
|
|
|
|
|
(especially adding a hunk from visual selection, which is helpful to split
|
|
|
|
|
commits into sub-blocks when `git add -p` would have been quite tedious to use).
|
|
|
|
|
|
|
|
|
|
The [status bar](https://github.com/nvim-lualine/lualine.nvim) was also a
|
|
|
|
|
pleasant surprise for me. It is exactly the kind of things I find useful but a
|
|
|
|
|
pain to configure. I may tweak it a bit in the future, but so far it's fine as
|
|
|
|
|
it is.
|
|
|
|
|
|
|
|
|
|
The configuration will continue to evolve from this point, as my use of computer
|
|
|
|
|
and Neovim will change as well. And to finish, I think what TJ Devries said in
|
|
|
|
|
[this video](https://www.youtube.com/watch?v=QMVIJhC9Veg) about text editor is
|
|
|
|
|
quite on point: you don't have to spend time in your configuration if it is not
|
|
|
|
|
fun for you, just take something that works for you. I actually took the time to
|
|
|
|
|
do it because I find it interesting and fun 🙂
|
|
|
|
|
|
|
|
|
|
If you also find it fun, and want to try it, I strongly encourage you to take a
|
|
|
|
|
cup of hot cocoa, put on some relaxing music, and just dive head first!
|