mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-08-27 02:34:53 +00:00
424 lines
16 KiB
Markdown
424 lines
16 KiB
Markdown
# Neovim {#neovim}
|
|
|
|
Install `neovim-unwrapped` to get a bare-bones Neovim to configure imperatively.
|
|
This is the closest to what you encounter on other distributions.
|
|
|
|
`neovim` is a wrapper around Neovim with some extra configuration, for
|
|
instance, to set the various language providers like Python.
|
|
The wrapper can be further configured to include your favorite plugins and
|
|
configurations for a reproducible neovim across machines.
|
|
See the next section for more details.
|
|
|
|
## Custom configuration {#neovim-custom-configuration}
|
|
|
|
There are two wrappers available to provide additional configuration around the vanilla package `pkgs.neovim-unwrapped`:
|
|
1. `wrapNeovim`: the historical one you should use
|
|
2. `wrapNeovimUnstable` intended to replace the former. It has more features but
|
|
the interface is not stable yet.
|
|
|
|
You can configure the former via:
|
|
|
|
```nix
|
|
neovim.override {
|
|
withPython3 = true; # see `:h g:python3_host_prog`
|
|
withNodeJs = false;
|
|
withRuby = false;
|
|
configure = {
|
|
customRC = ''
|
|
" here your custom viml configuration goes!
|
|
'';
|
|
packages.myVimPackage = with pkgs.vimPlugins; {
|
|
# See examples below on how to use custom packages.
|
|
start = [ ];
|
|
# If a Vim plugin has a dependency that is not explicitly listed in
|
|
# `opt`, that dependency will always be added to `start` to avoid confusion.
|
|
opt = [ ];
|
|
};
|
|
};
|
|
}
|
|
```
|
|
`myVimPackage` is an arbitrary name for the generated package. You can choose any name you like.
|
|
|
|
If you want to use `neovim-qt` as a graphical editor, you can configure it by overriding Neovim in an overlay
|
|
or passing it an overridden Neovim:
|
|
|
|
```nix
|
|
neovim-qt.override {
|
|
neovim = neovim.override {
|
|
configure = {
|
|
customRC = ''
|
|
" your custom viml configuration
|
|
'';
|
|
};
|
|
};
|
|
}
|
|
```
|
|
|
|
You can use the new unstable wrapper but the interface may change:
|
|
- `autoconfigure`: certain plugins need a custom configuration to work with Nix.
|
|
For instance, `sqlite-lua` needs `g:sqlite_clib_path` to be set to work. Nixpkgs historically patched these in the plugins with several drawbacks: harder maintenance and making upstream work harder. Per convention, these mandatory bits of configuration are bookmarked in nixpkgs in `passthru.initLua`. Enabling `autoconfigure` automatically adds the snippets required for the plugins to work.
|
|
- `autowrapRuntimeDeps`: Appends plugin's runtime dependencies to `PATH`. For instance, `rest.nvim` requires `curl` to work. Enabling `autowrapRuntimeDeps` adds it to the `PATH` visible by your Neovim wrapper (but not your global `PATH`).
|
|
- `luaRcContent`: Extra lua code to add to the generated `init.lua`.
|
|
- `neovimRcContent`: Extra vimL code sourced by the generated `init.lua`.
|
|
- `wrapperArgs`: Extra arguments forwarded to the `makeWrapper` call.
|
|
- `wrapRc`: Nix, not being able to write in your `$HOME`, loads the
|
|
generated Neovim configuration via the `$VIMINIT` environment variable, i.e. : `export VIMINIT='lua dofile("/nix/store/…-init.lua")'`. This has side effects like preventing Neovim from sourcing your `init.lua` in `$XDG_CONFIG_HOME/nvim` (see bullet 7 of [`:help startup`](https://neovim.io/doc/user/starting.html#startup) in Neovim). Disable it if you want to generate your own wrapper. You can still reuse the generated vimscript init code via `neovim.passthru.initRc`.
|
|
- `plugins`: A list of plugins to add to the wrapper.
|
|
- `extraLuaPackages`: A function passed on to `lua.withPackages`.
|
|
- `extraPython3Packages`: A function passed on to `python3.withPackages`.
|
|
- `withPython3`, `withNodeJs`, `withRuby`, `withPerl` control when to enable neovim
|
|
providers (see `:h provider`).
|
|
- `vimAlias` and `viAlias` control whether to symlink the `vim` and `vi` binaries to `nvim` respectively.
|
|
- `extraName` is a string appended to the package name and derivation name.
|
|
|
|
```nix
|
|
wrapNeovimUnstable neovim-unwrapped {
|
|
autoconfigure = true;
|
|
autowrapRuntimeDeps = true;
|
|
luaRcContent = ''
|
|
vim.o.sessionoptions = 'buffers,curdir,help,tabpages,winsize,winpos,localoptions'
|
|
vim.g.mapleader = ' '
|
|
vim.g.maplocalleader = ' '
|
|
vim.opt.smoothscroll = true
|
|
vim.opt.colorcolumn = { 100 }
|
|
vim.opt.termguicolors = true
|
|
'';
|
|
# plugins accepts a list of either plugins or attribute sets containing:
|
|
# { plugin = ...; config = ...; type = "viml"|"lua"; } (type defaults to "viml")
|
|
plugins = with vimPlugins; [
|
|
{
|
|
plugin = vim-obsession;
|
|
config = ''
|
|
map <Leader>$ <Cmd>Obsession<CR>
|
|
'';
|
|
}
|
|
{
|
|
plugin = grug-far-nvim;
|
|
type = "lua";
|
|
config = ''
|
|
require('grug-far').setup({
|
|
startInInsertMode = false,
|
|
})
|
|
'';
|
|
}
|
|
(nvim-treesitter.withPlugins (p: [
|
|
p.nix
|
|
p.python
|
|
]))
|
|
hex-nvim
|
|
];
|
|
extraLuaPackages = lp: [ lp.mpack ];
|
|
withPython3 = true;
|
|
withNodeJs = false;
|
|
withRuby = false;
|
|
}
|
|
```
|
|
|
|
You can explore the configuration with `nix repl` to discover these options and
|
|
override them. For instance:
|
|
```nix
|
|
neovim.override {
|
|
autowrapRuntimeDeps = false;
|
|
}
|
|
```
|
|
|
|
## Specificities for some plugins {#neovim-plugin-specificities}
|
|
|
|
### Plugin optional configuration {#neovim-plugin-required-snippet}
|
|
|
|
Some plugins require specific configuration to work. We choose not to
|
|
patch those plugins but expose the necessary configuration under
|
|
`PLUGIN.passthru.initLua` for neovim plugins. For instance, the `unicode-vim` plugin
|
|
needs the path towards a unicode database so we expose the following snippet `vim.g.Unicode_data_directory="${self.unicode-vim}/autoload/unicode"` under `vimPlugins.unicode-vim.passthru.initLua`.
|
|
|
|
### Plugin license overrides {#neovim-plugin-license-overrides}
|
|
|
|
Generated Vim and Neovim plugins get their `meta.license` from GitHub license metadata when possible.
|
|
Some upstream repositories do not expose a license file that GitHub can detect, or only mention the license in a README.
|
|
In those cases, add a manual `meta.license` override in [overrides.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/overrides.nix).
|
|
|
|
For example, if upstream documents that a plugin uses the Vim license but GitHub does not detect it:
|
|
|
|
```nix
|
|
{
|
|
foo-nvim = super.foo-nvim.overrideAttrs (old: {
|
|
meta = old.meta // {
|
|
# README says this plugin is distributed under the Vim license.
|
|
license = lib.licenses.vim;
|
|
};
|
|
});
|
|
}
|
|
```
|
|
|
|
## LuaRocks based plugins {#neovim-luarocks-based-plugins}
|
|
|
|
To automatically handle plugin dependencies, several Neovim plugins
|
|
upload their package to [LuaRocks](https://www.luarocks.org). This means less work for nixpkgs maintainers in the long term as dependencies get updated automatically.
|
|
This means several Neovim plugins are first packaged as nixpkgs [lua
|
|
packages](#packaging-a-library-on-luarocks), and converted via `buildNeovimPlugin` in
|
|
a vim plugin. This conversion is necessary because Neovim expects lua folders to be
|
|
top-level while LuaRocks installs them in various subfolders by default.
|
|
|
|
For instance:
|
|
```nix
|
|
{
|
|
rtp-nvim = neovimUtils.buildNeovimPlugin { luaAttr = luaPackages.rtp-nvim; };
|
|
}
|
|
```
|
|
To update these packages, you should use the lua updater rather than vim's.
|
|
|
|
To add a lua package to the `vimPlugins` set, add it to the `luarocksPackageNames` list in [luaPackagePlugins.nix](https://github.com/nixos/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/luaPackagePlugins.nix).
|
|
|
|
## Treesitter {#neovim-plugin-treesitter}
|
|
|
|
[Treesitter](https://tree-sitter.github.io/) provides syntax parsing for Neovim, enabling features like:
|
|
Advanced syntax highlighting, Code folding, Indentation and more.
|
|
|
|
Most Neovim users manage treesitter through the `nvim-treesitter` plugin, which provides:
|
|
|
|
- Commands for managing grammars and queries,
|
|
e.g. `:TSInstall`, which downloads, compiles and installs them at runtime.
|
|
- A custom indentation implementation ([`:h indentexpr`](https://neovim.io/doc/user/options.html#'indentexpr'))
|
|
for languages with `indents.scm` queries.
|
|
|
|
These features build on top of treesitter functionality that is built into Neovim.
|
|
|
|
In nixpkgs, grammars and queries are precompiled and packaged separately. This means:
|
|
|
|
- You can use treesitter features **without** installing `nvim-treesitter`.
|
|
- You only need `nvim-treesitter` if you want its custom indentation implementation.
|
|
- Plugins that depend on grammars can reference them directly.
|
|
|
|
### Treesitter setup using `nvim-treesitter` {#neovim-plugin-nvim-treesitter}
|
|
|
|
::: {.tip}
|
|
Choose this approach if you want to use `nvim-treesitter`'s custom indentation expression.
|
|
:::
|
|
|
|
To install `nvim-treesitter` combined with a set of precompiled grammars,
|
|
you can use the `nvim-treesitter.withPlugins` function:
|
|
|
|
```nix
|
|
(pkgs.neovim.override {
|
|
configure = {
|
|
packages.myPlugins = with pkgs.vimPlugins; {
|
|
start = [
|
|
(nvim-treesitter.withPlugins (
|
|
plugins: with plugins; [
|
|
nix
|
|
python
|
|
]
|
|
))
|
|
];
|
|
};
|
|
};
|
|
})
|
|
```
|
|
|
|
To enable all grammars packaged in nixpkgs, use `pkgs.vimPlugins.nvim-treesitter.withAllGrammars`.
|
|
|
|
For how to configure `nvim-treesitter` and set up syntax highlighting, indentation, folding, etc.,
|
|
please refer to the `:help nvim-treesitter-quickstart` plugin documentation.
|
|
|
|
::: {.note}
|
|
When using Nix-managed grammars, `:checkhealth nvim-treesitter` will report no installed languages.
|
|
This is expected behavior because:
|
|
- The `nvim-treesitter` health check searches its configured install directory.
|
|
- Nix installs grammars to the Nix store and adds them to the `runtimepath` instead.
|
|
|
|
**To verify Nix-managed parsers and queries**, use `:checkhealth vim.treesitter` instead.
|
|
:::
|
|
|
|
### Treesitter setup using standalone grammars and queries {#neovim-plugin-treesitter-standalone}
|
|
|
|
::: {.tip}
|
|
Choose this approach if you
|
|
- Want minimal dependencies.
|
|
- Don't need `nvim-treesitter`'s custom indentation expression.
|
|
:::
|
|
|
|
You can install the standalone parsers and queries directly without installing `nvim-treesitter`:
|
|
|
|
```nix
|
|
(pkgs.neovim.override {
|
|
configure = {
|
|
packages.myPlugins =
|
|
with pkgs.vimPlugins;
|
|
let
|
|
# Select the grammars you need
|
|
treesitter-grammars = with nvim-treesitter-parsers; [
|
|
nix
|
|
python
|
|
];
|
|
# Queries are needed for treesitter based syntax highlighting and folds.
|
|
treesitter-queries = map (p: p.associatedQuery) treesitter-grammars;
|
|
in
|
|
{
|
|
start = [
|
|
# regular plugins
|
|
]
|
|
++ treesitter-grammars
|
|
++ treesitter-queries;
|
|
};
|
|
};
|
|
})
|
|
```
|
|
|
|
### Treesitter setup using WASM parsers and queries {#neovim-plugin-treesitter-wasm}
|
|
|
|
Neovim can load WASM parsers when it is built with Wasmtime support.
|
|
In nixpkgs, WASM parser plugins are available from the `wasm32-wasip1` cross package set:
|
|
|
|
```nix
|
|
(pkgs.wrapNeovim (pkgs.neovim-unwrapped.override { wasmSupport = true; }) {
|
|
configure = {
|
|
packages.myPlugins =
|
|
with pkgs.pkgsCross.wasm32-wasip1.vimPlugins;
|
|
let
|
|
# Select the grammars you need
|
|
treesitter-grammars = with nvim-treesitter-parsers; [
|
|
nix
|
|
python
|
|
];
|
|
# Queries are needed for treesitter based syntax highlighting and folds.
|
|
treesitter-queries = map (p: p.associatedQuery) treesitter-grammars;
|
|
in
|
|
{
|
|
start = [
|
|
# regular plugins
|
|
]
|
|
++ treesitter-grammars
|
|
++ treesitter-queries;
|
|
};
|
|
};
|
|
})
|
|
```
|
|
|
|
Do not install both native and WASM parsers for the same language.
|
|
For example, installing both `pkgs.vimPlugins.nvim-treesitter-parsers.nix` and
|
|
`pkgs.pkgsCross.wasm32-wasip1.vimPlugins.nvim-treesitter-parsers.nix` is invalid because Neovim
|
|
loads the first `parser/nix.*` found on `runtimepath`.
|
|
|
|
Use `:checkhealth vim.treesitter` to verify Nix-managed WASM parsers.
|
|
|
|
You can enable treesitter features for installed grammars in a `FileType` autocommand
|
|
or in an `ftplugin/<language>.lua` script, e.g.
|
|
|
|
```lua
|
|
vim.api.nvim_create_autocmd('FileType', {
|
|
pattern = { 'rust', 'javascript', 'zig' },
|
|
callback = function(ev)
|
|
local bufnr = ev.buf
|
|
|
|
-- Enable treesitter syntax highlighting and parsing for the current buffer
|
|
-- (Requires queries to be installed)
|
|
vim.treesitter.start(bufnr)
|
|
|
|
-- Enable treesitter based code folding
|
|
-- (folds are window-scoped, not buffer-scoped)
|
|
-- (Requires queries to be installed)
|
|
vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
|
|
vim.wo.foldmethod = 'expr'
|
|
end,
|
|
})
|
|
```
|
|
|
|
### Treesitter grammars as plugin dependencies {#neovim-plugin-treesitter-grammar-dependencies}
|
|
|
|
Some Neovim plugins (like `neotest` adapters, `markdoc-nvim`, `hurl-nvim`) depend on treesitter grammars.
|
|
These dependencies are usually declared in plugin overrides.
|
|
|
|
::: {.important}
|
|
Some plugin READMEs may suggest that they depend on `nvim-treesitter`.
|
|
**This is almost always not the case.**
|
|
|
|
`nvim-treesitter` no longer provides a Lua module API for other plugins to use.
|
|
In the vast majority of cases, these plugins:
|
|
- **Depend on parsers** (not on `nvim-treesitter` or its queries).
|
|
- **Bundle their own queries** (either as `*.scm` files or hardcoded in the Lua sources).
|
|
:::
|
|
|
|
To add grammars as a plugin dependency, add an [override](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/overrides.nix):
|
|
|
|
```nix
|
|
{
|
|
foo-nvim = super.foo-nvim.overrideAttrs {
|
|
dependencies = with self.nvim-treesitter-parsers; [
|
|
markdown
|
|
markdown_inline
|
|
html
|
|
];
|
|
};
|
|
}
|
|
```
|
|
|
|
If a plugin actually does depend on the `nvim-treesitter` legacy module API, you can add
|
|
`nvim-treesitter-legacy` as a dependency:
|
|
|
|
```nix
|
|
{
|
|
foo-legacy-nvim = super.foo-legacy-nvim.overrideAttrs {
|
|
dependencies = with self; [
|
|
nvim-treesitter-legacy
|
|
nvim-treesitter-parsers.nix
|
|
];
|
|
};
|
|
}
|
|
```
|
|
|
|
::: {.caution}
|
|
`nvim-treesitter-legacy` exists for the purpose of easing transition and will be removed in 26.11.
|
|
If a Neovim configuration contains both `nvim-treesitter` and `nvim-treesitter-legacy`, it will fail to evaluate.
|
|
:::
|
|
|
|
## Testing Neovim plugins {#testing-neovim-plugins}
|
|
|
|
### neovimRequireCheck {#testing-neovim-plugins-neovim-require-check}
|
|
|
|
`neovimRequireCheck` is a simple test which checks if Neovim can require lua modules without errors. This is often enough to catch missing dependencies.
|
|
|
|
It accepts a single string for a module, or a list of module strings to test.
|
|
- `nvimRequireCheck = MODULE;`
|
|
- `nvimRequireCheck = [ MODULE1 MODULE2 ];`
|
|
|
|
When `nvimRequireCheck` is not specified, we will search the plugin's directory for lua modules to attempt loading. This quick smoke test can catch obvious dependency errors that might be missed.
|
|
The check hook will fail the build if any modules cannot be loaded. This encourages inspecting the logs to identify potential issues.
|
|
|
|
To only check a specific module, add it manually to the plugin definition [overrides](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/overrides.nix).
|
|
|
|
```nix
|
|
{
|
|
gitsigns-nvim = super.gitsigns-nvim.overrideAttrs {
|
|
dependencies = [ self.plenary-nvim ];
|
|
nvimRequireCheck = "gitsigns";
|
|
};
|
|
}
|
|
```
|
|
Some plugins will have lua modules that require a user configuration to function properly or can contain optional lua modules that we don't want to test by requiring.
|
|
We can skip specific modules using `nvimSkipModules`. Similar to `nvimRequireCheck`, it accepts a list of strings.
|
|
- `nvimSkipModules = [ MODULE1 MODULE2 ];`
|
|
|
|
```nix
|
|
{
|
|
asyncrun-vim = super.asyncrun-vim.overrideAttrs {
|
|
nvimSkipModules = [
|
|
# vim plugin with optional toggleterm integration
|
|
"asyncrun.toggleterm"
|
|
"asyncrun.toggleterm2"
|
|
];
|
|
};
|
|
}
|
|
```
|
|
|
|
In rare cases, we might not want to actually test loading lua modules for a plugin. In those cases, we can disable `neovimRequireCheck` with `doCheck = false;`.
|
|
|
|
This can be manually added through plugin definition overrides in the [overrides.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/overrides.nix).
|
|
```nix
|
|
{
|
|
vim-test = super.vim-test.overrideAttrs {
|
|
# Vim plugin with a test lua file
|
|
doCheck = false;
|
|
};
|
|
}
|
|
```
|