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 as my keyboard layout with partial remaps
(fr).
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 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, 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 and
lsp. 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 which decided not to
work for some languages… While it's not an absolute rule (for instance, I'm
using vimtex 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
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.
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
, 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
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_APPNAME
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_APPNAME
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.
I started using git from the start in order to remember what I did by using its history. 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, a core developer of Neovim, author
of telescope.nvim and content
creator about Neovim. You can see a quick presentation on his YouTube channel
[here].
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 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.
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:
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 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.
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.
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:
-- 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_APPNAME=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 (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;
- 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
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.
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.
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.
Now, rinse and repeat for each plugin/specific configuration set: vimtex
,
vim-pandoc-syntax
(which I mainly use for the
concealer), 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: mz[s1z=`z
. 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
which triggers
when the option spell
is set.
To see the resulting configuration, see these two files:
autocommands.lua
for the autocommand setting, and
spelling.lua
for the utils module.
Just for the record, this is what it does:
- Store the current cursor location:
mz
sets a mark z on current position; - Go to the previous spelling error:
[s
; - Pick the first spelling suggestion:
1z=
; - Go back to the stored location:
`z
jumps to mark 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
,
before because of its accessibility
in bépo, disabling quite a useful motion
binding, 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.
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
in the $VIMHOME/lua/lsp-configure.lua
file.
Final thoughts
To conclude, I would like to say thanks to the French
tuppervim community, which regularly organises meetings
where we can show our latest configuration file, or just exchange nice tips. I
discovered both TJ DeVries and
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 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 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!