Neovim revamp

October 12, 2023

Recently, I switched to lazy.nvim to manage my Neovim plugins. I’m thus writing yet another post on Vim with a fresh new configuration. Reasons are multiple but quite simple: I wanted a more minimalistic set of config files (ideally one or two Lua files) allowing me to keep my after/ftplugin directory as optional in case I need to transfer my config to other machines; packer looks like it will no longer be in use (it is already archived), like is the case for null-ls.nvim; I still want blazing fast startup time (before moving to that new config, I was well under 30 ms, as measured by hyperfine or vim-startuptime).

TL;DR I got a twofold increase in startup time, but I only need to manage a single lua file now.

~/.config/nvim                                                                                                                                                                                               16m18» hyperfine "nvim --headless +qa" --warmup 5
Benchmark 1: nvim --headless +qa
  Time (mean ± σ):      67.4 ms ±   1.0 ms    [User: 52.3 ms, System: 15.0 ms]
  Range (min … max):    65.9 ms …  70.4 ms    44 runs


Yes, I’m back to the good old era of the 500+ LOC vimrc. In my case, I now have a single init.lua file to manage my plugins and general settings, nicely organized and presented thanks to native (and efficient) Vim folding. I still have various directories lying around, though. Here is the big picture:

» tree -L 1
├── after
├── compiler
├── ftdetect
├── init.lua
├── lazy-lock.json
├── spell
└── templates

5 directories, 2 files

I discarded part of a forked version of mini.nvim that I was using for completion, as well as several hand-made helper functions. Meanwhile I also cleanup stuff dispatched in several Lua files and put stuff in either my after directory, or directly into my init.lua file. Overall, nothing really changed, except that I’m now relying on dedicated packages to manage the colorscheme and statusline of Neovim stable release (v0.9.2 at the time of this writing). Breaking changes are inevitable with “over-the-beta” software, which is why I stopped using the dev version of Neovim in recent months. And since I don’t have the time nor inclination to read the changelog every two weeks, or after every new stable release, I let package maintainers do the right stuff for me. I’ve been using a bare bone custom monochromatic theme for three years now, but as I said in a previous post, the zenbones plugin is quite good and I very much like the zenbones and zenwritten themes on light background. They also render nice on a dark background by the way. Lualine is okay for most part and it fulfills all my requirements.

The biggest issue for me was to replace null-ls1 since it provided me with a bunch of useful linters and fixers but it came out it was not too difficult to get rid of it since conform.nvim and nvim-lint came to the rescue shortly. I am aware it can be done with autocommands as explained on SO or simple mappings (which is what I already have in some of my after/ftplugin files, but these two packages allow to manage linters and formatters in a more comfortable way.

Startup time is a bit longer (60-70 ms instead of 30 ms with my previous config), but I use a different set of plugins so it’s hard to compare. The most notable changes are the addition of auto-installers, like mason.nvim (with mason-lspconfig.nvim and mason-tool-installer.nvim, which works alongside nvim-lspconfig, and linting/formatting packages cited above). I already installed all LSPs, linters and formatters I need using pip, npm, curl or whatever, but the big advantage of this approach is that everything is self-contained so that I can transfer my config files to any other computer and get everything installed right away. Mason-based tools will install everything (using a registry list in the case of Mason itself) within a single click or config line.2 It also means you end up with a huge $HOME/local/share/nvim directory (3.3 Go with 9 LSPs, compared to less than 180 Mo with my previous config). This is not a big deal if you have a large HD, but if you make regular backup using Kopia, you may want to exclude that directory from your hourly or daily backups. As an example, consider the following listing, in the middle of my configuration: some LSPs, formatters and linters take up some space, really:3

$ .local/share/nvim/mason/packages
» du -sh ./* | sort -h
2,8M    ./shfmt
4,0M    ./purescript-language-server
14M     ./stylua
15M     ./shellcheck
19M     ./texlab
20M     ./docformatter
20M     ./isort
27M     ./black
28M     ./pyright
28M     ./sqlfmt
29M     ./clojure-lsp
41M     ./typescript-language-server
44M     ./rust-analyzer
105M    ./r-languageserver
124M    ./clangd
2,8G    ./haskell-language-server

Some after-thoughts: chktex is not available to install via mason-installer while racket-languageserver must be set up manually (it cannot be configured with mason-lsp). This means you still have to add extra stuff unless you submit a patch to the maintainers. You can define an auto-format command with conform, which may render some of your own function call or autocommands useless in your after/ftplugin folder. This means we must be careful with synchronizing all filetype-specific settings. I would prefer that everything could be centralized within conform setup function.

I tried nvim-cmp as a replacement of my personal fork of mini.nvim completion module (this was before the mini.nvim project introduced submodules), but I removed it after a few days. I never really like autocomplete and popup windows after every two keystrokes, and I’m probably fine with Vim’s omni complete (C-x C-o), when I need it.

And then comes nvim-orgmode, which is so great compared to my previous half hand-made configuration. But I will talk a bit more bout this in a separate post.

♪ Bauhaus • Exquisite Corpse

  1. By the end of writing this post, I learned it has been forked as none-ls.nvim↩︎

  2. Compared to nvimlsp-config, Mason uses a different naming convention, so be careful. ↩︎

  3. Of note, the R language server took a lot of time to install, compared to other LSPs. At this point, I’m thinking of removing it since I don’t really need it except for the keywordprg (on-line help), which I can manage by my side. ↩︎

See Also

» Using fzf-lua » Zero-plugin linting and fixing in Neovim » Speeding up Neovim » Unified colors of TUIs » Debugging in Vim