diff --git a/content/images/nvim-which-keys.png b/content/images/nvim-which-keys.png new file mode 100644 index 0000000..58802c6 Binary files /dev/null and b/content/images/nvim-which-keys.png differ diff --git a/content/software/nvim-configure.md b/content/software/nvim-configure.md new file mode 100644 index 0000000..9b0f7ff --- /dev/null +++ b/content/software/nvim-configure.md @@ -0,0 +1,327 @@ +--- +Title: Setup Neovim with kickstart.nvim +Date: 2023-12-25 14: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 .. '', {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: 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`](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: \`z [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 + 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!