The guiding principle of nixvim is to only add to the `init.lua` what the user added to the configuration. This means that we must trim out all the options that were not set.
- Most plugins should be added to [`plugins/by-name/<name>`](plugins/by-name).
Plugins in `by-name` are automatically imported 🚀
- Occasionally, you may wish to add a plugin to a directory outside of `by-name`, such as [`plugins/colorschemes`](plugins/colorschemes).
If so, you will also need to add your plugin to [`plugins/default.nix`](plugins/default.nix) to ensure it gets imported.
Note: the imports list is sorted and grouped. In vim, you can usually use `V` (visual-line mode) with the `:sort` command to achieve the desired result.
| **configLocation** | The option location where the lua configuration should be installed. Nested option locations can be represented as a list. The location can also be wrapped using `lib.mkBefore`, `lib.mkAfter`, or `lib.mkOrder`. | No | `"extraConfigLuaPre"` if `isColorscheme` then `extraConfigLuaPre`, otherwise `"extraConfigLua"` |
| **extraConfig** | Additional configuration for the plugin. Either an attrset, a function accepting `cfg`, or a function accepting `cfg` and `opts`. | No | `{}` |
| **extraOptions** | Module options for the plugin, to be added _outside_ of the `settings` option. These should be Nixvim-specific options. | No | `{}` |
| **extraPackages** | Extra packages to include. | No | `[]` |
| **extraPlugins** | Extra plugins to include. | No | `[]` |
| **packPathName** | The name of the plugin directory in [packpath](https://neovim.io/doc/user/options.html#'packpath'), usually the plugin's github repo name. E.g. `"foo-bar.nvim"`. | No | `name` parameter |
| **package** | The nixpkgs package attr for this plugin. Can be a string, a list of strings, a module option, or any derivation. For example, "foo-bar-nvim" for `pkgs.vimPlugins.foo-bar-nvim`, or `[ "hello" "world" ]` will be referenced as `pkgs.hello.world`. | No | `name` parameter |
| **settingsDescription** | A description of the settings provided to the `setup` function. | No | `"Options provided to the require('${moduleName}')${setup} function."` |
| **settingsExample** | An example configuration for the plugin's settings. See [Writing option examples]. | No | `null` |
| **settingsOptions** | Options representing the plugin's settings. This is optional because `settings` is a "freeform" option. See [Declaring plugin options]. | No | `{}` |
This example defines a Neovim plugin named `example-plugin` with specified maintainers, URL, description, settings options, and additional configuration. `package` will be 'example-plugin'
thanks to package referring to the `name` attribute.
| **extraConfig** | Extra configuration for the plugin. Either an attrset, a function accepting `cfg`, or a function accepting `cfg` and `opts`. | No | `{}` |
| **packPathName** | The name of the plugin directory in [packpath](https://neovim.io/doc/user/options.html#'packpath'), usually the plugin's github repo name. E.g. `"foo-bar.vim"`. | No | `name` parameter |
| **package** | The nixpkgs package attr for this plugin. Can be a string, a list of strings, a module option, or any derivation. For example, "foo-bar-vim" for `pkgs.vimPlugins.foo-bar-vim`, or `[ "hello" "world" ]` will be referenced as `pkgs.hello.world`. | No | `name` parameter |
| **settingsExample** | Example settings for the plugin. See [Writing option examples]. | No | `null` |
| **settingsOptions** | Options representing the plugin's settings. This is optional because `settings` is a "freeform" option. See [Declaring plugin options]. | No | `{}` |
Module options have first-class support for "examples" that are included automatically in documentation.
For example this option will render something like:
> # foo
>
> Some string
>
> **Default**: `null` \
> **Example**: `"Hello, world!"`
```nix
foo = lib.mkOption {
type = lib.types.nullOr lib.types.str;
description = "Some string";
default = null;
example = "Hello, world!";
}
```
Because [`mkVimPlugin`] and [`mkNeovimPlugin`] abstract away creation of the `settings` option, they provide a `settingsExample` argument. It is highly recommended to use this to provide an example for the plugin's `settings`.
Although `lib.nixvim.defaultNullOpts` helper functions don't usually support defining an example, each function offers a "prime variant" (e.g. `defaultNullOpts.mkString` has `defaultNullOpts.mkString'`) which accept nearly any argument you could use with `lib.mkOption`.
See [Declaring plugin options].
Most of the time you will set `example` to a nix value and the module system will render it using `lib.generators.toPretty`.
However, sometimes the example you wish to show would benefit from a specific formatting, may include function application or use of nix operators, or may benefit from some non-code explanation.
In that scenario, you should use `lib.literalExpression` or `lib.literalMD`.
You can use `lib.literalExpression` to write an example that is manually rendered by you. E.g. if your example needs to include expressions like `lib.nixvim.mkRaw "foo"`, you could use:
```nix
example = lib.literalExpression ''
{
foo = lib.nixvim.mkRaw "foo";
}
''
```
Another example where `literalExpression` is beneficial is when your example includes multi-line strings.
If you allow the module system to render your example itself using `lib.generators.toPretty`, then multi-line strings will be rendered as a "normal" string literal, with `\n` used to represent line-breaks.
Note that to include a `''` literal within a nix indented string, you should use `'''`. E.g:
```nix
example = lib.literalExpression ''
{
long-string = '''
This string
spans over
several lines!
''';
}
''
```
On very rare occasions, you may wish to include some non-code text within your example. This can be done by wrapping a markdown string with `lib.literalMD`.
E.g:
`````nix
example = lib.literalMD ''
This will render as normal text.
Markdown formatting is **supported**!
```nix
This will render as nix code.
```
''
`````
See also: [Writing NixOS Modules: Option Declarations](https://nixos.org/manual/nixos/unstable/#sec-option-declarations) (NixOS Manual).
> Declaring `settings`-options is **not required**, because the `settings` option is a freeform type.
>
> While `settings` options can be helpful for documentation and type-checking purposes, this is a double-edged sword because we have to ensure the options are correctly typed and documented to avoid unnecessary restrictions or confusion.
If you feel having nix options for some of the upstream plugin options adds value and is worth the maintenance cost, you can declare these in `settingsOptions`.
There are a number of helpers added into `lib` that can help you correctly implement them:
-`lib.nixvim.defaultNullOpts.{mkBool,mkInt,mkStr,...}`: This family of helpers takes a default value and a description, and sets the Nix default to `null`.
These are the main functions you should use to define options.
-`lib.nixvim.defaultNullOpts.<name>'`: These "prime" variants of the above helpers do the same thing, but expect a "structured" attrs argument.
This allows more flexibility in what arguments are passed through to the underlying `lib.mkOption` call.
-`lib.types.rawLua`: A type to represent raw lua code. The values are of the form `{ __raw = "<code>";}`.
The resulting `settings` attrs will be directly translated to `lua` and will be forwarded the plugin:
Most of the tests of nixvim consist of creating a neovim derivation with the supplied nixvim configuration, and then try to execute neovim to check for any output. All output is considered to be an error.
The tests are located in the [tests/test-sources](tests/test-sources) directory, and should be added to a file in the same hierarchy than the repository. For example if a plugin is defined in `./plugins/ui/foo.nix` the test should be added in `./tests/test-sources/ui/foo.nix`.
Tests can either be a simple attribute set, or a function taking `{pkgs}` as an input. The keys of the set are configuration names, and the values are a nixvim configuration.
You can specify the special `test` attribute in the configuration that will not be interpreted by nixvim, but only the test runner. The following keys are available:
> A single test can be run with `nix develop --command tests --interactive`. This launches the testing suite in interactive mode, allowing you to easily search for and select specific tests to run.
> [!WARNING]
> Running the entire test suite locally is not necessary in most cases. Instead, you may find it more efficient to focus on specific tests relevant to your changes, as Continuous Integration (CI) will run the full test suite on any Pull Requests (PRs) you open. This ensures comprehensive coverage without requiring the full suite to be run locally every time.
The full test suite can still be run locally with `nix flake check --all-systems` if needed.