1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
# 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
```sh
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](https://github.com/folke/lazy.nvim) 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 `opts` option, `config` isn't needed: lazy sees the option and automatically calls `require("plugin").setup(opts)` with the given options.
- Setting `config` to `true`, which tells lazy to call `require("plugin").setup()` with no options.
- Setting `config` to a function where I configure everything directly.
- Setting `config` to 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.
```lua
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](https://github.com/craftzdog/solarized-osaka.nvim) 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](https://rubjo.github.io/victor-mono).
I use the same theme in my Kitty terminal, where the font is configured.
For symbols I complement it with [Nerd Fonts](https://www.nerdfonts.com/).
## 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](https://github.com/mason-org/mason.nvim) 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.lua` and `./lua/pi/lsp/servers/`: the most important part, where servers are registered using the same names as _lspconfig_ ([ref](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md)). `default.lua` holds the list of enabled servers; most use the default configuration, but those that need something extra have their own `servers/<name>.lua` file 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](https://github.com/saghen/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](https://github.com/milanglacier/minuet-ai.nvim) 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).
|