Neovim Configuration
This is my Neovim configuration, the text editor I use for programming. I use it every day.
The goal of this configuration is to help me in my daily work by turning Neovim into the best possible tool for programming.
Installation
git clone https://git.all.ar/pub/nvim-conf.git ~/.config/nvim
Repository: https://git.all.ar/pub/nvim-conf
Neovim
I always use the latest version of Neovim (currently 0.13), building it from source about once a week (maybe more often if I'm bored, haha). I keep replacing plugins with native Neovim functionality whenever possible: the statusline, colorscheme, LSP and treesitter no longer depend on external plugins for the basics.

Options, Autocommands and Keymaps
Editor options live in ./lua/config/options.lua, and are loaded at startup together with the colorscheme and statusline.
Editor keymaps (not plugin-related ones) live in ./lua/config/keymaps.lua.
Autocommands I want to register live in ./lua/config/autocmds.lua.
The same directory holds the "Diagnostic" configuration, where I set the icons shown for errors coming from LSP or other tools. Since Neovim handles diagnostics as a separate module, I like to keep it on its own.
Autocommands, user commands and keymaps are loaded on the VeryLazy event through an autocommand in ./lua/config/init.lua.
Plugins
I use lazy as the plugin manager; its setup is in ./lua/config/lazy.lua.
I use lazy's ability to take a directory, ./lua/plugins/, as the source of plugin specs.
I try to configure one plugin per file, naming the file after the plugin or the feature it provides.
Note that there is also ./lua/plugins/init.lua, which holds the plugins I haven't split out, or that don't have enough logic to deserve their own one-line file.
Configuration
To configure plugins I use lazy's config option, which can be defined in the following ways:
- Using the
optsoption,configisn't needed: lazy sees the option and automatically callsrequire("plugin").setup(opts)with the given options. - Setting
configtotrue, which tells lazy to callrequire("plugin").setup()with no options. - Setting
configto a function where I configure everything directly. - Setting
configto a function that calls another file, such as./lua/pi/lsp, when the configuration is long and I don't want it all inline.
Lazy loading
Since the package manager is called lazy, I can't skip one of its most important features: configuring plugins so they only load when they're needed.
Many plugins are only needed at certain moments, so it makes no sense to load them at startup when we don't even know whether they'll be used.
As an example, take ./lua/plugins/neogen.lua, which generates documentation comments for the function or class under the cursor.
It fits the case above: I don't want it loaded when Neovim starts.
return {
"danymat/neogen",
dependencies = "nvim-treesitter/nvim-treesitter",
cmd = { "Neogen" },
keys = { { "<leader>n", ":Neogen<cr>", desc = "Add comment to the near possible object" } },
opts = { snippet_engine = "luasnip" },
}
To achieve this I use the keys property, which serves two purposes:
- It tells lazy that the plugin should only load when that key combination is pressed.
- If it has a second element, it's used as the value or function for the keymap, so there's a single place to define the plugin's keymaps and lazy knows about them.
Another way to lazy load is the cmd option, which works like keys but takes the commands that trigger loading the plugin and then run.
Setting lazy = true explicitly tells lazy not to load the plugin until another plugin requires it, which is useful for libraries.
The last one is loading on events. Events are signals Neovim emits, and here we use them to trigger loading the plugin. In my configuration I use VeryLazy, a lazy event that fires once Neovim has loaded and the user has control. At that point other plugins start loading in the background.
I use it for things like the LSP, snippets and completion.
Colorscheme, statusline and fonts
The colorscheme is a native implementation based on the Solarized Osaka palette, in ./lua/config/native-colorscheme.lua.
The statusline is native too (it replaces lualine) and uses the same palette, in ./lua/config/statusline.lua.
For the font I use Victor Mono.
I use the same theme in my Kitty terminal, where the font is configured.
For symbols I complement it with Nerd Fonts.
LSP language support
Neovim implements an LSP (Language Server Protocol) client. This gives us rich interaction with many languages without needing a different plugin for each one. Neovim itself knows nothing about the languages we use; it just knows how to act as a client. It's up to us to install the right server for each language and tell Neovim how we want to interact with it. My configuration is split into the following parts:
./lua/plugins/lsp.lua: where I define the LSP-related packages I use../lua/pi/lsp: the directory with my LSP configuration../lua/pi/lsp/init.lua: the first file to load. It registers every enabled server using the native LSP client, without nvim-lspconfig or mason-lspconfig. mason is only kept as an optional installer for binaries such as debug adapters (./lua/pi/lsp/tools.lua). It then applies each server's specific configuration. Ideally this file doesn't need to be modified../lua/pi/lsp/attach.lua: a more interesting file, where I set up the LSP-related mappings. They're only registered for buffers that have an attached LSP server. This is where you can change keybindings or register new functions../lua/pi/lsp/default.luaand./lua/pi/lsp/servers/: the most important part, where servers are registered using the same names as lspconfig (ref).default.luaholds the list of enabled servers; most use the default configuration, but those that need something extra have their ownservers/<name>.luafile returning a function with the required parameters.
Treesitter
I use nvim-treesitter on its main branch, which only installs parsers and provides queries. Highlighting, indentation, folds and injections are provided natively by Neovim; the hook-up is done with a FileType autocommand in ./lua/pi/treesitter.lua, which also holds the list of parsers I always want installed.
Completion
For completion I use blink.cmp.
Its configuration is in ./lua/plugins/completition.lua, where I define the keymaps and the integration with the different sources such as LSP, path, LuaSnip, LaTeX, and local AI completion via minuet-ai against a llama-server.
Snippets
For snippets I use LuaSnip, configured in ./lua/plugins/snippets.lua.
That file doesn't hold the snippets themselves, only how they behave. The snippets live in ./lua/pi/snips/ft/, which has one file per filetype; they're registered automatically when I add a new file (reload with <leader><leader>s, or restart Neovim).