<divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="preface"><ahref="index.xhtml#ch-preface">Preface</a></span></dt><dt><spanclass="preface"><ahref="index.xhtml#ch-try-it-out">Try it out</a></span></dt><dt><spanclass="part"><ahref="index.xhtml#ch-installation">Installing nvf</a></span></dt><dd><dl><dt><spanclass="chapter"><ahref="index.xhtml#ch-standalone-installation">Standalone Installation</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-module-installation">Module Installation</a></span></dt></dl></dd><dt><spanclass="part"><ahref="index.xhtml#ch-configuring">Configuring nvf</a></span></dt><dd><dl><dt><spanclass="chapter"><ahref="index.xhtml#ch-custom-package">Custom Neovim Package</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-custom-plugins">Custom Plugins</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-overriding-plugins">Overriding plugins</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-languages">Language Support</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-using-dags">Using DAGs</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-dag-entries">DAG entries in nvf</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-autocmds-augroups">Autocommands and Autogroups</a></span></dt></dl></dd><dt><spanclass="part"><ahref="index.xhtml#ch-helpful-tips">Helpful Tips</a></span></dt><dd><dl><dt><spanclass="chapter"><ahref="index.xhtml#sec-debugging-nvf">Debugging nvf</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#sec-offline-documentation">Offline Documentation</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#sec-pure-lua-config">Pure Lua Configuration</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#sec-plugin-sources">Adding Plugins From Different Sources</a></span></dt></dl></dd><dt><spanclass="chapter"><ahref="index.xhtml#ch-hacking">Hacking nvf</a></span></dt><dt><spanclass="appendix"><ahref="quirks.html">A. Known Issues and Quirks</a></span></dt><dt><spanclass="appendix"><ahref="options.html">B. nvf Configuration Options</a></span></dt><dt><spanclass="appendix"><ahref="release-notes.html">C. Release Notes</a></span></dt></dl></div>
<divclass="preface"><divclass="titlepage"><div><div><h1id="ch-preface"class="title">Preface </h1></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-what-is-it">What is nvf</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-bugs-suggestions">Bugs & Suggestions</a></span></dt></dl></div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-what-is-it"class="title">What is nvf </h2></div></div></div><p>nvf is a highly modular, configurable, extensible and easy to use Neovim
configuration in Nix. Designed for flexibility and ease of use, nvf allows you
to easily configure your fully featured Neovim instance with a few lines of Nix.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-bugs-suggestions"class="title">Bugs & Suggestions </h2></div></div></div><p>If you notice any issues with nvf, or this documentation, then please consider
reporting them over at the <aclass="link"href="https://github.com/notashelf/nvf/issues"target="_top">issue tracker</a>. Issues tab, in addition to the
<aclass="link"href="https://github.com/notashelf/nvf/discussions"target="_top">discussions tab</a> is a good place as any to request new features.</p><p>You may also consider submitting bugfixes, feature additions and upstreamed
changes that you think are critical over at the <aclass="link"href="https://github.com/notashelf/nvf/pulls"target="_top">pull requests tab</a>.</p>
</div>
</div><divclass="preface"><divclass="titlepage"><div><div><h1id="ch-try-it-out"class="title">Try it out </h1></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-using-prebuilt-configs">Using Prebuilt Configs</a></span></dt></dl></div><p>Thanks to the portability of Nix, you can try out nvf without actually
installing it to your machine. Below are the commands you may run to try out
different configurations provided by this flake. As of v0.5, two specialized
configurations are provided:</p><divclass="itemizedlist"><ulclass="itemizedlist compact"style="list-style-type: disc;"><liclass="listitem"><p><spanclass="strong"><strong>Nix</strong></span> (<codeclass="literal">packages.nix</code>) - Nix language server + simple utility plugins</p></li><liclass="listitem"><p><spanclass="strong"><strong>Maximal</strong></span> (<codeclass="literal">packages.maximal</code>) - Variable language servers + utility and
decorative plugins</p></li></ul></div><p>You may try out any of the provided configurations using the <codeclass="literal">nix run</code> command
on a system where Nix is installed.</p><pre><codeclass="programlisting sh">$ cachix use nvf # Optional: it'll save you CPU resources and time
$ nix run github:notashelf/nvf#nix # Will run the default minimal configuration
</code></pre><p>Do keep in mind that this is <spanclass="strong"><strong>susceptible to garbage collection</strong></span> meaning that
the built outputs will be removed from your Nix store once you garbage collect.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-using-prebuilt-configs"class="title">Using Prebuilt Configs </h2></div></div></div><divclass="toc"><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-available-configs">Available Configurations</a></span></dt></dl></div><pre><codeclass="programlisting bash">$ nix run github:notashelf/nvf#nix
$ nix run github:notashelf/nvf#maximal
</code></pre><divclass="section"><divclass="titlepage"><div><div><h3id="sec-available-configs"class="title">Available Configurations </h3></div></div></div><p>::: {.info}</p><p>The below configurations are provided for demonstration purposes, and are
<spanclass="strong"><strong>not</strong></span> designed to be installed as is. You may</p><divclass="section"><divclass="titlepage"><div><div><h4id="sec-configs-nix"class="title">Nix </h4></div></div></div><p><codeclass="literal">Nix</code> configuration by default provides LSP/diagnostic support for Nix alongside
a set of visual and functional plugins. By running <codeclass="literal">nix run .#</code>, which is the
default package, you will build Neovim with this config.</p><pre><codeclass="programlisting bash">$ nix run github:notashelf/nvf#nix test.nix
</code></pre><p>This command will start Neovim with some opinionated plugin configurations, and
is designed specifically for Nix. the <codeclass="literal">nix</code> configuration lets you see how a
fully configured Neovim setup <spanclass="emphasis"><em>might</em></span> look like without downloading too many
packages or shell utilities.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h4id="sec-configs-maximal"class="title">Maximal </h4></div></div></div><p><codeclass="literal">Maximal</code> is the ultimate configuration that will enable support for more
commonly used language as well as additional complementary plugins. Keep in
mind, however, that this will pull a lot of dependencies.</p><pre><codeclass="programlisting bash">$ nix run github:notashelf/nvf#maximal -- test.nix
</code></pre><p>It uses the same configuration template with the <aclass="link"href="index.xhtml#sec-configs-nix"title="Nix">Nix</a>
configuration, but supports many more languages, and enables more utility,
companion or fun plugins.</p><divclass="warning"><h3class="title">Warning</h3><p>Running the maximal config will download <spanclass="emphasis"><em>a lot</em></span> of packages as it is
downloading language servers, formatters, and more. If CPU time and bandwidth
are concerns, please use the default package instead.</p></div>
</div>
</div>
</div>
</div><divclass="part"><divclass="titlepage"><div><div><h1id="ch-installation"class="title">Installing nvf </h1></div></div></div><divclass="partintro"><p>There are multiple ways of installing nvf on your system. You may either choose
the standalone installation method, which does not depend on a module system and
may be done on any system that has the Nix package manager or the appropriate
modules for NixOS and home-manager as described in the
<aclass="link"href="index.xhtml#ch-module-installation"title="Module Installation">module installation section</a>.</p><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="chapter"><ahref="index.xhtml#ch-standalone-installation">Standalone Installation</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-module-installation">Module Installation</a></span></dt></dl></div></div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-standalone-installation"class="title">Standalone Installation </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="chapter"><ahref="index.xhtml#ch-standalone-nixos">Standalone Installation on NixOS</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-standalone-hm">Standalone Installation on Home-Manager</a></span></dt></dl></div><p>It is possible to install nvf without depending on NixOS or Home-Manager as the
parent module system, using the <codeclass="literal">neovimConfiguration</code> function exposed in the
extended library. This function will take <codeclass="literal">modules</code> and <codeclass="literal">extraSpecialArgs</code> as
arguments, and return the following schema as a result.</p><pre><codeclass="programlisting nix">{
options = "The options that were available to configure";
config = "The outputted configuration";
pkgs = "The package set used to evaluate the module";
neovim = "The built neovim package";
}
</code></pre><p>An example flake that exposes your custom Neovim configuration might look like</p><pre><codeclass="programlisting nix">{
# Set the default package to the wrapped instance of Neovim.
# This will allow running your Neovim configuration with
# `nix run` and in addition, sharing your configuration with
# other users in case your repository is public.
default =
(inputs.nvf.lib.neovimConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
modules = [
{
config.vim = {
# Enable custom theming options
theme.enable = true;
# Enable Treesitter
treesitter.enable = true;
# Other options will go here. Refer to the config
# reference in Appendix B of the nvf manual.
# ...
};
}
];
})
.neovim;
};
};
}
</code></pre><p>The above setup will allow to set up nvf as a standalone flake, which you can
build independently from your system configuration while also possibly sharing
it with others. The next two chapters will detail specific usage of such a setup
for a package output in the context of NixOS or Home-Manager installation.</p><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-standalone-nixos"class="title">Standalone Installation on NixOS </h2></div></div></div><p>Your built Neovim configuration can be exposed as a flake output to make it
easier to share across machines, repositories and so on. Or it can be added to
your system packages to make it available across your system.</p><p>The following is an example installation of <codeclass="literal">nvf</code> as a standalone package with
the default theme enabled. You may use other options inside <codeclass="literal">config.vim</code> in
<codeclass="literal">configModule</code>, but this example will not cover that extensively.</p><pre><codeclass="programlisting nix">{
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-standalone-hm"class="title">Standalone Installation on Home-Manager </h2></div></div></div><p>Your built Neovim configuration can be exposed as a flake output to make it
easier to share across machines, repositories and so on. Or it can be added to
your system packages to make it available across your system.</p><p>The following is an example installation of <codeclass="literal">nvf</code> as a standalone package with
the default theme enabled. You may use other options inside <codeclass="literal">config.vim</code> in
<codeclass="literal">configModule</code>, but this example will not cover that extensively.</p><pre><codeclass="programlisting nix">{
# This will make Neovim available to users using the Home-Manager
# configuration. To make the package available to all users, prefer
# environment.systemPackages in your NixOS configuration.
{home.packages = [customNeovim.neovim];}
];
# ...
};
};
};
}
</code></pre>
</div>
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-module-installation"class="title">Module Installation </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="chapter"><ahref="index.xhtml#ch-nixos-module">NixOS Module</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-hm-module">Home-Manager Module</a></span></dt></dl></div><p>The below chapters will describe installing nvf as NixOS and Home-Manager
modules. Note that those methods are mutually exclusive, and will likely cause
path collisions if used simultaneously.</p><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-nixos-module"class="title">NixOS Module </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-nixos-flakes">With Flakes</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-nixos-flakeless">Without Flakes</a></span></dt></dl></div><p>The NixOS module allows us to customize the different <codeclass="literal">vim</code> options from inside
the NixOS configuration without having to call for the wrapper yourself. It is
the recommended way to use <spanclass="strong"><strong>nvf</strong></span> alongside the home-manager module depending
on your needs.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-nixos-flakes"class="title"style="clear: both">With Flakes </h2></div></div></div><divclass="toc"><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-nixos-flakes-usage">Usage</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-example-installation-nixos">Example Installation</a></span></dt></dl></div><pre><codeclass="programlisting {=include=}">flakes.md
</code></pre><divclass="section"><divclass="titlepage"><div><div><h3id="sec-nixos-flakes-usage"class="title">Usage </h3></div></div></div><p>To use <spanclass="strong"><strong>nvf</strong></span> with flakes, we first need to add the input to our <codeclass="literal">flake.nix</code>.</p><pre><codeclass="programlisting nix"># flake.nix
{
inputs = {
# Optional, if you intend to follow nvf's obsidian-nvim input
# Your settings need to go into the settings attribute set
# most settings are documented in the appendix
settings = {
vim.viAlias = false;
vim.vimAlias = true;
vim.lsp = {
enable = true;
};
};
};
}
</code></pre><divclass="note"><h3class="title">Note</h3><p><spanclass="strong"><strong>nvf</strong></span> exposes a lot of options, most of which are not referenced in the
installation sections of the manual. You may find all available options in the
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-nixos-flakeless"class="title"style="clear: both">Without Flakes </h2></div></div></div><p>As of v0.8, it is possible to install <spanclass="strong"><strong>nvf</strong></span> on a system if you are not using
flakes. This is possible thanks to the flake-compat project.</p><p>To get started, you must fetch the repository using <codeclass="literal">builtins.fetchTarball</code> or a
similar mechanism.</p><pre><codeclass="programlisting nix"># configuration.nix
let
nvf = import (builtins.fetchTarball {
url = "https://github.com/notashelf/nvf/archive/<commit or tag>.tar.gz";
# Optionally, you can add 'sha256' for verification and caching
# sha256 = "<sha256>";
});
in {
imports = [
# Import the NixOS module from your fetched input
nvf.nixosModules.nvf
];
# Once the module is imported, you may use `programs.nvf` as exposed by the
# NixOS module.
programs.nvf.enable = true;
}
</code></pre><divclass="tip"><h3class="title">Tip</h3><p>Nix2 does not have a builtin lockfile mechanism like flakes. As such you must
manually update the URL and hash for your input. This is annoying to deal with,
and most users choose to defer this task to projects such as <aclass="link"href="https://github.com/andir/npins"target="_top">npins</a> or <aclass="link"href="https://github.com/nmattia/niv"target="_top">niv</a>.
If you are new to NixOS, I encourage you to look into Flakes and see if they fit
your use case. Alternatively, look into the aforementioned projects for more
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-hm-module"class="title">Home-Manager Module </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-hm-flakes">With Flakes</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-hm-flakeless">Without Flakes</a></span></dt></dl></div><p>The home-manager module allows us to customize the different <codeclass="literal">vim</code> options from
inside the home-manager configuration without having to call for the wrapper
yourself. It is the recommended way to use <spanclass="strong"><strong>nvf</strong></span> alongside the NixOS module
depending on your needs.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-hm-flakes"class="title"style="clear: both">With Flakes </h2></div></div></div><divclass="toc"><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-hm-flakes-usage">Usage</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-example-installation-hm">Example Installation</a></span></dt></dl></div><pre><codeclass="programlisting {=include=}">flakes.md
</code></pre><divclass="section"><divclass="titlepage"><div><div><h3id="sec-hm-flakes-usage"class="title">Usage </h3></div></div></div><p>To use <spanclass="strong"><strong>nvf</strong></span> with flakes, we first need to add the input to our <codeclass="literal">flake.nix</code>.</p><pre><codeclass="programlisting nix"># flake.nix
{
inputs = {
# Optional, if you intend to follow nvf's obsidian-nvim input
# your settings need to go into the settings attribute set
# most settings are documented in the appendix
settings = {
vim.viAlias = false;
vim.vimAlias = true;
vim.lsp = {
enable = true;
};
};
};
}
</code></pre><divclass="note"><h3class="title">Note</h3><p><spanclass="strong"><strong>nvf</strong></span> exposes a lot of options, most of which are not referenced in the
installation sections of the manual. You may find all available options in the
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-hm-flakeless"class="title"style="clear: both">Without Flakes </h2></div></div></div><p>As of v0.8, it is possible to install <spanclass="strong"><strong>nvf</strong></span> on a system if you are not using
flakes. This is possible thanks to the flake-compat project.</p><p>To get started, you must fetch the repository using <codeclass="literal">builtins.fetchTarball</code> or a
similar mechanism.</p><pre><codeclass="programlisting nix"># home.nix
let
nvf = import (builtins.fetchTarball {
url = "https://github.com/notashelf/nvf/archive/<commit or tag>.tar.gz";
# Optionally, you can add 'sha256' for verification and caching
# sha256 = "<sha256>";
});
in {
imports = [
# Import the NixOS module from your fetched input
nvf.homeManagerModules.nvf
];
# Once the module is imported, you may use `programs.nvf` as exposed by the
# NixOS module.
programs.nvf.enable = true;
}
</code></pre><divclass="tip"><h3class="title">Tip</h3><p>Nix2 does not have a builtin lockfile mechanism like flakes. As such you must
manually update the URL and hash for your input. This is annoying to deal with,
and most users choose to defer this task to projects such as <aclass="link"href="https://github.com/andir/npins"target="_top">npins</a> or <aclass="link"href="https://github.com/nmattia/niv"target="_top">niv</a>.
If you are new to NixOS, I encourage you to look into Flakes and see if they fit
your use case. Alternatively, look into the aforementioned projects for more
</div><divclass="part"><divclass="titlepage"><div><div><h1id="ch-configuring"class="title">Configuring nvf </h1></div></div></div><divclass="partintro"><p>nvf allows for <spanclass="emphasis"><em>very</em></span> extensive configuration in Neovim through the Nix module
interface. The below chapters describe several of the options exposed in nvf for
your convenience. You might also be interested in the <aclass="link"href="index.xhtml#ch-helpful-tips"title="Helpful Tips">helpful tips section</a> for
more advanced or unusual configuration options supported by nvf.</p><p>Note that this section does not cover module <spanclass="emphasis"><em>options</em></span>. For an overview of all
module options provided by nvf, please visit the <aclass="link"href="/nvf/options.html"target="_top">appendix</a></p><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="chapter"><ahref="index.xhtml#ch-custom-package">Custom Neovim Package</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-custom-plugins">Custom Plugins</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-overriding-plugins">Overriding plugins</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-languages">Language Support</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-using-dags">Using DAGs</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-dag-entries">DAG entries in nvf</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#ch-autocmds-augroups">Autocommands and Autogroups</a></span></dt></dl></div></div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-custom-package"class="title">Custom Neovim Package </h2></div></div></div><p>As of v0.5, you may now specify the Neovim package that will be wrapped with
your configuration. This is done with the <aclass="xref"href="options.html#opt-vim.package"><codeclass="option">vim.package</code></a> option.</p><pre><codeclass="programlisting nix">{inputs, pkgs, ...}: {
</code></pre><p>The neovim-nightly-overlay always exposes an unwrapped package. If using a
different source, you are highly recommended to get an “unwrapped” version of
the neovim package, similar to <codeclass="literal">neovim-unwrapped</code> in nixpkgs.</p><pre><codeclass="programlisting nix">{ pkgs, ...}: {
# using the neovim-nightly overlay
vim.package = pkgs.neovim-unwrapped;
}
</code></pre>
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-custom-plugins"class="title">Custom Plugins </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#ch-adding-plugins">Adding Plugins</a></span></dt></dl></div><p><spanclass="strong"><strong>nvf</strong></span> exposes a very wide variety of plugins by default, which are consumed by
module options. This is done for your convenience, and to bundle all necessary
dependencies into <spanclass="strong"><strong>nvf</strong></span>’s runtime with full control of versioning, testing and
dependencies. In the case a plugin you need is <spanclass="emphasis"><em>not</em></span> available, you may consider
making a pull request to add the package you’re looking for, or you may add it
to your configuration locally. The below section describes how new plugins may
be added to the user’s configuration.</p><divclass="section"><divclass="titlepage"><div><div><h2id="ch-adding-plugins"class="title"style="clear: both">Adding Plugins </h2></div></div></div><divclass="toc"><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-configuring-plugins">Configuring</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-lazy-method">Lazy Method</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-non-lazy-method">Non-lazy Method</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-legacy-method">Legacy Method</a></span></dt></dl></div><p>Per <spanclass="strong"><strong>nvf</strong></span>’s design choices, there are several ways of adding custom plugins to
your configuration as you need them. As we aim for extensive configuration, it
is possible to add custom plugins (from nixpkgs, pinning tools, flake inputs,
etc.) to your Neovim configuration before they are even implemented in <spanclass="strong"><strong>nvf</strong></span>
as a module.</p><p>:::{.info}</p><p>To add a plugin to your runtime, you will need to add it to
<aclass="xref"href="options.html#opt-vim.startPlugins"><codeclass="option">vim.startPlugins</code></a> list in your configuration. This is akin to cloning a
plugin to <codeclass="literal">~/.config/nvim</code>, but they are only ever placed in the Nix store and
never exposed to the outside world for purity and full isolation.</p><p>:::</p><p>As you would configure a cloned plugin, you must configure the new plugins that
you’ve added to <codeclass="literal">startPlugins.</code><spanclass="strong"><strong>nvf</strong></span> provides multiple ways of configuring
any custom plugins that you might have added to your configuration.</p><divclass="section"><divclass="titlepage"><div><div><h3id="sec-configuring-plugins"class="title">Configuring </h3></div></div></div><p>Just making the plugin to your Neovim configuration available might not always
be enough., for example, if the plugin requires a setup table. In that case, you
can write custom Lua configuration using one of</p><divclass="itemizedlist"><ulclass="itemizedlist compact"style="list-style-type: disc;"><liclass="listitem"><p><codeclass="literal">config.vim.lazy.plugins.*.setupOpts</code></p></li><liclass="listitem"><p><codeclass="literal">config.vim.extraPlugins.*.setup</code></p></li><liclass="listitem"><p><codeclass="literal">config.vim.luaConfigRC</code>.</p></li></ul></div><divclass="section"><divclass="titlepage"><div><div><h4id="ch-vim-lazy-plugins"class="title">Lazy Plugins </h4></div></div></div><p><codeclass="literal">config.vim.lazy.plugins.*.setupOpts</code> is useful for lazy-loading plugins, and
uses an extended version of <codeclass="literal">lz.n's</code><codeclass="literal">PluginSpec</code> to expose a familiar
interface. <codeclass="literal">setupModule</code> and <codeclass="literal">setupOpt</code> can be used if the plugin uses a
<codeclass="literal">require('module').setup(...)</code> pattern. Otherwise, the <codeclass="literal">before</code> and <codeclass="literal">after</code>
hooks should do what you need.</p><pre><codeclass="programlisting nix">{
config.vim.lazy.plugins = {
aerial.nvim = {
# ^^^^^^^^^ this name should match the package.pname or package.name
package = aerial-nvim;
setupModule = "aerial";
setupOpts = {option_name = false;};
after = "print('aerial loaded')";
};
};
}
</code></pre>
</div><divclass="section"><divclass="titlepage"><div><div><h4id="ch-vim-extra-plugins"class="title">Standard API </h4></div></div></div><p><codeclass="literal">vim.extraPlugins</code> uses an attribute set, which maps DAG section names to a
custom type, which has the fields <codeclass="literal">package</code>, <codeclass="literal">after</code>, <codeclass="literal">setup</code>. They allow you to
set the package of the plugin, the sections its setup code should be after (note
that the <codeclass="literal">extraPlugins</code> option has its own DAG scope), and the its setup code
respectively. For example:</p><pre><codeclass="programlisting nix">{pkgs, ...}: {
after = ["aerial"]; # place harpoon configuration after aerial
};
};
}
</code></pre><divclass="section"><divclass="titlepage"><div><div><h5id="setup-using-luaconfigrc"class="title">Setup using luaConfigRC </h5></div></div></div><p><codeclass="literal">vim.luaConfigRC</code> also uses an attribute set, but this one is resolved as a DAG
directly. The attribute names denote the section names, and the values lua code.
For example:</p><pre><codeclass="programlisting nix">{
# This will create a section called "aquarium" in the 'init.lua' with the
# contents of your custom configuration. By default 'entryAnywhere' is implied
# in DAGs, so this will be inserted to an arbitrary position. In the case you
# wish to control the position of this section with more precision, please
</code></pre><divclass="note"><h3class="title">Note</h3><p>One of the <spanclass="strong"><strong>greatest strengths</strong></span> of <spanclass="strong"><strong>nvf</strong></span> is the ability to order
configuration snippets precisely using the <aclass="link"href="index.xhtml#ch-using-dags"title="Using DAGs">DAG system</a>. DAGs
are a very powerful mechanism that allows specifying positions
of individual sections of configuration as needed. We provide helper functions
in the extended library, usually under <codeclass="literal">inputs.nvf.lib.nvim.dag</code> that you may
use.</p><p>Please refer to the <aclass="link"href="index.xhtml#ch-dag-entries"title="DAG entries in nvf">DAG section</a> in the nvf manual
to find out more about the DAG system.</p></div>
</div>
</div>
</div><divclass="section"><divclass="titlepage"><div><div><h3id="sec-lazy-method"class="title">Lazy Method </h3></div></div></div><p>As of version <spanclass="strong"><strong>0.7</strong></span>, an API is exposed to allow configuring lazy-loaded
plugins via <codeclass="literal">lz.n</code> and <codeclass="literal">lzn-auto-require</code>. Below is a comprehensive example of
how it may be loaded to lazy-load an arbitrary plugin.</p><pre><codeclass="programlisting nix">{
config.vim.lazy.plugins = {
"aerial.nvim" = {
package = pkgs.vimPlugins.aerial-nvim;
setupModule = "aerial";
setupOpts = {
option_name = true;
};
after = ''
-- custom lua code to run after plugin is loaded
print('aerial loaded')
'';
# Explicitly mark plugin as lazy. You don't need this if you define one of
# the trigger "events" below
lazy = true;
# load on command
cmd = ["AerialOpen"];
# load on event
event = ["BufEnter"];
# load on keymap
keys = [
{
key = "<leader>a";
action = ":AerialToggle<CR>";
}
];
};
};
}
</code></pre><divclass="section"><divclass="titlepage"><div><div><h4id="sec-lazyfile-event"class="title">LazyFile event </h4></div></div></div><p><spanclass="strong"><strong>nvf</strong></span> re-implements <codeclass="literal">LazyFile</code> as a familiar user event to load a plugin when
a file is opened:</p><pre><codeclass="programlisting nix">{
</code></pre><p>You can consider the <codeclass="literal">LazyFile</code> event as an alias to the combination of
<codeclass="literal">"BufReadPost"</code>, <codeclass="literal">"BufNewFile"</code> and <codeclass="literal">"BufWritePre"</code>, i.e., a list containing all
three of those events: <codeclass="literal">["BufReadPost""BufNewFile""BufWritePre"]</code></p>
</div>
</div><divclass="section"><divclass="titlepage"><div><div><h3id="sec-non-lazy-method"class="title">Non-lazy Method </h3></div></div></div><p>As of version <spanclass="strong"><strong>0.5</strong></span>, we have a more extensive API for configuring plugins that
should be preferred over the legacy method. This API is available as
<aclass="xref"href="options.html#opt-vim.extraPlugins"><codeclass="option">vim.extraPlugins</code></a>. Instead of using DAGs exposed by the library
<spanclass="emphasis"><em>directly</em></span>, you may use the extra plugin module as follows:</p><pre><codeclass="programlisting nix">{pkgs, ...}: {
</code></pre><p>This provides a level of abstraction over the DAG system for faster iteration.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h3id="sec-legacy-method"class="title">Legacy Method </h3></div></div></div><p>Prior to version <spanclass="strong"><strong>0.5</strong></span>, the method of adding new plugins was adding the plugin
package to <aclass="xref"href="options.html#opt-vim.startPlugins"><codeclass="option">vim.startPlugins</code></a> and adding its configuration as a DAG under
one of <codeclass="literal">vim.configRC</code> or <aclass="xref"href="options.html#opt-vim.luaConfigRC"><codeclass="option">vim.luaConfigRC</code></a>. While <codeclass="literal">configRC</code> has been
deprecated, users who have not yet updated to 0.5 or those who prefer a more
hands-on approach may choose to use the old method where the load order of the
plugins is explicitly determined by DAGs without internal abstractions.</p><divclass="section"><divclass="titlepage"><div><div><h4id="sec-adding-new-plugins"class="title">Adding New Plugins </h4></div></div></div><p>To add a plugin not available in <spanclass="strong"><strong>nvf</strong></span> as a module to your configuration using
the legacy method, you must add it to <aclass="xref"href="options.html#opt-vim.startPlugins"><codeclass="option">vim.startPlugins</code></a> in order to make
it available to Neovim at runtime.</p><pre><codeclass="programlisting nix">{pkgs, ...}: {
# Add a Neovim plugin from Nixpkgs to the runtime.
# This does not need to come explicitly from packages. 'vim.startPlugins'
# takes a list of *string* (to load internal plugins) or *package* to load
# a Neovim package from any source.
vim.startPlugins = [pkgs.vimPlugins.aerial-nvim];
}
</code></pre><p>Once the package is available in Neovim’s runtime, you may use the <codeclass="literal">luaConfigRC</code>
option to provide configuration as a DAG using the <spanclass="strong"><strong>nvf</strong></span> extended library in
order to configure the added plugin,</p><pre><codeclass="programlisting nix">{inputs, ...}: let
# This assumes you have an input called 'nvf' in your flake inputs
# and 'inputs' in your specialArgs. In the case you have passed 'nvf'
# to specialArgs, the 'inputs' prefix may be omitted.
inherit (inputs.nvf.lib.nvim.dag) entryAnywhere;
in {
# luaConfigRC takes Lua configuration verbatim and inserts it at an arbitrary
# position by default or if 'entryAnywhere' is used.
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-overriding-plugins"class="title">Overriding plugins </h2></div></div></div><p>The <aclass="link"href="index.xhtml#sec-additional-plugins"title="Adding Plugins">additional plugins section</a> details the addition
of new plugins to nvf under regular circumstances, i.e. while making a pull
request to the project. You may <spanclass="emphasis"><em>override</em></span> those plugins in your config to
change source versions, e.g., to use newer versions of plugins that are not yet
updated in <spanclass="strong"><strong>nvf</strong></span>.</p><pre><codeclass="programlisting nix">vim.pluginOverrides = {
lazydev-nvim = pkgs.fetchFromGitHub {
owner = "folke";
repo = "lazydev.nvim";
rev = "";
hash = "";
};
# It's also possible to use a flake input
lazydev-nvim = inputs.lazydev-nvim;
# Or a local path
lazydev-nvim = ./lazydev;
# Or a npins pin... etc
};
</code></pre><p>This will override the source for the <codeclass="literal">neodev.nvim</code> plugin that is used in nvf
with your own plugin.</p><divclass="warning"><h3class="title">Warning</h3><p>While updating plugin inputs, make sure that any configuration that has been
deprecated in newer versions is changed in the plugin’s <codeclass="literal">setupOpts</code>. If you
depend on a new version, requesting a version bump in the issues section is a
more reliable option.</p></div>
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-languages"class="title">Language Support </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-languages-custom-lsp-packages">LSP Custom Packages/Command</a></span></dt></dl></div><p>Language specific support means there is a combination of language specific
great places where you can contribute with a PR.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-languages-custom-lsp-packages"class="title"style="clear: both">LSP Custom Packages/Command </h2></div></div></div><p>One of the strengths of <spanclass="strong"><strong>nvf</strong></span> is convenient aliases to quickly configure LSP
servers through the Nix module system. By default the LSP packages for relevant
language modules will be pulled into the closure. If this is not desirable, you
may provide <spanclass="strong"><strong>a custom LSP package</strong></span> (e.g., a Bash script that calls a command)
or <spanclass="strong"><strong>a list of strings</strong></span> to be interpreted as the command to launch the language
server. By using a list of strings, you can use this to skip automatic
installation of a language server, and instead use the one found in your <codeclass="literal">$PATH</code>
during runtime, for example:</p><pre><codeclass="programlisting nix">vim.languages.java = {
lsp = {
enable = true;
# This expects 'jdt-language-server' to be in your PATH or in
# 'vim.extraPackages.' There are no additional checks performed to see
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-using-dags"class="title">Using DAGs </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-types-dag-entryAnywhere">entryAnywhere</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#ch-types-dag-entryAfter">entryAfter</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#ch-types-dag-entryBefore">entryBefore</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-types-dag-entryBetween">entryBetween</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-types-dag-entriesAnywhere">entriesAnywhere</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-types-dag-entriesAfter">entriesAfter</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-types-dag-entriesBefore">entriesBefore</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-types-dag-entriesBetween">entriesBetween</a></span></dt></dl></div><p>We conform to the NixOS options types for the most part, however, a noteworthy
explains in more detail the overall usage logic of the DAG type.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-types-dag-entryAnywhere"class="title"style="clear: both">entryAnywhere </h2></div></div></div><divclass="blockquote"><blockquoteclass="blockquote"><p><codeclass="literal">nvf.lib.nvim.dag.entryAnywhere (value: T) : DagEntry<T></code></p></blockquote></div><p>Indicates that <codeclass="literal">value</code> can be placed anywhere within the DAG. This is also the
default for plain attribute set entries, that is</p><pre><codeclass="programlisting nix"># For 'nvf' to be available in module's arguments,
# it needs to be inherited from imports in the modules array as:
</div><divclass="section"><divclass="titlepage"><div><div><h2id="ch-types-dag-entryAfter"class="title"style="clear: both">entryAfter </h2></div></div></div><divclass="blockquote"><blockquoteclass="blockquote"><p><codeclass="literal">nvf.lib.nvim.dag.entryAfter (afters: list string) (value: T) : DagEntry<T></code></p></blockquote></div><p>Indicates that <codeclass="literal">value</code> must be placed <spanclass="emphasis"><em>after</em></span> each of the attribute names in the
given list. For example</p><pre><codeclass="programlisting nix">foo.bar = {
a = 0;
b = nvf.lib.nvim.dag.entryAfter [ "a" ] 1;
}
</code></pre><p>would place <codeclass="literal">b</code> after <codeclass="literal">a</code> in the graph.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="ch-types-dag-entryBefore"class="title"style="clear: both">entryBefore </h2></div></div></div><divclass="blockquote"><blockquoteclass="blockquote"><p><codeclass="literal">nvf.lib.nvim.dag.entryBefore (befores: list string) (value: T) : DagEntry<T></code></p></blockquote></div><p>Indicates that <codeclass="literal">value</code> must be placed <spanclass="emphasis"><em>before</em></span> each of the attribute names in
the given list. For example</p><pre><codeclass="programlisting nix">foo.bar = {
b = nvf.lib.nvim.dag.entryBefore [ "a" ] 1;
a = 0;
}
</code></pre><p>would place <codeclass="literal">b</code> before <codeclass="literal">a</code> in the graph.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-types-dag-entryBetween"class="title"style="clear: both">entryBetween </h2></div></div></div><divclass="blockquote"><blockquoteclass="blockquote"><p><codeclass="literal">nvf.lib.nvim.dag.entryBetween (befores: list string) (afters: list string) (value: T) : DagEntry<T></code></p></blockquote></div><p>Indicates that <codeclass="literal">value</code> must be placed <spanclass="emphasis"><em>before</em></span> the attribute names in the first
list and <spanclass="emphasis"><em>after</em></span> the attribute names in the second list. For example</p><pre><codeclass="programlisting nix">foo.bar = {
a = 0;
c = nvf.lib.nvim.dag.entryBetween [ "b" ] [ "a" ] 2;
b = 1;
}
</code></pre><p>would place <codeclass="literal">c</code> before <codeclass="literal">b</code> and after <codeclass="literal">a</code> in the graph.</p><p>There are also a set of functions that generate a DAG from a list. These are
convenient when you just want to have a linear list of DAG entries, without
having to manually enter the relationship between each entry. Each of these
functions take a <codeclass="literal">tag</code> as argument and the DAG entries will be named
<codeclass="literal">${tag}-${index}</code>.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-types-dag-entriesAnywhere"class="title"style="clear: both">entriesAnywhere </h2></div></div></div><divclass="blockquote"><blockquoteclass="blockquote"><p><codeclass="literal">nvf.lib.nvim.dag.entriesAnywhere (tag: string) (values: [T]) : Dag<T></code></p></blockquote></div><p>Creates a DAG with the given values with each entry labeled using the given tag.
For example</p><pre><codeclass="programlisting nix">foo.bar = nvf.lib.nvim.dag.entriesAnywhere "a" [ 0 1 ];
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-types-dag-entriesAfter"class="title"style="clear: both">entriesAfter </h2></div></div></div><divclass="blockquote"><blockquoteclass="blockquote"><p><codeclass="literal">nvf.lib.nvim.dag.entriesAfter (tag: string) (afters: list string) (values: [T]) : Dag<T></code></p></blockquote></div><p>Creates a DAG with the given values with each entry labeled using the given tag.
The list of values are placed are placed <spanclass="emphasis"><em>after</em></span> each of the attribute names in
<codeclass="literal">afters</code>. For example</p><pre><codeclass="programlisting nix">foo.bar =
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-types-dag-entriesBefore"class="title"style="clear: both">entriesBefore </h2></div></div></div><divclass="blockquote"><blockquoteclass="blockquote"><p><codeclass="literal">nvf.lib.nvim.dag.entriesBefore (tag: string) (befores: list string) (values: [T]) : Dag<T></code></p></blockquote></div><p>Creates a DAG with the given values with each entry labeled using the given tag.
The list of values are placed <spanclass="emphasis"><em>before</em></span> each of the attribute names in <codeclass="literal">befores</code>.
For example</p><pre><codeclass="programlisting nix">foo.bar =
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-types-dag-entriesBetween"class="title"style="clear: both">entriesBetween </h2></div></div></div><divclass="blockquote"><blockquoteclass="blockquote"><p><codeclass="literal">nvf.lib.nvim.dag.entriesBetween (tag: string) (befores: list string) (afters: list string) (values: [T]) : Dag<T></code></p></blockquote></div><p>Creates a DAG with the given values with each entry labeled using the given tag.
The list of values are placed <spanclass="emphasis"><em>before</em></span> each of the attribute names in <codeclass="literal">befores</code>
and <spanclass="emphasis"><em>after</em></span> each of the attribute names in <codeclass="literal">afters</code>. For example</p><pre><codeclass="programlisting nix">foo.bar =
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-dag-entries"class="title">DAG entries in nvf </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#ch-vim-luaconfigrc"><codeclass="literal">vim.luaConfigRC</code> (top-level DAG)</a></span></dt></dl></div><p>From the previous chapter, it should be clear that DAGs are useful, because you
can add code that relies on other code. However, if you don’t know what the
entries are called, it’s hard to do that, so here is a list of the internal
entries in nvf:</p><divclass="section"><divclass="titlepage"><div><div><h2id="ch-vim-luaconfigrc"class="title"style="clear: both"><codeclass="literal">vim.luaConfigRC</code> (top-level DAG) </h2></div></div></div><divclass="orderedlist"><olclass="orderedlist compact"type="1"><liclass="listitem"><p>(<codeclass="literal">luaConfigPre</code>) - not a part of the actual DAG, instead, it’s simply
inserted before the rest of the DAG</p></li><liclass="listitem"><p><codeclass="literal">globalsScript</code> - used to set globals defined in <codeclass="literal">vim.globals</code></p></li><liclass="listitem"><p><codeclass="literal">basic</code> - used to set basic configuration options</p></li><liclass="listitem"><p><codeclass="literal">optionsScript</code> - used to set options defined in <codeclass="literal">vim.o</code></p></li><liclass="listitem"><p><codeclass="literal">theme</code> (this is simply placed before <codeclass="literal">pluginConfigs</code> and <codeclass="literal">lazyConfigs</code>,
meaning that surrounding entries don’t depend on it) - used to set up the
theme, which has to be done before other plugins</p></li><liclass="listitem"><p><codeclass="literal">lazyConfigs</code> - <codeclass="literal">lz.n</code> and <codeclass="literal">lzn-auto-require</code> configs. If <codeclass="literal">vim.lazy.enable</code>
is false, this will contain each plugin’s config instead.</p></li><liclass="listitem"><p><codeclass="literal">pluginConfigs</code> - the result of the nested <codeclass="literal">vim.pluginRC</code> (internal option,
see the <aclass="link"href="/index.xhtml#ch-custom-plugins"target="_top">Custom Plugins</a> page for adding your
own plugins) DAG, used to set up internal plugins</p></li><liclass="listitem"><p><codeclass="literal">extraPluginConfigs</code> - the result of <codeclass="literal">vim.extraPlugins</code>, which is not a
direct DAG, but is converted to, and resolved as one internally</p></li><liclass="listitem"><p><codeclass="literal">mappings</code> - the result of <codeclass="literal">vim.maps</code></p></li></ol></div>
</div>
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="ch-autocmds-augroups"class="title">Autocommands and Autogroups </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-vim-augroups">Autogroups (<codeclass="literal">vim.augroups</code>)</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-vim-autocmds">Autocommands (<codeclass="literal">vim.autocmds</code>)</a></span></dt></dl></div><p>This module allows you to declaratively configure Neovim autocommands and
autogroups within your Nix configuration.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-vim-augroups"class="title"style="clear: both">Autogroups (<codeclass="literal">vim.augroups</code>) </h2></div></div></div><p>Autogroups (<codeclass="literal">augroup</code>) organize related autocommands. This allows them to be
managed collectively, such as clearing them all at once to prevent duplicates.
Each entry in the list is a submodule with the following options:</p><divclass="informaltable"><tableclass="informaltable"border="1"><colgroup><colalign="left"/><colalign="left"/><colalign="left"/><colalign="left"/><colalign="left"/></colgroup><thead><tr><thalign="left">Option</th><thalign="left">Type</th><thalign="left">Default</th><thalign="left">Description</th><thalign="left">Example</th></tr></thead><tbody><tr><tdalign="left"><codeclass="literal">enable</code></td><tdalign="left"><codeclass="literal">bool</code></td><tdalign="left"><codeclass="literal">true</code></td><tdalign="left">Enables or disables this autogroup definition.</td><tdalign="left"><codeclass="literal">true</code></td></tr><tr><tdalign="left"><codeclass="literal">name</code></td><tdalign="left"><codeclass="literal">str</code></td><tdalign="left"><spanclass="emphasis"><em>None</em></span></td><tdalign="left"><spanclass="strong"><strong>Required.</strong></span> The unique name for the autogroup.</td><tdalign="left"><codeclass="literal">"MyFormatGroup"</code></td></tr><tr><tdalign="left"><codeclass="literal">clear</code></td><tdalign="left"><codeclass="literal">bool</code></td><tdalign="left"><codeclass="literal">true</code></td><tdalign="left">Clears any existing autocommands within this group before adding new ones defined in <codeclass="literal">vim.autocmds</code>.</td><tdalign="left"><codeclass="literal">true</code></td></tr></tbody></table></div><p><spanclass="strong"><strong>Example:</strong></span></p><pre><codeclass="programlisting nix">{
vim.augroups = [
{
name = "MyCustomAuGroup";
clear = true; # Clear previous autocommands in this group on reload
}
{
name = "Formatting";
# clear defaults to true
}
];
}
</code></pre>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-vim-autocmds"class="title"style="clear: both">Autocommands (<codeclass="literal">vim.autocmds</code>) </h2></div></div></div><p>Autocommands (<codeclass="literal">autocmd</code>) trigger actions based on events happening within Neovim
(e.g., saving a file, entering a buffer). Each entry in the list is a submodule
with the following options:</p><divclass="informaltable"><tableclass="informaltable"border="1"><colgroup><colalign="left"/><colalign="left"/><colalign="left"/><colalign="left"/><colalign="left"/></colgroup><thead><tr><thalign="left">Option</th><thalign="left">Type</th><thalign="left">Default</th><thalign="left">Description</th><thalign="left">Example</th></tr></thead><tbody><tr><tdalign="left"><codeclass="literal">enable</code></td><tdalign="left"><codeclass="literal">bool</code></td><tdalign="left"><codeclass="literal">true</code></td><tdalign="left">Enables or disables this autocommand definition.</td><tdalign="left"><codeclass="literal">true</code></td></tr><tr><tdalign="left"><codeclass="literal">event</code></td><tdalign="left"><codeclass="literal">nullOr (listOf str)</code></td><tdalign="left"><codeclass="literal">null</code></td><tdalign="left"><spanclass="strong"><strong>Required.</strong></span> List of Neovim events that trigger this autocommand (e.g., <codeclass="literal">BufWritePre</code>, <codeclass="literal">FileType</code>).</td><tdalign="left"><codeclass="literal">[ "BufWritePre" ]</code></td></tr><tr><tdalign="left"><codeclass="literal">pattern</code></td><tdalign="left"><codeclass="literal">nullOr (listOf str)</code></td><tdalign="left"><codeclass="literal">null</code></td><tdalign="left">List of file patterns (globs) to match against (e.g., <codeclass="literal">*.py</code>, <codeclass="literal">*</code>). If <codeclass="literal">null</code>, matches all files for the given event.</td><tdalign="left"><codeclass="literal">[ "*.lua", "*.nix" ]</code></td></tr><tr><tdalign="left"><codeclass="literal">callback</code></td><tdalign="left"><codeclass="literal">nullOr luaInline</code></td><tdalign="left"><codeclass="literal">null</code></td><tdalign="left">A Lua function to execute when the event triggers. Use <codeclass="literal">lib.nvim.types.luaInline</code> or <codeclass="literal">lib.options.literalExpression "mkLuaInline '''...'''"</code>. <spanclass="strong"><strong>Cannot be used with <codeclass="literal">command</code>.</strong></span></td><tdalign="left"><codeclass="literal">lib.nvim.types.luaInline "function() print('File saved!') end"</code></td></tr><tr><tdalign="left"><codeclass="literal">command</code></td><tdalign="left"><codeclass="literal">nullOr str</code></td><tdalign="left"><codeclass="literal">null</code></td><tdalign="left">A Vimscript command to execute when the event triggers. <spanclass="strong"><strong>Cannot be used with <codeclass="literal">callback</code>.</strong></span></td><tdalign="left"><codeclass="literal">"echo 'File saved!'"</code></td></tr><tr><tdalign="left"><codeclass="literal">group</code></td><tdalign="left"><codeclass="literal">nullOr str</code></td><tdalign="left"><codeclass="literal">null</code></td><tdalign="left">The name of an <codeclass="literal">augroup</code> (defined in <codeclass="literal">vim.augroups</code>) to associate this autocommand with.</td><tdalign="left"><codeclass="literal">"MyCustomAuGroup"</code></td></tr><tr><tdalign="left"><codeclass="literal">desc</code></td><tdalign="left"><codeclass="literal">nullOr str</code></td><tdalign="left"><codeclass="literal">null</code></td><tdalign="left">A description for the autocommand (useful for introspection).</td><tdalign="left"><codeclass="literal">"Format buffer on save"</code></td></tr><tr><tdalign="left"><codeclass="literal">once</code></td><tdalign="left"><codeclass="literal">bool</code></td><tdalign="left"><codeclass="literal">false</code></td><tdalign="left">If <codeclass="literal">true</code>, the autocommand runs only once and then automatically removes itself.</td><tdalign="left"><codeclass="literal">false</code></td></tr><tr><tdalign="left"><codeclass="literal">nested</code></td><tdalign="left"><codeclass="literal">bool</code></td><tdalign="left"><codeclas
Vimscript) for the same autocommand. Choose one.</p></div><p><spanclass="strong"><strong>Examples:</strong></span></p><pre><codeclass="programlisting nix">{ lib, ... }:
{
vim.augroups = [ { name = "UserSetup"; } ];
</code></pre><p>These definitions are automatically translated into the necessary Lua code to
configure <codeclass="literal">vim.api.nvim_create_augroup</code> and <codeclass="literal">vim.api.nvim_create_autocmd</code> when
Neovim starts.</p>
</div>
</div>
</div><divclass="part"><divclass="titlepage"><div><div><h1id="ch-helpful-tips"class="title">Helpful Tips </h1></div></div></div><divclass="partintro"><p>This section provides helpful tips that may be considered “unorthodox” or “too
advanced” for some users. We will cover basic debugging steps, offline
documentation, configuring <spanclass="strong"><strong>nvf</strong></span> with pure Lua and using custom plugin sources
in <spanclass="strong"><strong>nvf</strong></span> in this section. For general configuration tips, please see previous
chapters.</p><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="chapter"><ahref="index.xhtml#sec-debugging-nvf">Debugging nvf</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#sec-offline-documentation">Offline Documentation</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#sec-pure-lua-config">Pure Lua Configuration</a></span></dt><dt><spanclass="chapter"><ahref="index.xhtml#sec-plugin-sources">Adding Plugins From Different Sources</a></span></dt></dl></div></div><divclass="chapter"><divclass="titlepage"><div><div><h2id="sec-debugging-nvf"class="title">Debugging nvf </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-accessing-config">Accessing <codeclass="literal">neovimConfig</code></a></span></dt></dl></div><p>There may be instances where the your Nix configuration evaluates to invalid
Lua, or times when you will be asked to provide your built Lua configuration for
easier debugging by nvf maintainers. nvf provides two helpful utilities out of
the box.</p><p><spanclass="strong"><strong>nvf-print-config</strong></span> and <spanclass="strong"><strong>nvf-print-config-path</strong></span> will be bundled with nvf as
lightweight utilities to help you view or share your built configuration when
necessary.</p><p>To view your configuration with syntax highlighting, you may use the
<aclass="link"href="https://github.com/sharkdp/bat"target="_top">bat pager</a>.</p><pre><codeclass="programlisting bash">nvf-print-config | bat --language=lua
</code></pre><p>Alternatively, <codeclass="literal">cat</code> or <codeclass="literal">less</code> may also be used.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-accessing-config"class="title"style="clear: both">Accessing <codeclass="literal">neovimConfig</code></h2></div></div></div><p>It is also possible to access the configuration for the wrapped package. The
<spanclass="emphasis"><em>built</em></span> Neovim package will contain a <codeclass="literal">neovimConfig</code> attribute in its
<codeclass="literal">passthru</code>.</p>
</div>
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="sec-offline-documentation"class="title">Offline Documentation </h2></div></div></div><p>The manpages provided by nvf contains an offline version of the option search
normally available at <aclass="link"href="https://notashelf.github.io/nvf/options.html"target="_top">https://notashelf.github.io/nvf/options.html</a>. You may
use the <codeclass="literal">man 5 nvf</code> command to view option documentation from the comfort of
your terminal.</p><p>Note that this is only available for NixOS and Home-Manager module
installations.</p>
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="sec-pure-lua-config"class="title">Pure Lua Configuration </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-pure-nvf-runtime">Pure Runtime Directory</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-impure-absolute-dir">Impure Absolute Directory</a></span></dt></dl></div><p>We recognize that you might not always want to configure your setup purely in
Nix, sometimes doing things in Lua is simply the “superior” option. In such a
case you might want to configure your Neovim instance using Lua, and nothing but
Lua. It is also possible to mix Lua and Nix configurations.</p><p>Pure Lua or hybrid Lua/Nix configurations can be achieved in two different ways.
<spanclass="emphasis"><em>Purely</em></span>, by modifying Neovim’s runtime directory or <spanclass="emphasis"><em>impurely</em></span> by placing Lua
configuration in a directory found in <codeclass="literal">$HOME</code>. For your convenience, this
section will document both methods as they can be used.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-pure-nvf-runtime"class="title"style="clear: both">Pure Runtime Directory </h2></div></div></div><p>As of 0.6, nvf allows you to modify Neovim’s runtime path to suit your needs.
One of the ways the new runtime option is to add a configuration <spanclass="strong"><strong>located
relative to your <codeclass="literal">flake.nix</code></strong></span>, which must be version controlled in pure flakes
manner.</p><pre><codeclass="programlisting nix">{
# Let us assume we are in the repository root, i.e., the same directory as the
# flake.nix. For the sake of the argument, we will assume that the Neovim lua
# configuration is in a nvim/ directory relative to flake.nix.
vim = {
additionalRuntimePaths = [
# This will be added to Neovim's runtime paths. Conceptually, this behaves
# very similarly to ~/.config/nvim but you may not place a top-level
# init.lua to be able to require it directly.
./nvim
];
};
}
</code></pre><p>This will add the <codeclass="literal">nvim</code> directory, or rather, the <spanclass="emphasis"><em>store path</em></span> that will be
realised after your flake gets copied to the Nix store, to Neovim’s runtime
directory. You may now create a <codeclass="literal">lua/myconfig</code> directory within this nvim
directory, and call it with <aclass="xref"href="options.html#opt-vim.luaConfigRC"><codeclass="option">vim.luaConfigRC</code></a>.</p><pre><codeclass="programlisting nix">{pkgs, ...}: {
vim = {
additionalRuntimePaths = [
# You can list more than one file here.
./nvim-custom-1
# To make sure list items are ordered, use lib.mkBefore or lib.mkAfter
# Simply placing list items in a given order will **not** ensure that
# this list will be deterministic.
./nvim-custom-2
];
startPlugins = [pkgs.vimPlugins.gitsigns];
# Neovim supports in-line syntax highlighting for multi-line strings.
# Simply place the filetype in a /* comment */ before the line.
luaConfigRC.myconfig = /* lua */ ''
-- Call the Lua module from ./nvim/lua/myconfig
require("myconfig")
-- Any additional Lua configuration that you might want *after* your own
-- configuration. For example, a plugin setup call.
require('gitsigns').setup({})
'';
};
}
</code></pre>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-impure-absolute-dir"class="title"style="clear: both">Impure Absolute Directory </h2></div></div></div><p>As of <aclass="link"href="https://github.com/neovim/neovim/pull/22128"target="_top">Neovim 0.9</a>, <codeclass="varname">$NVIM_APPNAME</code> is a variable expected by Neovim to
decide on the configuration directory. nvf sets this variable as <codeclass="literal">"nvf"</code>,
meaning <codeclass="literal">~/.config/nvf</code> will be regarded as <spanclass="emphasis"><em>the</em></span> configuration directory by
Neovim, similar to how <codeclass="literal">~/.config/nvim</code> behaves in regular installations. This
allows some degree of Lua configuration, backed by our low-level wrapper
<aclass="link"href="https://github.com/Gerg-L/mnw"target="_top">mnw</a>. Creating a <codeclass="literal">lua/</code> directory located in
<codeclass="literal">$NVIM_APPNAME</code> (“nvf” by default) and placing your configuration in, e.g.,
<codeclass="literal">~/.config/nvf/lua/myconfig</code> will allow you to <codeclass="literal">require</code> it as a part of the Lua
module system through nvf’s module system.</p><p>Let’s assume your <codeclass="literal">~/.config/nvf/lua/myconfig/init.lua</code> consists of the
</code></pre><p>The following Nix configuration via <aclass="xref"href="options.html#opt-vim.luaConfigRC"><codeclass="option">vim.luaConfigRC</code></a> will allow loading
this</p><pre><codeclass="programlisting nix">{
# The attribute name "myconfig-dir" here is arbitrary. It is required to be
# a *named* attribute by the DAG system, but the name is entirely up to you.
vim.luaConfigRC.myconfig-dir = ''
require("myconfig")
-- Any additional Lua
'';
}
</code></pre><p>After you load your custom configuration, you may use an <codeclass="literal">init.lua</code> located in
your custom configuration directory to configure Neovim exactly as you would
without a wrapper like nvf. If you want to place your <codeclass="literal">require</code> call in a
specific position (i.e., before or after options you set in nvf) the
<aclass="link"href="https://notashelf.github.io/nvf/index.xhtml#ch-using-dags"target="_top">DAG system</a> will let you place your configuration in a location of your
choosing.</p>
</div>
</div><divclass="chapter"><divclass="titlepage"><div><div><h2id="sec-plugin-sources"class="title">Adding Plugins From Different Sources </h2></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#ch-plugins-from-nixpkgs">Nixpkgs & Friends</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#ch-plugins-from-source">Building Your Own Plugins</a></span></dt></dl></div><p><spanclass="strong"><strong>nvf</strong></span> attempts to avoid depending on Nixpkgs for Neovim plugins. For the most
part, this is accomplished by defining each plugin’s source and building them
from source.</p><p>To define plugin sources, we use <aclass="link"href="https://github.com/andir/npins"target="_top">npins</a> and pin each plugin source using
builtin fetchers. You are not bound by this restriction. In your own
configuration, any kind of fetcher or plugin source is fine.</p><divclass="section"><divclass="titlepage"><div><div><h2id="ch-plugins-from-nixpkgs"class="title"style="clear: both">Nixpkgs & Friends </h2></div></div></div><p><codeclass="literal">vim.startPlugins</code> and <codeclass="literal">vim.optPlugins</code> options take either a <spanclass="strong"><strong>string</strong></span>, in
which case a plugin from nvf’s internal plugins registry will be used, or a
<spanclass="strong"><strong>package</strong></span>. If your plugin does not require any setup, or ordering for it s
configuration, then it is possible to add it to <codeclass="literal">vim.startPlugins</code> to load it on
# Aerial does require some setup. In the case you pass a plugin that *does*
# require manual setup, then you must also call the setup function.
vim.startPlugins = [pkgs.vimPlugins.aerial-nvim];
}
</code></pre><p>This will fetch aerial.nvim from nixpkgs, and add it to Neovim’s runtime path to
be loaded manually. Although for plugins that require manual setup, you are
encouraged to use <aclass="link"href="https://notashelf.github.io/nvf/options.html#opt-vim.extraPlugins"target="_top"><codeclass="literal">vim.extraPlugins</code></a>.</p><pre><codeclass="programlisting nix">{
</div><divclass="section"><divclass="titlepage"><div><div><h2id="ch-plugins-from-source"class="title"style="clear: both">Building Your Own Plugins </h2></div></div></div><p>In the case a plugin is not available in Nixpkgs, or the Nixpkgs package is
outdated (or, more likely, broken) it is possible to build the plugins from
source using a tool, such as <aclass="link"href="https://github.com/andir/npins"target="_top">npins</a>. You may also use your <spanclass="emphasis"><em>flake inputs</em></span> as
sources.</p><p>Example using plugin inputs:</p><pre><codeclass="programlisting nix">{
# In your flake.nix
inputs = {
aerial-nvim = {
url = "github:stevearc/aerial.nvim"
flake = false;
};
};
# Make sure that 'inputs' is properly propagated into Nvf, for example, through
# specialArgs.
outputs = { ... };
}
</code></pre><p>In the case, you may use the input directly for the plugin’s source attribute in
<codeclass="literal">buildVimPlugin</code>.</p><pre><codeclass="programlisting nix"># Make sure that 'inputs' is properly propagated! It will be missing otherwise
</div><divclass="chapter"><divclass="titlepage"><div><div><h1id="ch-hacking"class="title">Hacking nvf </h1></div></div></div><divclass="toc"><p><strong>Table of Contents</strong></p><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-contrib-getting-started">Getting Started</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-guidelines">Guidelines</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-testing-changes">Testing Changes</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-keybinds">Keybinds</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-additional-plugins">Adding Plugins</a></span></dt></dl></div><p>nvf is designed for the developer as much as it is designed for the end-user. We
would like for any contributor to be able to propagate their changes, or add new
features to the project with minimum possible friction. As such, below are the
guides and guidelines written to streamline the contribution process and to
ensure that your valuable input integrates into nvf’s development as seamlessly
as possible without leaving any question marks in your head.</p><p>This section is directed mainly towards those who wish to contribute code into
the project. If you instead wish to report a bug, or discuss a potential new
feature implementation (which you do not wish to implement yourself) first look
among the already <aclass="link"href="https://github.com/notashelf/nvf/issues"target="_top">open issues</a> and if no matching issue exists you may open a
<aclass="link"href="https://github.com/notashelf/nvf/issues/new"target="_top">new issue</a> and describe your problem/request.</p><p>While creating an issue, please try to include as much information as you can,
ideally also include relevant context in which an issue occurs or a feature
should be implemented. If you wish to make a contribution, but feel stuck -
please do not be afraid to submit a pull request, we will help you get it in.</p><divclass="section"><divclass="titlepage"><div><div><h1id="sec-contrib-getting-started"class="title"style="clear: both">Getting Started </h1></div></div></div><p>You, naturally, would like to start by forking the repository to get started. If
you are new to Git and GitHub, do have a look at GitHub’s
<aclass="link"href="https://help.github.com/articles/fork-a-repo/"target="_top">Fork a repo guide</a> for
instructions on how you can do this. Once you have a fork of <spanclass="strong"><strong>nvf</strong></span>, you should
create a separate branch based on the most recent <codeclass="literal">main</code> branch. Give your
branch a reasonably descriptive name (e.g. <codeclass="literal">feature/debugger</code> or
<codeclass="literal">fix/pesky-bug</code>) and you are ready to work on your changes</p><p>Implement your changes and commit them to the newly created branch and when you
are happy with the result, and positive that it fulfills our
<aclass="link"href="index.xhtml#sec-guidelines"title="Guidelines">Contributing Guidelines</a>, push the branch to GitHub and
<aclass="link"href="https://help.github.com/articles/creating-a-pull-request"target="_top">create a pull request</a>.
The default pull request template available on the <spanclass="strong"><strong>nvf</strong></span> repository will guide
you through the rest of the process, and we’ll gently nudge you in the correct
direction if there are any mistakes.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h1id="sec-guidelines"class="title"style="clear: both">Guidelines </h1></div></div></div><divclass="toc"><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-guidelines-documentation">Adding Documentation</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-guidelines-formatting">Formatting Code</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-guidelines-commit-message-style">Formatting Commits</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-guidelines-commit-style">Commit Style</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-guidelines-ex-commit-message">Example Commit</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-guidelines-code-style">Code Style</a></span></dt></dl></div><p>If your contribution tightly follows the guidelines, then there is a good chance
it will be merged without too much trouble. Some of the guidelines will be
strictly enforced, others will remain as gentle nudges towards the correct
direction. As we have no automated system enforcing those guidelines, please try
to double check your changes before making your pull request in order to avoid
“faulty” code slipping by.</p><p>If you are uncertain how these rules affect the change you would like to make
then feel free to start a discussion in the
<aclass="link"href="https://github.com/NotAShelf/nvf/discussions"target="_top">discussions tab</a> ideally (but not
necessarily) before you start developing.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-guidelines-documentation"class="title"style="clear: both">Adding Documentation </h2></div></div></div><p>Almost all changes warrant updates to the documentation: at the very least, you
must update the changelog. Both the manual and module options use
<aclass="link"href="https://github.com/NixOS/nixpkgs/blob/master/doc/README.md#syntax"target="_top">Nixpkgs Flavoured Markdown</a>.</p><p>The HTML version of this manual containing both the module option descriptions
and the documentation of <spanclass="strong"><strong>nvf</strong></span> (such as this page) can be generated and opened
by typing the following in a shell within a clone of the <spanclass="strong"><strong>nvf</strong></span> Git repository:</p><pre><codeclass="programlisting console">$ nix build .#docs-html
$ xdg-open $PWD/result/share/doc/nvf/index.html
</code></pre>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-guidelines-formatting"class="title"style="clear: both">Formatting Code </h2></div></div></div><p>Make sure your code is formatted as described in
<aclass="link"href="index.xhtml#sec-guidelines-code-style"title="Code Style">code-style section</a>. To maintain consistency
throughout the project you are encouraged to browse through existing code and
adopt its style also in new code.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-guidelines-commit-message-style"class="title"style="clear: both">Formatting Commits </h2></div></div></div><p>Similar to <aclass="link"href="index.xhtml#sec-guidelines-code-style"title="Code Style">code style guidelines</a> we encourage a
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-guidelines-commit-style"class="title"style="clear: both">Commit Style </h2></div></div></div><p>The commits in your pull request should be reasonably self-contained. Which
means each and every commit in a pull request should make sense both on its own
and in general context. That is, a second commit should not resolve an issue
that is introduced in an earlier commit. In particular, you will be asked to
amend any commit that introduces syntax errors or similar problems even if they
are fixed in a later commit.</p><p>The commit messages should follow the
<aclass="link"href="https://chris.beams.io/posts/git-commit/#seven-rule"target="_top">seven rules</a>, except for
“Capitalize the subject line”. We also ask you to include the affected code
component or module in the first line. A commit message ideally, but not
necessarily, follow the given template from home-manager’s own documentation</p><pre><codeclass="programlisting"> {component}: {description}
{long description}
</code></pre><p>where <codeclass="literal">{component}</code> refers to the code component (or module) your change
affects, <codeclass="literal">{description}</code> is a very brief description of your change, and
<codeclass="literal">{long description}</code> is an optional clarifying description. As a rare exception,
if there is no clear component, or your change affects many components, then the
<codeclass="literal">{component}</code> part is optional. See
<aclass="link"href="index.xhtml#sec-guidelines-ex-commit-message"title="Example Commit">example commit message</a> for a commit message
in home-manager contains the following commit message.</p><pre><codeclass="programlisting">starship: allow running in Emacs if vterm is used
The vterm buffer is backed by libvterm and can handle Starship prompts
without issues.
</code></pre><p>Similarly, if you are contributing to <spanclass="strong"><strong>nvf</strong></span>, you would include the scope of
the commit followed by the description:</p><pre><codeclass="programlisting">languages/ruby: init module
Adds a language module for Ruby, adds appropriate formatters and Treesitter grammars
</code></pre><p>Long description can be omitted if the change is too simple to warrant it. A
minor fix in spelling or a formatting change does not warrant long description,
however, a module addition or removal does as you would like to provide the
relevant context, i.e. the reasoning behind it, for your commit.</p><p>Finally, when adding a new module, say <codeclass="literal">modules/foo.nix</code>, we use the fixed
commit format <codeclass="literal">foo: add module</code>. You can, of course, still include a long
description if you wish.</p><p>In case of nested modules, i.e <codeclass="literal">modules/languages/java.nix</code> you are recommended
to contain the parent as well - for example <codeclass="literal">languages/java: some major change</code>.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-guidelines-code-style"class="title"style="clear: both">Code Style </h2></div></div></div><divclass="section"><divclass="titlepage"><div><div><h3id="sec-code-style-treewide"class="title">Treewide </h3></div></div></div><p>Keep lines at a reasonable width, ideally 80 characters or less. This also
applies to string literals and module descriptions and documentation.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h3id="sec-code-style-nix"class="title">Nix </h3></div></div></div><p><spanclass="strong"><strong>nvf</strong></span> is formatted by the <aclass="link"href="https://github.com/kamadorueda/alejandra"target="_top">alejandra</a> tool and the formatting is checked in
the pull request and push workflows. Run the <codeclass="literal">nix fmt</code> command inside the
project repository before submitting your pull request.</p><p>While Alejandra is mostly opinionated on how code looks after formatting,
certain changes are done at the user’s discretion based on how the original code
was structured.</p><p>Please use one line code for attribute sets that contain only one subset. For
example:</p><pre><codeclass="programlisting nix"># parent modules should always be unfolded
# which means module = { value = ... } instead of module.value = { ... }
module = {
value = mkEnableOption "some description" // { default = true; }; # merges can be done inline where possible
# same as parent modules, unfold submodules
subModule = {
# this is an option that contains more than one nested value
# Note: try to be careful about the ordering of `mkOption` arguments.
# General rule of thumb is to order from least to most likely to change.
# This is, for most cases, type < default < description.
# Example, if present, would be between default and description
someOtherValue = mkOption {
type = lib.types.bool;
default = true;
description = "Some other description";
};
};
}
</code></pre><p>If you move a line down after the merge operator, Alejandra will automatically
unfold the whole merged attrset for you, which we <spanclass="strong"><strong>do not</strong></span> want.</p><pre><codeclass="programlisting nix">module = {
# this is also ok if the list is expected to contain more elements
acceptableList= [
item1
item2
# more items if needed...
];
</code></pre>
</div>
</div>
</div><divclass="section"><divclass="titlepage"><div><div><h1id="sec-testing-changes"class="title"style="clear: both">Testing Changes </h1></div></div></div><p>Once you have made your changes, you will need to test them thoroughly. If it is
a module, add your module option to <codeclass="literal">configuration.nix</code> (located in the root of
this project) inside <codeclass="literal">neovimConfiguration</code>. Enable it, and then run the maximal
configuration with <codeclass="literal">nix run .#maximal -Lv</code> to check for build errors. If neovim
opens in the current directory without any error messages (you can check the
output of <codeclass="literal">:messages</code> inside neovim to see if there are any errors), then your
changes are good to go. Open your pull request, and it will be reviewed as soon
as possible.</p><p>If it is not a new module, but a change to an existing one, then make sure the
module you have changed is enabled in the maximal configuration by editing
<codeclass="literal">configuration.nix</code>, and then run it with <codeclass="literal">nix run .#maximal -Lv</code>. Same
procedure as adding a new module will apply here.</p>
</div><divclass="section"><divclass="titlepage"><div><div><h1id="sec-keybinds"class="title"style="clear: both">Keybinds </h1></div></div></div><divclass="toc"><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-custom-key-mappings">Custom Key Mappings Support for a Plugin</a></span></dt></dl></div><p>As of 0.4, there exists an API for writing your own keybinds and a couple of
useful utility functions are available in the
<aclass="link"href="https://github.com/NotAShelf/nvf/tree/main/lib"target="_top">extended standard library</a>. The
following section contains a general overview to how you may utilize said
functions.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-custom-key-mappings"class="title"style="clear: both">Custom Key Mappings Support for a Plugin </h2></div></div></div><p>To set a mapping, you should define it in <codeclass="literal">vim.keymaps</code>.</p><p>An example, simple keybinding, can look like this:</p><pre><codeclass="programlisting nix">{
vim.keymaps = [
{
key = "<leader>wq";
mode = ["n"];
action = ":wq<CR>";
silent = true;
desc = "Save file and quit";
}
];
}
</code></pre><p>There are many settings available in the options. Please refer to the
<aclass="link"href="https://notashelf.github.io/nvf/options.html#opt-vim.keymaps"target="_top">documentation</a> to
see a list of them.</p><p><spanclass="strong"><strong>nvf</strong></span> provides a helper function, so that you don’t have to write the mapping
attribute sets every time:</p><divclass="itemizedlist"><ulclass="itemizedlist compact"style="list-style-type: disc;"><liclass="listitem"><p><codeclass="literal">mkKeymap</code>, which mimics neovim’s <codeclass="literal">vim.keymap.set</code> function</p></li></ul></div><p>You can read the source code of some modules to see them in action, but the
usage should look something like this:</p><pre><codeclass="programlisting nix"># plugindefinition.nix
</code></pre><divclass="note"><h3class="title">Note</h3><p>If you have come across a plugin that has an API that doesn’t seem to easily
allow custom keybindings, don’t be scared to implement a draft PR. We’ll help
you get it done.</p></div>
</div>
</div><divclass="section"><divclass="titlepage"><div><div><h1id="sec-additional-plugins"class="title"style="clear: both">Adding Plugins </h1></div></div></div><divclass="toc"><dlclass="toc"><dt><spanclass="section"><ahref="index.xhtml#sec-npins-for-plugins">With npins</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-pkgs-for-plugins">Packaging Complex Plugins</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-modular-setup-options">Modular setup options</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-details-of-toluaobject">Details of toLuaObject</a></span></dt><dt><spanclass="section"><ahref="index.xhtml#sec-lazy-plugins">Lazy plugins</a></span></dt></dl></div><p>There are two methods for adding new Neovim plugins to <spanclass="strong"><strong>nvf</strong></span>. npins is the
faster option that should be preferred if the plugin consists of pure Lua or
Vimscript code. In which case there is no building required, and we can easily
handle the copying of plugin files. Alternative method, which is required when
plugins try to build their own libraries (e.g., in Rust or C) that need to be
built with Nix to function correctly.</p><divclass="section"><divclass="titlepage"><div><div><h2id="sec-npins-for-plugins"class="title"style="clear: both">With npins </h2></div></div></div><p>npins is the standard method of adding new plugins to <spanclass="strong"><strong>nvf</strong></span>. You simply need
the repository URL for the plugin, and can add it as a source to be built
automatically with one command. To add a new Neovim plugin, use <codeclass="literal">npins</code>. For
example:</p><pre><codeclass="programlisting bash">nix-shell -p npins # or nix shell nixpkgs#npins if using flakes
</code></pre><divclass="note"><h3class="title">Note</h3><p>Be sure to replace any non-alphanumeric characters with <codeclass="literal">-</code> for <codeclass="literal">--name</code>. For
example</p><pre><codeclass="programlisting bash">npins add --name lazydev-nvim github folke lazydev.nvim -b main
</code></pre></div><p>Once the <codeclass="literal">npins</code> command is done, you can start referencing the plugin as a
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-pkgs-for-plugins"class="title"style="clear: both">Packaging Complex Plugins </h2></div></div></div><p>Some plugins require additional packages to be built and substituted to function
correctly. For example <aclass="link"href="https://github.com/Saghen/blink.cmp"target="_top">blink.cmp</a> requires its own fuzzy matcher library, built
with Rust, to be installed or else defaults to a much slower Lua implementation.
In the Blink documentation, you are advised to build with <codeclass="literal">cargo</code> but that is
not ideal since we are leveraging the power of Nix. In this case the ideal
solution is to write a derivation for the plugin.</p><p>We use <codeclass="literal">buildRustPackage</code> to build the library from the repository root, and
copy everything in the <codeclass="literal">postInstall</code> phase.</p><pre><codeclass="programlisting nix">postInstall = ''
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-modular-setup-options"class="title"style="clear: both">Modular setup options </h2></div></div></div><p>Most plugins is initialized with a call to <codeclass="literal">require('plugin').setup({...})</code>.</p><p>We use a special function that lets you easily add support for such setup
options in a modular way: <codeclass="literal">mkPluginSetupOption</code>.</p><p>Once you have added the source of the plugin as shown above, you can define the
setup options like this:</p><pre><codeclass="programlisting nix"># in modules/.../your-plugin/your-plugin.nix
</code></pre><p>This above config will result in this Lua script:</p><pre><codeclass="programlisting lua">require('plugin-name').setup({
enable_feature_a = false,
number_option = 3,
})
</code></pre><p>Now users can set any of the pre-defined option field, and can also add their
own fields!</p><pre><codeclass="programlisting nix"># in user's config
{
vim.your-plugin.setupOpts = {
enable_feature_a = true;
number_option = 4;
another_field = "hello";
size = { # nested fields work as well
top = 10;
};
};
}
</code></pre>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-details-of-toluaobject"class="title"style="clear: both">Details of toLuaObject </h2></div></div></div><p>As you’ve seen above, <codeclass="literal">toLuaObject</code> is used to convert our nix attrSet
<codeclass="literal">cfg.setupOpts</code>, into a lua table. Here are some rules of the conversion:</p><divclass="orderedlist"><olclass="orderedlist "type="1"><liclass="listitem"><p>Nix <codeclass="literal">null</code> converts to lua <codeclass="literal">nil</code></p></li><liclass="listitem"><p>Number and strings convert to their lua counterparts</p></li><liclass="listitem"><p>Nix attribute sets (<codeclass="literal">{}</code>) and lists (<codeclass="literal">[]</code>) convert into Lua dictionaries and
tables respectively. Here is an example of Nix -> Lua conversion.</p><divclass="itemizedlist"><ulclass="itemizedlist compact"style="list-style-type: disc;"><liclass="listitem"><p><codeclass="literal">{foo = "bar"}</code> -><codeclass="literal">{["foo"] = "bar"}</code></p></li><liclass="listitem"><p><codeclass="literal">["foo""bar"]</code> -><codeclass="literal">{"foo", "bar"}</code></p></li></ul></div></li><liclass="listitem"><p>You can write raw Lua code using <codeclass="literal">lib.generators.mkLuaInline</code>. This function
is part of nixpkgs, and is accessible without relying on <spanclass="strong"><strong>nvf</strong></span>’s extended
library.</p><divclass="itemizedlist"><ulclass="itemizedlist compact"style="list-style-type: disc;"><liclass="listitem"><p><codeclass="literal">mkLuaInline "function add(a, b) return a + b end"</code> will yield the
following result:</p></li></ul></div><pre><codeclass="programlisting nix">{
_type = "lua-inline";
expr = "function add(a, b) return a + b end";
}
</code></pre><p>The above expression will be interpreted as a Lua expression in the final
config. Without the <codeclass="literal">mkLuaInline</code> function, you will only receive a string
literal. You can use it to feed plugin configuration tables Lua functions
that return specific values as expected by the plugins.</p><pre><codeclass="programlisting nix">{
vim.your-plugin.setupOpts = {
on_init = lib.generators.mkLuaInline ''
function()
print('we can write lua!')
end
'';
};
}
</code></pre></li></ol></div>
</div><divclass="section"><divclass="titlepage"><div><div><h2id="sec-lazy-plugins"class="title"style="clear: both">Lazy plugins </h2></div></div></div><p>If the plugin can be lazy-loaded, <codeclass="literal">vim.lazy.plugins</code> should be used to add it.
Lazy plugins are managed by <codeclass="literal">lz.n</code>.</p><pre><codeclass="programlisting nix"># in modules/.../your-plugin/config.nix
{config, ...}: let
cfg = config.vim.your-plugin;
in {
vim.lazy.plugins.your-plugin = {
# Instead of vim.startPlugins, use this:
package = "your-plugin";
# ıf your plugin uses the `require('your-plugin').setup{...}` pattern
setupModule = "your-plugin";
inherit (cfg) setupOpts;
# Events that trigger this plugin to be loaded
event = ["DirChanged"];
cmd = ["YourPluginCommand"];
# Plugin Keymaps
keys = [
# We'll cover this in detail in the 'keybinds' section
{
key = "<leader>d";
mode = "n";
action = ":YourPluginCommand";
}
];
};
}
</code></pre><p>This results in the following lua code:</p><pre><codeclass="programlisting lua">require('lz.n').load({
</code></pre><p>A full list of options can be found in the <aclass="link"href="https://notashelf.github.io/nvf/options.html#opt-vim.lazy.plugins"target="_top"><codeclass="literal">vim.lazy.plugins</code> spec</a> on the