<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><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
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
</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
</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
</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
<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
</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
</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
</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
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
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
</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
</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
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
</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
</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, ...}: {
</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">{
</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
</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
</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
</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">{
</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><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, ...}: {
with your own plugin.</p><divclass="warning"><h3class="title">Warning</h3><p>While updating plugin inputs, make sure that any configuration that has been
</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
plugins, <codeclass="literal">treesitter</code> support, <codeclass="literal">nvim-lspconfig</code> language servers, and <codeclass="literal">null-ls</code>
<codeclass="literal">vim.languages</code> attribute.</p><divclass="itemizedlist"><ulclass="itemizedlist compact"style="list-style-type: disc;"><liclass="listitem"><p>Rust: <aclass="link"href="options.html#opt-vim.languages.rust.enable">vim.languages.rust.enable</a></p></li><liclass="listitem"><p>Nix: <aclass="link"href="options.html#opt-vim.languages.nix.enable">vim.languages.nix.enable</a></p></li><liclass="listitem"><p>SQL: <aclass="link"href="options.html#opt-vim.languages.sql.enable">vim.languages.sql.enable</a></p></li><liclass="listitem"><p>C/C++: <aclass="link"href="options.html#opt-vim.languages.clang.enable">vim.languages.clang.enable</a></p></li><liclass="listitem"><p>Typescript/Javascript: <aclass="link"href="options.html#opt-vim.languages.ts.enable">vim.languages.ts.enable</a></p></li><liclass="listitem"><p>Python: <aclass="link"href="options.html#opt-vim.languages.python.enable">vim.languages.python.enable</a>:</p></li><liclass="listitem"><p>Zig: <aclass="link"href="options.html#opt-vim.languages.zig.enable">vim.languages.zig.enable</a></p></li><liclass="listitem"><p>Markdown: <aclass="link"href="options.html#opt-vim.languages.markdown.enable">vim.languages.markdown.enable</a></p></li><liclass="listitem"><p>HTML: <aclass="link"href="options.html#opt-vim.languages.html.enable">vim.languages.html.enable</a></p></li><liclass="listitem"><p>Dart: <aclass="link"href="options.html#opt-vim.languages.dart.enable">vim.languages.dart.enable</a></p></li><liclass="listitem"><p>Go: <aclass="link"href="options.html#opt-vim.languages.go.enable">vim.languages.go.enable</a></p></li><liclass="listitem"><p>Lua: <aclass="link"href="options.html#opt-vim.languages.lua.enable">vim.languages.lua.enable</a></p></li><liclass="listitem"><p>PHP: <aclass="link"href="options.html#opt-vim.languages.php.enable">vim.languages.php.enable</a></p></li><liclass="listitem"><p>F#: <aclass="link"href="options.html#opt-vim.languages.fsharp.enable">vim.languages.fsharp.enable</a></p></li></ul></div><p>Adding support for more languages, and improving support for existing ones are
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 = {
</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">lib.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">foo.bar = {
</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">lib.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 = {
</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">lib.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 = {
</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">lib.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 = {
</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">lib.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 = lib.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">lib.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">lib.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">lib.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
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><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
</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.
# 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, ...}: {
# 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
</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
</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
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
</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
</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
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,
</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 = {
</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
</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
<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">{
<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
</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
</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";
</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
</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