nvf/docs-preview-1051/index.xhtml
2025-09-02 02:38:22 +00:00

1451 lines
No EOL
123 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>nvf manual</title>
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="highlightjs/highlight.pack.js" type="text/javascript"></script><script src="highlightjs/loader.js" type="text/javascript"></script><script src="script/anchor-use.js" type="text/javascript"></script><script src="script/anchor-min.js" type="text/javascript"></script><script src="script/search.js" type="text/javascript"></script>
<meta name="generator" content="nixos-render-docs" />
<link rel="home" href="index.xhtml" title="nvf manual" />
<link rel="next" href="quirks.html" title="Appendix A. Known Issues and Quirks" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">nvf manual</th>
</tr>
<tr>
<td width="20%" align="left">&nbsp;</td>
<th width="60%" align="center">&nbsp;</th>
<td width="20%" align="right">&nbsp;<a accesskey="n" href="quirks.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="book">
<div class="titlepage">
<div>
<div><h1 class="title"><a id="nvf-manual"></a>nvf manual</h1></div>
<div><h2 class="subtitle">Version v0.8</h2></div>
</div>
<hr />
</div>
<div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="preface"> <a href="index.xhtml#ch-preface">Preface</a> </span></dt><dt> <span class="preface"> <a href="index.xhtml#ch-try-it-out">Try it out</a> </span></dt><dt> <span class="part"> <a href="index.xhtml#ch-installation">Installing nvf</a> </span></dt><dd><dl><dt> <span class="chapter"> <a href="index.xhtml#ch-standalone-installation">Standalone Installation</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-module-installation">Module Installation</a> </span></dt></dl></dd><dt> <span class="part"> <a href="index.xhtml#ch-configuring">Configuring nvf</a> </span></dt><dd><dl><dt> <span class="chapter"> <a href="index.xhtml#ch-custom-package">Custom Neovim Package</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-custom-plugins">Custom Plugins</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-overriding-plugins">Overriding plugins</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-languages">Language Support</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-using-dags">Using DAGs</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-dag-entries">DAG entries in nvf</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-autocmds-augroups">Autocommands and Autogroups</a> </span></dt></dl></dd><dt> <span class="part"> <a href="index.xhtml#ch-helpful-tips">Helpful Tips</a> </span></dt><dd><dl><dt> <span class="chapter"> <a href="index.xhtml#sec-debugging-nvf">Debugging nvf</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#sec-offline-documentation">Offline Documentation</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#sec-pure-lua-config">Pure Lua Configuration</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#sec-plugin-sources">Adding Plugins From Different Sources</a> </span></dt></dl></dd><dt> <span class="chapter"> <a href="index.xhtml#ch-hacking">Hacking nvf</a> </span></dt><dt> <span class="appendix"> <a href="quirks.html">A. Known Issues and Quirks</a> </span></dt><dt> <span class="appendix"> <a href="options.html">B. nvf Configuration Options</a> </span></dt><dt> <span class="appendix"> <a href="release-notes.html">C. Release Notes</a> </span></dt> </dl></div>
<div class="preface"> <div class="titlepage"> <div> <div> <h1 id="ch-preface" class="title" >Preface </h1> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-what-is-it">What is nvf</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-bugs-suggestions">Bugs &amp; Suggestions</a> </span></dt> </dl></div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="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><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-bugs-suggestions" class="title" >Bugs &amp; Suggestions </h2> </div> </div></div><p>If you notice any issues with nvf, or this documentation, then please consider
reporting them over at the <a class="link" href="https://github.com/notashelf/nvf/issues" target="_top">issue tracker</a>. Issues tab, in addition to the
<a class="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 <a class="link" href="https://github.com/notashelf/nvf/pulls" target="_top">pull requests tab</a>.</p>
</div>
</div><div class="preface"> <div class="titlepage"> <div> <div> <h1 id="ch-try-it-out" class="title" >Try it out </h1> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="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><div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc;"><li class="listitem"><p><span class="strong"><strong>Nix</strong></span> (<code class="literal">packages.nix</code>) - Nix language server + simple utility plugins</p></li><li class="listitem"><p><span class="strong"><strong>Maximal</strong></span> (<code class="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 <code class="literal">nix run</code> command
on a system where Nix is installed.</p><pre><code class="programlisting sh">$ cachix use nvf # Optional: it&#x27;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 <span class="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><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-using-prebuilt-configs" class="title" >Using Prebuilt Configs </h2> </div> </div></div><div class="toc"> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-available-configs">Available Configurations</a> </span></dt> </dl></div><pre><code class="programlisting bash">$ nix run github:notashelf/nvf#nix
$ nix run github:notashelf/nvf#maximal
</code></pre><div class="section"> <div class="titlepage"> <div> <div> <h3 id="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
<span class="strong"><strong>not</strong></span> designed to be installed as is. You may</p><div class="section"> <div class="titlepage"> <div> <div> <h4 id="sec-configs-nix" class="title" >Nix </h4> </div> </div></div><p><code class="literal">Nix</code> configuration by default provides LSP/diagnostic support for Nix alongside
a set of visual and functional plugins. By running <code class="literal">nix run .#</code>, which is the
default package, you will build Neovim with this config.</p><pre><code class="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 <code class="literal">nix</code> configuration lets you see how a
fully configured Neovim setup <span class="emphasis"><em>might</em></span> look like without downloading too many
packages or shell utilities.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h4 id="sec-configs-maximal" class="title" >Maximal </h4> </div> </div></div><p><code class="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><code class="programlisting bash">$ nix run github:notashelf/nvf#maximal -- test.nix
</code></pre><p>It uses the same configuration template with the <a class="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><div class="warning"><h3 class="title">Warning</h3><p>Running the maximal config will download <span class="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><div class="part"> <div class="titlepage"> <div> <div> <h1 id="ch-installation" class="title" >Installing nvf </h1> </div> </div></div><div class="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
<a class="link" href="index.xhtml#ch-module-installation" title="Module Installation" >module installation section</a>.</p><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="chapter"> <a href="index.xhtml#ch-standalone-installation">Standalone Installation</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-module-installation">Module Installation</a> </span></dt> </dl></div></div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="ch-standalone-installation" class="title" >Standalone Installation </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="chapter"> <a href="index.xhtml#ch-standalone-nixos">Standalone Installation on NixOS</a> </span></dt><dt> <span class="chapter"> <a href="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 <code class="literal">neovimConfiguration</code> function exposed in the
extended library. This function will take <code class="literal">modules</code> and <code class="literal">extraSpecialArgs</code> as
arguments, and return the following schema as a result.</p><pre><code class="programlisting nix">{
options = &quot;The options that were available to configure&quot;;
config = &quot;The outputted configuration&quot;;
pkgs = &quot;The package set used to evaluate the module&quot;;
neovim = &quot;The built neovim package&quot;;
}
</code></pre><p>An example flake that exposes your custom Neovim configuration might look like</p><pre><code class="programlisting nix">{
inputs = {
nixpkgs.url = &quot;github:NixOS/nixpkgs/nixos-unstable&quot;;
nvf.url = &quot;github:notashelf/nvf&quot;;
};
outputs = {nixpkgs, ...} @ inputs: {
packages.x86_64-linux = {
# 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><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="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 <code class="literal">nvf</code> as a standalone package with
the default theme enabled. You may use other options inside <code class="literal">config.vim</code> in
<code class="literal">configModule</code>, but this example will not cover that extensively.</p><pre><code class="programlisting nix">{
inputs = {
nixpkgs.url = &quot;github:NixOS/nixpkgs/nixos-unstable&quot;;
home-manager.url = &quot;github:nix-community/home-manager&quot;;
nvf.url = &quot;github:notashelf/nvf&quot;;
};
outputs = {
nixpkgs,
nvf,
self,
...
}: {
# This will make the package available as a flake output under &#x27;packages&#x27;
packages.x86_64-linux.my-neovim =
(nvf.lib.neovimConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
modules = [
# Or move this to a separate file and add it&#x27;s path here instead
# IE: ./nvf_module.nix
(
{pkgs, ...}: {
# Add any custom options (and do feel free to upstream them!)
# options = { ... };
config.vim = {
theme.enable = true;
# and more options as you see fit...
};
}
)
];
})
.neovim;
# Example nixosConfiguration using the configured Neovim package
nixosConfigurations = {
yourHostName = nixpkgs.lib.nixosSystem {
# ...
modules = [
# This will make wrapped neovim available in your system packages
# Can also move this to another config file if you pass your own
# inputs/self around with specialArgs
({pkgs, ...}: {
environment.systemPackages = [self.packages.${pkgs.stdenv.system}.neovim];
})
];
# ...
};
};
};
}
</code></pre>
</div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="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 <code class="literal">nvf</code> as a standalone package with
the default theme enabled. You may use other options inside <code class="literal">config.vim</code> in
<code class="literal">configModule</code>, but this example will not cover that extensively.</p><pre><code class="programlisting nix">{
inputs = {
nixpkgs.url = &quot;github:NixOS/nixpkgs/nixos-unstable&quot;;
home-manager.url = &quot;github:nix-community/home-manager&quot;;
nvf.url = &quot;github:notashelf/nvf&quot;;
};
outputs = {nixpkgs, home-manager, nvf, ...}: let
system = &quot;x86_64-linux&quot;;
pkgs = nixpkgs.legacyPackages.${system};
configModule = {
# Add any custom options (and do feel free to upstream them!)
# options = { ... };
config.vim = {
theme.enable = true;
# and more options as you see fit...
};
};
customNeovim = nvf.lib.neovimConfiguration {
inherit pkgs;
modules = [configModule];
};
in {
# This will make the package available as a flake output under &#x27;packages&#x27;
packages.${system}.my-neovim = customNeovim.neovim;
# Example Home-Manager configuration using the configured Neovim package
homeConfigurations = {
&quot;your-username@your-hostname&quot; = home-manager.lib.homeManagerConfiguration {
# ...
modules = [
# 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><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="ch-module-installation" class="title" >Module Installation </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="chapter"> <a href="index.xhtml#ch-nixos-module">NixOS Module</a> </span></dt><dt> <span class="chapter"> <a href="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><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="ch-nixos-module" class="title" >NixOS Module </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-nixos-flakes">With Flakes</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-nixos-flakeless">Without Flakes</a> </span></dt> </dl></div><p>The NixOS module allows us to customize the different <code class="literal">vim</code> options from inside
the NixOS configuration without having to call for the wrapper yourself. It is
the recommended way to use <span class="strong"><strong>nvf</strong></span> alongside the home-manager module depending
on your needs.</p><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-nixos-flakes" class="title" style="clear: both">With Flakes </h2> </div> </div></div><div class="toc"> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-nixos-flakes-usage">Usage</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-example-installation-nixos">Example Installation</a> </span></dt> </dl></div><pre><code class="programlisting {=include=}">flakes.md
</code></pre><div class="section"> <div class="titlepage"> <div> <div> <h3 id="sec-nixos-flakes-usage" class="title" >Usage </h3> </div> </div></div><p>To use <span class="strong"><strong>nvf</strong></span> with flakes, we first need to add the input to our <code class="literal">flake.nix</code>.</p><pre><code class="programlisting nix"># flake.nix
{
inputs = {
# Optional, if you intend to follow nvf&#x27;s obsidian-nvim input
# you must also add it as a flake input.
obsidian-nvim.url = &quot;github:epwalsh/obsidian.nvim&quot;;
# Required, nvf works best and only directly supports flakes
nvf = {
url = &quot;github:NotAShelf/nvf&quot;;
# You can override the input nixpkgs to follow your system&#x27;s
# instance of nixpkgs. This is safe to do as nvf does not depend
# on a binary cache.
inputs.nixpkgs.follows = &quot;nixpkgs&quot;;
# Optionally, you can also override individual plugins
# for example:
inputs.obsidian-nvim.follows = &quot;obsidian-nvim&quot;; # &lt;- this will use the obsidian-nvim from your inputs
};
# ...
};
}
</code></pre><p>Followed by importing the NixOS module somewhere in your configuration.</p><pre><code class="programlisting nix">{
# assuming nvf is in your inputs and inputs is in the argset
# see example below
imports = [ inputs.nvf.nixosModules.default ];
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h3 id="sec-example-installation-nixos" class="title" >Example Installation </h3> </div> </div></div><pre><code class="programlisting nix">{
inputs = {
nixpkgs.url = &quot;github:NixOS/nixpkgs/nixos-unstable&quot;;
nvf.url = &quot;github:notashelf/nvf&quot;;
};
outputs = { nixpkgs, nvf, ... }: {
# ↓ this is your host output in the flake schema
nixosConfigurations.&quot;your-hostname&quot; = nixpkgs.lib.nixosSystem {
modules = [
nvf.nixosModules.default # &lt;- this imports the NixOS module that provides the options
./configuration.nix # &lt;- your host entrypoint, `programs.nvf.*` may be defined here
];
};
};
}
</code></pre><p>Once the module is properly imported by your host, you will be able to use the
<code class="literal">programs.nvf</code> module option anywhere in your configuration in order to
configure <span class="strong"><strong>nvf</strong></span>.</p><pre><code class="programlisting nix">{
programs.nvf = {
enable = true;
# 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><div class="note"><h3 class="title">Note</h3><p><span class="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
<a class="link" href="https://notashelf.github.io/nvf/options" target="_top">appendix</a></p></div>
</div>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-nixos-flakeless" class="title" style="clear: both">Without Flakes </h2> </div> </div></div><p>As of v0.8, it is possible to install <span class="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 <code class="literal">builtins.fetchTarball</code> or a
similar mechanism.</p><pre><code class="programlisting nix"># configuration.nix
let
nvf = import (builtins.fetchTarball {
url = &quot;https://github.com/notashelf/nvf/archive/&lt;commit or tag&gt;.tar.gz&quot;;
# Optionally, you can add &#x27;sha256&#x27; for verification and caching
# sha256 = &quot;&lt;sha256&gt;&quot;;
});
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><div class="tip"><h3 class="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 <a class="link" href="https://github.com/andir/npins" target="_top">npins</a> or <a class="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
convenient dependency management mechanisms.</p></div>
</div>
</div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="ch-hm-module" class="title" >Home-Manager Module </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-hm-flakes">With Flakes</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-hm-flakeless">Without Flakes</a> </span></dt> </dl></div><p>The home-manager module allows us to customize the different <code class="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 <span class="strong"><strong>nvf</strong></span> alongside the NixOS module
depending on your needs.</p><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-hm-flakes" class="title" style="clear: both">With Flakes </h2> </div> </div></div><div class="toc"> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-hm-flakes-usage">Usage</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-example-installation-hm">Example Installation</a> </span></dt> </dl></div><pre><code class="programlisting {=include=}">flakes.md
</code></pre><div class="section"> <div class="titlepage"> <div> <div> <h3 id="sec-hm-flakes-usage" class="title" >Usage </h3> </div> </div></div><p>To use <span class="strong"><strong>nvf</strong></span> with flakes, we first need to add the input to our <code class="literal">flake.nix</code>.</p><pre><code class="programlisting nix"># flake.nix
{
inputs = {
# Optional, if you intend to follow nvf&#x27;s obsidian-nvim input
# you must also add it as a flake input.
obsidian-nvim.url = &quot;github:epwalsh/obsidian.nvim&quot;;
# Required, nvf works best and only directly supports flakes
nvf = {
url = &quot;github:NotAShelf/nvf&quot;;
# You can override the input nixpkgs to follow your system&#x27;s
# instance of nixpkgs. This is safe to do as nvf does not depend
# on a binary cache.
inputs.nixpkgs.follows = &quot;nixpkgs&quot;;
# Optionally, you can also override individual plugins
# for example:
inputs.obsidian-nvim.follows = &quot;obsidian-nvim&quot;; # &lt;- this will use the obsidian-nvim from your inputs
};
# ...
};
}
</code></pre><p>Followed by importing the home-manager module somewhere in your configuration.</p><pre><code class="programlisting nix">{
# Assuming &quot;nvf&quot; is in your inputs and inputs is in the argument set.
# See example installation below
imports = [ inputs.nvf.homeManagerModules.default ];
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h3 id="sec-example-installation-hm" class="title" >Example Installation </h3> </div> </div></div><pre><code class="programlisting nix">{
inputs = {
nixpkgs.url = &quot;github:NixOS/nixpkgs/nixos-unstable&quot;;
home-manager.url = &quot;github:nix-community/home-manager&quot;;
nvf.url = &quot;github:notashelf/nvf&quot;;
};
outputs = { nixpkgs, home-manager, nvf, ... }: {
# ↓ this is your home output in the flake schema, expected by home-manager
&quot;your-username@your-hostname&quot; = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
modules = [
nvf.homeManagerModules.default # &lt;- this imports the home-manager module that provides the options
./home.nix # &lt;- your home entrypoint, `programs.nvf.*` may be defined here
];
};
};
}
</code></pre><p>Once the module is properly imported by your host, you will be able to use the
<code class="literal">programs.nvf</code> module option anywhere in your configuration in order to
configure <span class="strong"><strong>nvf</strong></span>.</p><pre><code class="programlisting nix">{
programs.nvf = {
enable = true;
# 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><div class="note"><h3 class="title">Note</h3><p><span class="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
<a class="link" href="https://notashelf.github.io/nvf/options" target="_top">appendix</a></p></div>
</div>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-hm-flakeless" class="title" style="clear: both">Without Flakes </h2> </div> </div></div><p>As of v0.8, it is possible to install <span class="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 <code class="literal">builtins.fetchTarball</code> or a
similar mechanism.</p><pre><code class="programlisting nix"># home.nix
let
nvf = import (builtins.fetchTarball {
url = &quot;https://github.com/notashelf/nvf/archive/&lt;commit or tag&gt;.tar.gz&quot;;
# Optionally, you can add &#x27;sha256&#x27; for verification and caching
# sha256 = &quot;&lt;sha256&gt;&quot;;
});
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><div class="tip"><h3 class="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 <a class="link" href="https://github.com/andir/npins" target="_top">npins</a> or <a class="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
convenient dependency management mechanisms.</p></div>
</div>
</div>
</div>
</div><div class="part"> <div class="titlepage"> <div> <div> <h1 id="ch-configuring" class="title" >Configuring nvf </h1> </div> </div></div><div class="partintro"><p>nvf allows for <span class="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 <a class="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 <span class="emphasis"><em>options</em></span>. For an overview of all
module options provided by nvf, please visit the <a class="link" href="/nvf/options.html" target="_top">appendix</a></p><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="chapter"> <a href="index.xhtml#ch-custom-package">Custom Neovim Package</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-custom-plugins">Custom Plugins</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-overriding-plugins">Overriding plugins</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-languages">Language Support</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-using-dags">Using DAGs</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-dag-entries">DAG entries in nvf</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#ch-autocmds-augroups">Autocommands and Autogroups</a> </span></dt> </dl></div></div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="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 <a class="xref" href="options.html#opt-vim.package" ><code class="option">vim.package</code></a> option.</p><pre><code class="programlisting nix">{inputs, pkgs, ...}: {
# using the neovim-nightly overlay
vim.package = inputs.neovim-overlay.packages.${pkgs.stdenv.system}.neovim;
}
</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 <code class="literal">neovim-unwrapped</code> in nixpkgs.</p><pre><code class="programlisting nix">{ pkgs, ...}: {
# using the neovim-nightly overlay
vim.package = pkgs.neovim-unwrapped;
}
</code></pre>
</div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="ch-custom-plugins" class="title" >Custom Plugins </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#ch-adding-plugins">Adding Plugins</a> </span></dt> </dl></div><p><span class="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 <span class="strong"><strong>nvf</strong></span>s runtime with full control of versioning, testing and
dependencies. In the case a plugin you need is <span class="emphasis"><em>not</em></span> available, you may consider
making a pull request to add the package youre looking for, or you may add it
to your configuration locally. The below section describes how new plugins may
be added to the users configuration.</p><div class="section"> <div class="titlepage"> <div> <div> <h2 id="ch-adding-plugins" class="title" style="clear: both">Adding Plugins </h2> </div> </div></div><div class="toc"> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-configuring-plugins">Configuring</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-lazy-method">Lazy Method</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-non-lazy-method">Non-lazy Method</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-legacy-method">Legacy Method</a> </span></dt> </dl></div><p>Per <span class="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 <span class="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
<a class="xref" href="options.html#opt-vim.startPlugins" ><code class="option">vim.startPlugins</code></a> list in your configuration. This is akin to cloning a
plugin to <code class="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
youve added to <code class="literal">startPlugins.</code> <span class="strong"><strong>nvf</strong></span> provides multiple ways of configuring
any custom plugins that you might have added to your configuration.</p><div class="section"> <div class="titlepage"> <div> <div> <h3 id="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><div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc;"><li class="listitem"><p><code class="literal">config.vim.lazy.plugins.*.setupOpts</code></p></li><li class="listitem"><p><code class="literal">config.vim.extraPlugins.*.setup</code></p></li><li class="listitem"><p><code class="literal">config.vim.luaConfigRC</code>.</p></li></ul></div><div class="section"> <div class="titlepage"> <div> <div> <h4 id="ch-vim-lazy-plugins" class="title" >Lazy Plugins </h4> </div> </div></div><p><code class="literal">config.vim.lazy.plugins.*.setupOpts</code> is useful for lazy-loading plugins, and
uses an extended version of <code class="literal">lz.n&#x27;s</code> <code class="literal">PluginSpec</code> to expose a familiar
interface. <code class="literal">setupModule</code> and <code class="literal">setupOpt</code> can be used if the plugin uses a
<code class="literal">require(&#x27;module&#x27;).setup(...)</code> pattern. Otherwise, the <code class="literal">before</code> and <code class="literal">after</code>
hooks should do what you need.</p><pre><code class="programlisting nix">{
config.vim.lazy.plugins = {
aerial.nvim = {
# ^^^^^^^^^ this name should match the package.pname or package.name
package = aerial-nvim;
setupModule = &quot;aerial&quot;;
setupOpts = {option_name = false;};
after = &quot;print(&#x27;aerial loaded&#x27;)&quot;;
};
};
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h4 id="ch-vim-extra-plugins" class="title" >Standard API </h4> </div> </div></div><p><code class="literal">vim.extraPlugins</code> uses an attribute set, which maps DAG section names to a
custom type, which has the fields <code class="literal">package</code>, <code class="literal">after</code>, <code class="literal">setup</code>. They allow you to
set the package of the plugin, the sections its setup code should be after (note
that the <code class="literal">extraPlugins</code> option has its own DAG scope), and the its setup code
respectively. For example:</p><pre><code class="programlisting nix">{pkgs, ...}: {
config.vim.extraPlugins = {
aerial = {
package = pkgs.vimPlugins.aerial-nvim;
setup = &quot;require(&#x27;aerial&#x27;).setup {}&quot;;
};
harpoon = {
package = pkgs.vimPlugins.harpoon;
setup = &quot;require(&#x27;harpoon&#x27;).setup {}&quot;;
after = [&quot;aerial&quot;]; # place harpoon configuration after aerial
};
};
}
</code></pre><div class="section"> <div class="titlepage"> <div> <div> <h5 id="setup-using-luaconfigrc" class="title" >Setup using luaConfigRC </h5> </div> </div></div><p><code class="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><code class="programlisting nix">{
# This will create a section called &quot;aquarium&quot; in the &#x27;init.lua&#x27; with the
# contents of your custom configuration. By default &#x27;entryAnywhere&#x27; 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
# look into the DAGs section of the manual.
config.vim.luaConfigRC.aquarium = &quot;vim.cmd(&#x27;colorscheme aquiarum&#x27;)&quot;;
}
</code></pre><div class="note"><h3 class="title">Note</h3><p>One of the <span class="strong"><strong>greatest strengths</strong></span> of <span class="strong"><strong>nvf</strong></span> is the ability to order
configuration snippets precisely using the <a class="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 <code class="literal">inputs.nvf.lib.nvim.dag</code> that you may
use.</p><p>Please refer to the <a class="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><div class="section"> <div class="titlepage"> <div> <div> <h3 id="sec-lazy-method" class="title" >Lazy Method </h3> </div> </div></div><p>As of version <span class="strong"><strong>0.7</strong></span>, an API is exposed to allow configuring lazy-loaded
plugins via <code class="literal">lz.n</code> and <code class="literal">lzn-auto-require</code>. Below is a comprehensive example of
how it may be loaded to lazy-load an arbitrary plugin.</p><pre><code class="programlisting nix">{
config.vim.lazy.plugins = {
&quot;aerial.nvim&quot; = {
package = pkgs.vimPlugins.aerial-nvim;
setupModule = &quot;aerial&quot;;
setupOpts = {
option_name = true;
};
after = &#x27;&#x27;
-- custom lua code to run after plugin is loaded
print(&#x27;aerial loaded&#x27;)
&#x27;&#x27;;
# Explicitly mark plugin as lazy. You don&#x27;t need this if you define one of
# the trigger &quot;events&quot; below
lazy = true;
# load on command
cmd = [&quot;AerialOpen&quot;];
# load on event
event = [&quot;BufEnter&quot;];
# load on keymap
keys = [
{
key = &quot;&lt;leader&gt;a&quot;;
action = &quot;:AerialToggle&lt;CR&gt;&quot;;
}
];
};
};
}
</code></pre><div class="section"> <div class="titlepage"> <div> <div> <h4 id="sec-lazyfile-event" class="title" >LazyFile event </h4> </div> </div></div><p><span class="strong"><strong>nvf</strong></span> re-implements <code class="literal">LazyFile</code> as a familiar user event to load a plugin when
a file is opened:</p><pre><code class="programlisting nix">{
config.vim.lazy.plugins = {
&quot;aerial.nvim&quot; = {
package = pkgs.vimPlugins.aerial-nvim;
event = [{event = &quot;User&quot;; pattern = &quot;LazyFile&quot;;}];
# ...
};
};
}
</code></pre><p>You can consider the <code class="literal">LazyFile</code> event as an alias to the combination of
<code class="literal">&quot;BufReadPost&quot;</code>, <code class="literal">&quot;BufNewFile&quot;</code> and <code class="literal">&quot;BufWritePre&quot;</code>, i.e., a list containing all
three of those events: <code class="literal">[&quot;BufReadPost&quot; &quot;BufNewFile&quot; &quot;BufWritePre&quot;]</code></p>
</div>
</div><div class="section"> <div class="titlepage"> <div> <div> <h3 id="sec-non-lazy-method" class="title" >Non-lazy Method </h3> </div> </div></div><p>As of version <span class="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
<a class="xref" href="options.html#opt-vim.extraPlugins" ><code class="option">vim.extraPlugins</code></a>. Instead of using DAGs exposed by the library
<span class="emphasis"><em>directly</em></span>, you may use the extra plugin module as follows:</p><pre><code class="programlisting nix">{pkgs, ...}: {
config.vim.extraPlugins = {
aerial = {
package = pkgs.vimPlugins.aerial-nvim;
setup = &#x27;&#x27;
require(&#x27;aerial&#x27;).setup {
-- some lua configuration here
}
&#x27;&#x27;;
};
harpoon = {
package = pkgs.vimPlugins.harpoon;
setup = &quot;require(&#x27;harpoon&#x27;).setup {}&quot;;
after = [&quot;aerial&quot;];
};
};
}
</code></pre><p>This provides a level of abstraction over the DAG system for faster iteration.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h3 id="sec-legacy-method" class="title" >Legacy Method </h3> </div> </div></div><p>Prior to version <span class="strong"><strong>0.5</strong></span>, the method of adding new plugins was adding the plugin
package to <a class="xref" href="options.html#opt-vim.startPlugins" ><code class="option">vim.startPlugins</code></a> and adding its configuration as a DAG under
one of <code class="literal">vim.configRC</code> or <a class="xref" href="options.html#opt-vim.luaConfigRC" ><code class="option">vim.luaConfigRC</code></a>. While <code class="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><div class="section"> <div class="titlepage"> <div> <div> <h4 id="sec-adding-new-plugins" class="title" >Adding New Plugins </h4> </div> </div></div><p>To add a plugin not available in <span class="strong"><strong>nvf</strong></span> as a module to your configuration using
the legacy method, you must add it to <a class="xref" href="options.html#opt-vim.startPlugins" ><code class="option">vim.startPlugins</code></a> in order to make
it available to Neovim at runtime.</p><pre><code class="programlisting nix">{pkgs, ...}: {
# Add a Neovim plugin from Nixpkgs to the runtime.
# This does not need to come explicitly from packages. &#x27;vim.startPlugins&#x27;
# 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 Neovims runtime, you may use the <code class="literal">luaConfigRC</code>
option to provide configuration as a DAG using the <span class="strong"><strong>nvf</strong></span> extended library in
order to configure the added plugin,</p><pre><code class="programlisting nix">{inputs, ...}: let
# This assumes you have an input called &#x27;nvf&#x27; in your flake inputs
# and &#x27;inputs&#x27; in your specialArgs. In the case you have passed &#x27;nvf&#x27;
# to specialArgs, the &#x27;inputs&#x27; 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 &#x27;entryAnywhere&#x27; is used.
vim.luaConfigRC.aerial-nvim= entryAnywhere &#x27;&#x27;
require(&#x27;aerial&#x27;).setup {
-- your configuration here
}
&#x27;&#x27;;
}
</code></pre>
</div>
</div>
</div>
</div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="ch-overriding-plugins" class="title" >Overriding plugins </h2> </div> </div></div><p>The <a class="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 <span class="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 <span class="strong"><strong>nvf</strong></span>.</p><pre><code class="programlisting nix">vim.pluginOverrides = {
lazydev-nvim = pkgs.fetchFromGitHub {
owner = &quot;folke&quot;;
repo = &quot;lazydev.nvim&quot;;
rev = &quot;&quot;;
hash = &quot;&quot;;
};
# It&#x27;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 <code class="literal">neodev.nvim</code> plugin that is used in nvf
with your own plugin.</p><div class="warning"><h3 class="title">Warning</h3><p>While updating plugin inputs, make sure that any configuration that has been
deprecated in newer versions is changed in the plugins <code class="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><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="ch-languages" class="title" >Language Support </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="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, <code class="literal">treesitter</code> support, <code class="literal">nvim-lspconfig</code> language servers, <code class="literal">conform-nvim</code>
formatters, and <code class="literal">nvim-lint</code> linter integration. This gets you capabilities
ranging from autocompletion to formatting to diagnostics. The following
languages have sections under the <code class="literal">vim.languages</code> attribute.</p><div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc;"><li class="listitem"><p>Rust: <a class="link" href="options.html#opt-vim.languages.rust.enable" >vim.languages.rust.enable</a></p></li><li class="listitem"><p>Nix: <a class="link" href="options.html#opt-vim.languages.nix.enable" >vim.languages.nix.enable</a></p></li><li class="listitem"><p>SQL: <a class="link" href="options.html#opt-vim.languages.sql.enable" >vim.languages.sql.enable</a></p></li><li class="listitem"><p>C/C++: <a class="link" href="options.html#opt-vim.languages.clang.enable" >vim.languages.clang.enable</a></p></li><li class="listitem"><p>Typescript/Javascript: <a class="link" href="options.html#opt-vim.languages.ts.enable" >vim.languages.ts.enable</a></p></li><li class="listitem"><p>Python: <a class="link" href="options.html#opt-vim.languages.python.enable" >vim.languages.python.enable</a>:</p></li><li class="listitem"><p>Zig: <a class="link" href="options.html#opt-vim.languages.zig.enable" >vim.languages.zig.enable</a></p></li><li class="listitem"><p>Markdown: <a class="link" href="options.html#opt-vim.languages.markdown.enable" >vim.languages.markdown.enable</a></p></li><li class="listitem"><p>HTML: <a class="link" href="options.html#opt-vim.languages.html.enable" >vim.languages.html.enable</a></p></li><li class="listitem"><p>Dart: <a class="link" href="options.html#opt-vim.languages.dart.enable" >vim.languages.dart.enable</a></p></li><li class="listitem"><p>Go: <a class="link" href="options.html#opt-vim.languages.go.enable" >vim.languages.go.enable</a></p></li><li class="listitem"><p>Lua: <a class="link" href="options.html#opt-vim.languages.lua.enable" >vim.languages.lua.enable</a></p></li><li class="listitem"><p>PHP: <a class="link" href="options.html#opt-vim.languages.php.enable" >vim.languages.php.enable</a></p></li><li class="listitem"><p>F#: <a class="link" href="options.html#opt-vim.languages.fsharp.enable" >vim.languages.fsharp.enable</a></p></li><li class="listitem"><p>Assembly: <a class="link" href="options.html#opt-vim.languages.assembly.enable" >vim.languages.assembly.enable</a></p></li><li class="listitem"><p>Astro: <a class="link" href="options.html#opt-vim.languages.astro.enable" >vim.languages.astro.enable</a></p></li><li class="listitem"><p>Bash: <a class="link" href="options.html#opt-vim.languages.bash.enable" >vim.languages.bash.enable</a></p></li><li class="listitem"><p>Clang: <a class="link" href="options.html#opt-vim.languages.clang.enable" >vim.languages.clang.enable</a></p></li><li class="listitem"><p>Clojure: <a class="link" href="options.html#opt-vim.languages.clojure.enable" >vim.languages.clojure.enable</a></p></li><li class="listitem"><p>C#: <a class="link" href="options.html#opt-vim.languages.csharp.enable" >vim.languages.csharp.enable</a></p></li><li class="listitem"><p>CSS: <a class="link" href="options.html#opt-vim.languages.css.enable" >vim.languages.css.enable</a></p></li><li class="listitem"><p>CUE: <a class="link" href="options.html#opt-vim.languages.cue.enable" >vim.languages.cue.enable</a></p></li><li class="listitem"><p>Elixir: <a class="link" href="options.html#opt-vim.languages.elixir.enable" >vim.languages.elixir.enable</a></p></li><li class="listitem"><p>Gleam: <a class="link" href="options.html#opt-vim.languages.gleam.enable" >vim.languages.gleam.enable</a></p></li><li class="listitem"><p>HCL: <a class="link" href="options.html#opt-vim.languages.hcl.enable" >vim.languages.hcl.enable</a></p></li><li class="listitem"><p>Helm: <a class="link" href="options.html#opt-vim.languages.helm.enable" >vim.languages.helm.enable</a></p></li><li class="listitem"><p>Julia: <a class="link" href="options.html#opt-vim.languages.julia.enable" >vim.languages.julia.enable</a></p></li><li class="listitem"><p>Kotlin: <a class="link" href="options.html#opt-vim.languages.kotlin.enable" >vim.languages.kotlin.enable</a></p></li><li class="listitem"><p>Nim: <a class="link" href="options.html#opt-vim.languages.nim.enable" >vim.languages.nim.enable</a></p></li><li class="listitem"><p>Nu: <a class="link" href="options.html#opt-vim.languages.nu.enable" >vim.languages.nu.enable</a></p></li><li class="listitem"><p>OCaml: <a class="link" href="options.html#opt-vim.languages.ocaml.enable" >vim.languages.ocaml.enable</a></p></li><li class="listitem"><p>Odin: <a class="link" href="options.html#opt-vim.languages.odin.enable" >vim.languages.odin.enable</a></p></li><li class="listitem"><p>R: <a class="link" href="options.html#opt-vim.languages.r.enable" >vim.languages.r.enable</a></p></li><li class="listitem"><p>Ruby: <a class="link" href="options.html#opt-vim.languages.ruby.enable" >vim.languages.ruby.enable</a></p></li><li class="listitem"><p>Scala: <a class="link" href="options.html#opt-vim.languages.scala.enable" >vim.languages.scala.enable</a></p></li><li class="listitem"><p>Svelte: <a class="link" href="options.html#opt-vim.languages.svelte.enable" >vim.languages.svelte.enable</a></p></li><li class="listitem"><p>Tailwind: <a class="link" href="options.html#opt-vim.languages.tailwind.enable" >vim.languages.tailwind.enable</a></p></li><li class="listitem"><p>Terraform:
<a class="link" href="options.html#opt-vim.languages.terraform.enable" >vim.languages.terraform.enable</a></p></li><li class="listitem"><p>Typst: <a class="link" href="options.html#opt-vim.languages.typst.enable" >vim.languages.typst.enable</a></p></li><li class="listitem"><p>Vala: <a class="link" href="options.html#opt-vim.languages.vala.enable" >vim.languages.vala.enable</a></p></li><li class="listitem"><p>WGSL: <a class="link" href="options.html#opt-vim.languages.wgsl.enable" >vim.languages.wgsl.enable</a></p></li><li class="listitem"><p>YAML: <a class="link" href="options.html#opt-vim.languages.yaml.enable" >vim.languages.yaml.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><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-languages-custom-lsp-packages" class="title" style="clear: both">LSP Custom Packages/Command </h2> </div> </div></div><p>One of the strengths of <span class="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 <span class="strong"><strong>a custom LSP package</strong></span> (e.g., a Bash script that calls a command)
or <span class="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 <code class="literal">$PATH</code>
during runtime, for example:</p><pre><code class="programlisting nix">vim.languages.java = {
lsp = {
enable = true;
# This expects &#x27;jdt-language-server&#x27; to be in your PATH or in
# &#x27;vim.extraPackages.&#x27; There are no additional checks performed to see
# if the command provided is valid.
package = [&quot;jdt-language-server&quot; &quot;-data&quot; &quot;~/.cache/jdtls/workspace&quot;];
};
}
</code></pre>
</div>
</div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="ch-using-dags" class="title" >Using DAGs </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-types-dag-entryAnywhere">entryAnywhere</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#ch-types-dag-entryAfter">entryAfter</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#ch-types-dag-entryBefore">entryBefore</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-types-dag-entryBetween">entryBetween</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-types-dag-entriesAnywhere">entriesAnywhere</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-types-dag-entriesAfter">entriesAfter</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-types-dag-entriesBefore">entriesBefore</a> </span></dt><dt> <span class="section"> <a href="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
addition for certain options is the
<a class="link" href="https://en.wikipedia.org/wiki/Directed_acyclic_graph" target="_top"><span class="strong"><strong>DAG (Directed acyclic graph)</strong></span></a>
type which is borrowed from home-managers extended library. This type is most
used for topologically sorting strings. The DAG type allows the attribute set
entries to express dependency relations among themselves. This can, for example,
be used to control the order of configuration sections in your <code class="literal">luaConfigRC</code>.</p><p>The below section, mostly taken from the
<a class="link" href="https://raw.githubusercontent.com/nix-community/home-manager/master/docs/manual/writing-modules/types.md" target="_top">home-manager manual</a>
explains in more detail the overall usage logic of the DAG type.</p><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-types-dag-entryAnywhere" class="title" style="clear: both">entryAnywhere </h2> </div> </div></div><div class="blockquote"><blockquote class="blockquote"><p><code class="literal">nvf.lib.nvim.dag.entryAnywhere (value: T) : DagEntry&lt;T&gt;</code></p></blockquote></div><p>Indicates that <code class="literal">value</code> can be placed anywhere within the DAG. This is also the
default for plain attribute set entries, that is</p><pre><code class="programlisting nix"># For &#x27;nvf&#x27; to be available in module&#x27;s arguments,
# it needs to be inherited from imports in the modules array as:
# modules = [{ _module.args = { inherit nvf; }; } ...];
foo.bar = {
a = nvf.lib.nvim.dag.entryAnywhere 0;
}
</code></pre><p>and</p><pre><code class="programlisting nix">foo.bar = {
a = 0;
}
</code></pre><p>are equivalent.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="ch-types-dag-entryAfter" class="title" style="clear: both">entryAfter </h2> </div> </div></div><div class="blockquote"><blockquote class="blockquote"><p><code class="literal">nvf.lib.nvim.dag.entryAfter (afters: list string) (value: T) : DagEntry&lt;T&gt;</code></p></blockquote></div><p>Indicates that <code class="literal">value</code> must be placed <span class="emphasis"><em>after</em></span> each of the attribute names in the
given list. For example</p><pre><code class="programlisting nix">foo.bar = {
a = 0;
b = nvf.lib.nvim.dag.entryAfter [ &quot;a&quot; ] 1;
}
</code></pre><p>would place <code class="literal">b</code> after <code class="literal">a</code> in the graph.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="ch-types-dag-entryBefore" class="title" style="clear: both">entryBefore </h2> </div> </div></div><div class="blockquote"><blockquote class="blockquote"><p><code class="literal">nvf.lib.nvim.dag.entryBefore (befores: list string) (value: T) : DagEntry&lt;T&gt;</code></p></blockquote></div><p>Indicates that <code class="literal">value</code> must be placed <span class="emphasis"><em>before</em></span> each of the attribute names in
the given list. For example</p><pre><code class="programlisting nix">foo.bar = {
b = nvf.lib.nvim.dag.entryBefore [ &quot;a&quot; ] 1;
a = 0;
}
</code></pre><p>would place <code class="literal">b</code> before <code class="literal">a</code> in the graph.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-types-dag-entryBetween" class="title" style="clear: both">entryBetween </h2> </div> </div></div><div class="blockquote"><blockquote class="blockquote"><p><code class="literal">nvf.lib.nvim.dag.entryBetween (befores: list string) (afters: list string) (value: T) : DagEntry&lt;T&gt;</code></p></blockquote></div><p>Indicates that <code class="literal">value</code> must be placed <span class="emphasis"><em>before</em></span> the attribute names in the first
list and <span class="emphasis"><em>after</em></span> the attribute names in the second list. For example</p><pre><code class="programlisting nix">foo.bar = {
a = 0;
c = nvf.lib.nvim.dag.entryBetween [ &quot;b&quot; ] [ &quot;a&quot; ] 2;
b = 1;
}
</code></pre><p>would place <code class="literal">c</code> before <code class="literal">b</code> and after <code class="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 <code class="literal">tag</code> as argument and the DAG entries will be named
<code class="literal">${tag}-${index}</code>.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-types-dag-entriesAnywhere" class="title" style="clear: both">entriesAnywhere </h2> </div> </div></div><div class="blockquote"><blockquote class="blockquote"><p><code class="literal">nvf.lib.nvim.dag.entriesAnywhere (tag: string) (values: [T]) : Dag&lt;T&gt;</code></p></blockquote></div><p>Creates a DAG with the given values with each entry labeled using the given tag.
For example</p><pre><code class="programlisting nix">foo.bar = nvf.lib.nvim.dag.entriesAnywhere &quot;a&quot; [ 0 1 ];
</code></pre><p>is equivalent to</p><pre><code class="programlisting nix">foo.bar = {
a-0 = 0;
a-1 = nvf.lib.nvim.dag.entryAfter [ &quot;a-0&quot; ] 1;
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-types-dag-entriesAfter" class="title" style="clear: both">entriesAfter </h2> </div> </div></div><div class="blockquote"><blockquote class="blockquote"><p><code class="literal">nvf.lib.nvim.dag.entriesAfter (tag: string) (afters: list string) (values: [T]) : Dag&lt;T&gt;</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 <span class="emphasis"><em>after</em></span> each of the attribute names in
<code class="literal">afters</code>. For example</p><pre><code class="programlisting nix">foo.bar =
{ b = 0; } // nvf.lib.nvim.dag.entriesAfter &quot;a&quot; [ &quot;b&quot; ] [ 1 2 ];
</code></pre><p>is equivalent to</p><pre><code class="programlisting nix">foo.bar = {
b = 0;
a-0 = nvf.lib.nvim.dag.entryAfter [ &quot;b&quot; ] 1;
a-1 = nvf.lib.nvim.dag.entryAfter [ &quot;a-0&quot; ] 2;
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-types-dag-entriesBefore" class="title" style="clear: both">entriesBefore </h2> </div> </div></div><div class="blockquote"><blockquote class="blockquote"><p><code class="literal">nvf.lib.nvim.dag.entriesBefore (tag: string) (befores: list string) (values: [T]) : Dag&lt;T&gt;</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 <span class="emphasis"><em>before</em></span> each of the attribute names in <code class="literal">befores</code>.
For example</p><pre><code class="programlisting nix">foo.bar =
{ b = 0; } // nvf.lib.nvim.dag.entriesBefore &quot;a&quot; [ &quot;b&quot; ] [ 1 2 ];
</code></pre><p>is equivalent to</p><pre><code class="programlisting nix">foo.bar = {
b = 0;
a-0 = 1;
a-1 = nvf.lib.nvim.dag.entryBetween [ &quot;b&quot; ] [ &quot;a-0&quot; ] 2;
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-types-dag-entriesBetween" class="title" style="clear: both">entriesBetween </h2> </div> </div></div><div class="blockquote"><blockquote class="blockquote"><p><code class="literal">nvf.lib.nvim.dag.entriesBetween (tag: string) (befores: list string) (afters: list string) (values: [T]) : Dag&lt;T&gt;</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 <span class="emphasis"><em>before</em></span> each of the attribute names in <code class="literal">befores</code>
and <span class="emphasis"><em>after</em></span> each of the attribute names in <code class="literal">afters</code>. For example</p><pre><code class="programlisting nix">foo.bar =
{ b = 0; c = 3; } // nvf.lib.nvim.dag.entriesBetween &quot;a&quot; [ &quot;b&quot; ] [ &quot;c&quot; ] [ 1 2 ];
</code></pre><p>is equivalent to</p><pre><code class="programlisting nix">foo.bar = {
b = 0;
c = 3;
a-0 = nvf.lib.nvim.dag.entryAfter [ &quot;c&quot; ] 1;
a-1 = nvf.lib.nvim.dag.entryBetween [ &quot;b&quot; ] [ &quot;a-0&quot; ] 2;
}
</code></pre>
</div>
</div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="ch-dag-entries" class="title" >DAG entries in nvf </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#ch-vim-luaconfigrc"><code class="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 dont know what the
entries are called, its hard to do that, so here is a list of the internal
entries in nvf:</p><div class="section"> <div class="titlepage"> <div> <div> <h2 id="ch-vim-luaconfigrc" class="title" style="clear: both"><code class="literal">vim.luaConfigRC</code> (top-level DAG) </h2> </div> </div></div><div class="orderedlist"><ol class="orderedlist compact" type="1"><li class="listitem"><p>(<code class="literal">luaConfigPre</code>) - not a part of the actual DAG, instead, its simply
inserted before the rest of the DAG</p></li><li class="listitem"><p><code class="literal">globalsScript</code> - used to set globals defined in <code class="literal">vim.globals</code></p></li><li class="listitem"><p><code class="literal">basic</code> - used to set basic configuration options</p></li><li class="listitem"><p><code class="literal">optionsScript</code> - used to set options defined in <code class="literal">vim.o</code></p></li><li class="listitem"><p><code class="literal">theme</code> (this is simply placed before <code class="literal">pluginConfigs</code> and <code class="literal">lazyConfigs</code>,
meaning that surrounding entries dont depend on it) - used to set up the
theme, which has to be done before other plugins</p></li><li class="listitem"><p><code class="literal">lazyConfigs</code> - <code class="literal">lz.n</code> and <code class="literal">lzn-auto-require</code> configs. If <code class="literal">vim.lazy.enable</code>
is false, this will contain each plugins config instead.</p></li><li class="listitem"><p><code class="literal">pluginConfigs</code> - the result of the nested <code class="literal">vim.pluginRC</code> (internal option,
see the <a class="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><li class="listitem"><p><code class="literal">extraPluginConfigs</code> - the result of <code class="literal">vim.extraPlugins</code>, which is not a
direct DAG, but is converted to, and resolved as one internally</p></li><li class="listitem"><p><code class="literal">mappings</code> - the result of <code class="literal">vim.maps</code></p></li></ol></div>
</div>
</div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="ch-autocmds-augroups" class="title" >Autocommands and Autogroups </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-vim-augroups">Autogroups (<code class="literal">vim.augroups</code>)</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-vim-autocmds">Autocommands (<code class="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><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-vim-augroups" class="title" style="clear: both">Autogroups (<code class="literal">vim.augroups</code>) </h2> </div> </div></div><p>Autogroups (<code class="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><div class="informaltable"><table class="informaltable" border="1"><colgroup><col align="left" /><col align="left" /><col align="left" /><col align="left" /><col align="left" /></colgroup><thead><tr><th align="left">Option</th><th align="left">Type</th><th align="left">Default</th><th align="left">Description</th><th align="left">Example</th></tr></thead><tbody><tr><td align="left"><code class="literal">enable</code></td><td align="left"><code class="literal">bool</code></td><td align="left"><code class="literal">true</code></td><td align="left">Enables or disables this autogroup definition.</td><td align="left"><code class="literal">true</code></td></tr><tr><td align="left"><code class="literal">name</code></td><td align="left"><code class="literal">str</code></td><td align="left"><span class="emphasis"><em>None</em></span></td><td align="left"><span class="strong"><strong>Required.</strong></span> The unique name for the autogroup.</td><td align="left"><code class="literal">&quot;MyFormatGroup&quot;</code></td></tr><tr><td align="left"><code class="literal">clear</code></td><td align="left"><code class="literal">bool</code></td><td align="left"><code class="literal">true</code></td><td align="left">Clears any existing autocommands within this group before adding new ones defined in <code class="literal">vim.autocmds</code>.</td><td align="left"><code class="literal">true</code></td></tr></tbody></table></div><p><span class="strong"><strong>Example:</strong></span></p><pre><code class="programlisting nix">{
vim.augroups = [
{
name = &quot;MyCustomAuGroup&quot;;
clear = true; # Clear previous autocommands in this group on reload
}
{
name = &quot;Formatting&quot;;
# clear defaults to true
}
];
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-vim-autocmds" class="title" style="clear: both">Autocommands (<code class="literal">vim.autocmds</code>) </h2> </div> </div></div><p>Autocommands (<code class="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><div class="informaltable"><table class="informaltable" border="1"><colgroup><col align="left" /><col align="left" /><col align="left" /><col align="left" /><col align="left" /></colgroup><thead><tr><th align="left">Option</th><th align="left">Type</th><th align="left">Default</th><th align="left">Description</th><th align="left">Example</th></tr></thead><tbody><tr><td align="left"><code class="literal">enable</code></td><td align="left"><code class="literal">bool</code></td><td align="left"><code class="literal">true</code></td><td align="left">Enables or disables this autocommand definition.</td><td align="left"><code class="literal">true</code></td></tr><tr><td align="left"><code class="literal">event</code></td><td align="left"><code class="literal">nullOr (listOf str)</code></td><td align="left"><code class="literal">null</code></td><td align="left"><span class="strong"><strong>Required.</strong></span> List of Neovim events that trigger this autocommand (e.g., <code class="literal">BufWritePre</code>, <code class="literal">FileType</code>).</td><td align="left"><code class="literal">[ &quot;BufWritePre&quot; ]</code></td></tr><tr><td align="left"><code class="literal">pattern</code></td><td align="left"><code class="literal">nullOr (listOf str)</code></td><td align="left"><code class="literal">null</code></td><td align="left">List of file patterns (globs) to match against (e.g., <code class="literal">*.py</code>, <code class="literal">*</code>). If <code class="literal">null</code>, matches all files for the given event.</td><td align="left"><code class="literal">[ &quot;*.lua&quot;, &quot;*.nix&quot; ]</code></td></tr><tr><td align="left"><code class="literal">callback</code></td><td align="left"><code class="literal">nullOr luaInline</code></td><td align="left"><code class="literal">null</code></td><td align="left">A Lua function to execute when the event triggers. Use <code class="literal">lib.nvim.types.luaInline</code> or <code class="literal">lib.options.literalExpression &quot;mkLuaInline &#x27;&#x27;&#x27;...&#x27;&#x27;&#x27;&quot;</code>. <span class="strong"><strong>Cannot be used with <code class="literal">command</code>.</strong></span></td><td align="left"><code class="literal">lib.nvim.types.luaInline &quot;function() print(&#x27;File saved!&#x27;) end&quot;</code></td></tr><tr><td align="left"><code class="literal">command</code></td><td align="left"><code class="literal">nullOr str</code></td><td align="left"><code class="literal">null</code></td><td align="left">A Vimscript command to execute when the event triggers. <span class="strong"><strong>Cannot be used with <code class="literal">callback</code>.</strong></span></td><td align="left"><code class="literal">&quot;echo &#x27;File saved!&#x27;&quot;</code></td></tr><tr><td align="left"><code class="literal">group</code></td><td align="left"><code class="literal">nullOr str</code></td><td align="left"><code class="literal">null</code></td><td align="left">The name of an <code class="literal">augroup</code> (defined in <code class="literal">vim.augroups</code>) to associate this autocommand with.</td><td align="left"><code class="literal">&quot;MyCustomAuGroup&quot;</code></td></tr><tr><td align="left"><code class="literal">desc</code></td><td align="left"><code class="literal">nullOr str</code></td><td align="left"><code class="literal">null</code></td><td align="left">A description for the autocommand (useful for introspection).</td><td align="left"><code class="literal">&quot;Format buffer on save&quot;</code></td></tr><tr><td align="left"><code class="literal">once</code></td><td align="left"><code class="literal">bool</code></td><td align="left"><code class="literal">false</code></td><td align="left">If <code class="literal">true</code>, the autocommand runs only once and then automatically removes itself.</td><td align="left"><code class="literal">false</code></td></tr><tr><td align="left"><code class="literal">nested</code></td><td align="left"><code class="literal">bool</code></td><td align="left"><code class="literal">false</code></td><td align="left">If <code class="literal">true</code>, allows this autocommand to trigger other autocommands.</td><td align="left"><code class="literal">false</code></td></tr></tbody></table></div><div class="warning"><h3 class="title">Warning</h3><p>You cannot define both <code class="literal">callback</code> (for Lua functions) and <code class="literal">command</code> (for
Vimscript) for the same autocommand. Choose one.</p></div><p><span class="strong"><strong>Examples:</strong></span></p><pre><code class="programlisting nix">{ lib, ... }:
{
vim.augroups = [ { name = &quot;UserSetup&quot;; } ];
vim.autocmds = [
# Example 1: Using a Lua callback
{
event = [ &quot;BufWritePost&quot; ];
pattern = [ &quot;*.lua&quot; ];
group = &quot;UserSetup&quot;;
desc = &quot;Notify after saving Lua file&quot;;
callback = lib.nvim.types.luaInline &#x27;&#x27;
function()
vim.notify(&quot;Lua file saved!&quot;, vim.log.levels.INFO)
end
&#x27;&#x27;;
}
# Example 2: Using a Vim command
{
event = [ &quot;FileType&quot; ];
pattern = [ &quot;markdown&quot; ];
group = &quot;UserSetup&quot;;
desc = &quot;Set spellcheck for Markdown&quot;;
command = &quot;setlocal spell&quot;;
}
# Example 3: Autocommand without a specific group
{
event = [ &quot;BufEnter&quot; ];
pattern = [ &quot;*.log&quot; ];
desc = &quot;Disable line numbers in log files&quot;;
command = &quot;setlocal nonumber&quot;;
# No &#x27;group&#x27; specified
}
# Example 4: Using Lua for callback
{
event = [ &quot;BufWinEnter&quot; ];
pattern = [ &quot;*&quot; ];
desc = &quot;Simple greeting on entering a buffer window&quot;;
callback = lib.generators.mkLuaInline &#x27;&#x27;
function(args)
print(&quot;Entered buffer: &quot; .. args.buf)
end
&#x27;&#x27;;
# Run only once per session trigger
once = true;
}
];
}
</code></pre><p>These definitions are automatically translated into the necessary Lua code to
configure <code class="literal">vim.api.nvim_create_augroup</code> and <code class="literal">vim.api.nvim_create_autocmd</code> when
Neovim starts.</p>
</div>
</div>
</div><div class="part"> <div class="titlepage"> <div> <div> <h1 id="ch-helpful-tips" class="title" >Helpful Tips </h1> </div> </div></div><div class="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 <span class="strong"><strong>nvf</strong></span> with pure Lua and using custom plugin sources
in <span class="strong"><strong>nvf</strong></span> in this section. For general configuration tips, please see previous
chapters.</p><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="chapter"> <a href="index.xhtml#sec-debugging-nvf">Debugging nvf</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#sec-offline-documentation">Offline Documentation</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#sec-pure-lua-config">Pure Lua Configuration</a> </span></dt><dt> <span class="chapter"> <a href="index.xhtml#sec-plugin-sources">Adding Plugins From Different Sources</a> </span></dt> </dl></div></div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="sec-debugging-nvf" class="title" >Debugging nvf </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-accessing-config">Accessing <code class="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><span class="strong"><strong>nvf-print-config</strong></span> and <span class="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
<a class="link" href="https://github.com/sharkdp/bat" target="_top">bat pager</a>.</p><pre><code class="programlisting bash">nvf-print-config | bat --language=lua
</code></pre><p>Alternatively, <code class="literal">cat</code> or <code class="literal">less</code> may also be used.</p><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-accessing-config" class="title" style="clear: both">Accessing <code class="literal">neovimConfig</code> </h2> </div> </div></div><p>It is also possible to access the configuration for the wrapped package. The
<span class="emphasis"><em>built</em></span> Neovim package will contain a <code class="literal">neovimConfig</code> attribute in its
<code class="literal">passthru</code>.</p>
</div>
</div><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="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 <a class="link" href="https://notashelf.github.io/nvf/options.html" target="_top">https://notashelf.github.io/nvf/options.html</a>. You may
use the <code class="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><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="sec-pure-lua-config" class="title" >Pure Lua Configuration </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-pure-nvf-runtime">Pure Runtime Directory</a> </span></dt><dt> <span class="section"> <a href="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.
<span class="emphasis"><em>Purely</em></span>, by modifying Neovims runtime directory or <span class="emphasis"><em>impurely</em></span> by placing Lua
configuration in a directory found in <code class="literal">$HOME</code>. For your convenience, this
section will document both methods as they can be used.</p><div class="section"> <div class="titlepage"> <div> <div> <h2 id="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 Neovims runtime path to suit your needs.
One of the ways the new runtime option is to add a configuration <span class="strong"><strong>located
relative to your <code class="literal">flake.nix</code></strong></span>, which must be version controlled in pure flakes
manner.</p><pre><code class="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&#x27;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 <code class="literal">nvim</code> directory, or rather, the <span class="emphasis"><em>store path</em></span> that will be
realised after your flake gets copied to the Nix store, to Neovims runtime
directory. You may now create a <code class="literal">lua/myconfig</code> directory within this nvim
directory, and call it with <a class="xref" href="options.html#opt-vim.luaConfigRC" ><code class="option">vim.luaConfigRC</code></a>.</p><pre><code class="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 */ &#x27;&#x27;
-- Call the Lua module from ./nvim/lua/myconfig
require(&quot;myconfig&quot;)
-- Any additional Lua configuration that you might want *after* your own
-- configuration. For example, a plugin setup call.
require(&#x27;gitsigns&#x27;).setup({})
&#x27;&#x27;;
};
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-impure-absolute-dir" class="title" style="clear: both">Impure Absolute Directory </h2> </div> </div></div><p>As of <a class="link" href="https://github.com/neovim/neovim/pull/22128" target="_top">Neovim 0.9</a>, <code class="varname">$NVIM_APPNAME</code> is a variable expected by Neovim to
decide on the configuration directory. nvf sets this variable as <code class="literal">&quot;nvf&quot;</code>,
meaning <code class="literal">~/.config/nvf</code> will be regarded as <span class="emphasis"><em>the</em></span> configuration directory by
Neovim, similar to how <code class="literal">~/.config/nvim</code> behaves in regular installations. This
allows some degree of Lua configuration, backed by our low-level wrapper
<a class="link" href="https://github.com/Gerg-L/mnw" target="_top">mnw</a>. Creating a <code class="literal">lua/</code> directory located in
<code class="literal">$NVIM_APPNAME</code> (“nvf” by default) and placing your configuration in, e.g.,
<code class="literal">~/.config/nvf/lua/myconfig</code> will allow you to <code class="literal">require</code> it as a part of the Lua
module system through nvfs module system.</p><p>Lets assume your <code class="literal">~/.config/nvf/lua/myconfig/init.lua</code> consists of the
following:</p><pre><code class="programlisting lua">-- init.lua
vim.keymap.set(&quot;n&quot;, &quot; &quot;, &quot;&lt;Nop&gt;&quot;, { silent = true, remap = false })
vim.g.mapleader = &quot; &quot;
</code></pre><p>The following Nix configuration via <a class="xref" href="options.html#opt-vim.luaConfigRC" ><code class="option">vim.luaConfigRC</code></a> will allow loading
this</p><pre><code class="programlisting nix">{
# The attribute name &quot;myconfig-dir&quot; 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 = &#x27;&#x27;
require(&quot;myconfig&quot;)
-- Any additional Lua
&#x27;&#x27;;
}
</code></pre><p>After you load your custom configuration, you may use an <code class="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 <code class="literal">require</code> call in a
specific position (i.e., before or after options you set in nvf) the
<a class="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><div class="chapter"> <div class="titlepage"> <div> <div> <h2 id="sec-plugin-sources" class="title" >Adding Plugins From Different Sources </h2> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#ch-plugins-from-nixpkgs">Nixpkgs &amp; Friends</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#ch-plugins-from-source">Building Your Own Plugins</a> </span></dt> </dl></div><p><span class="strong"><strong>nvf</strong></span> attempts to avoid depending on Nixpkgs for Neovim plugins. For the most
part, this is accomplished by defining each plugins source and building them
from source.</p><p>To define plugin sources, we use <a class="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><div class="section"> <div class="titlepage"> <div> <div> <h2 id="ch-plugins-from-nixpkgs" class="title" style="clear: both">Nixpkgs &amp; Friends </h2> </div> </div></div><p><code class="literal">vim.startPlugins</code> and <code class="literal">vim.optPlugins</code> options take either a <span class="strong"><strong>string</strong></span>, in
which case a plugin from nvfs internal plugins registry will be used, or a
<span class="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 <code class="literal">vim.startPlugins</code> to load it on
startup.</p><pre><code class="programlisting nix">{pkgs, ...}: {
# 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 Neovims runtime path to
be loaded manually. Although for plugins that require manual setup, you are
encouraged to use <a class="link" href="https://notashelf.github.io/nvf/options.html#opt-vim.extraPlugins" target="_top"><code class="literal">vim.extraPlugins</code></a>.</p><pre><code class="programlisting nix">{
vim.extraPlugins = {
aerial = {
package = pkgs.vimPlugins.aerial-nvim;
setup = &quot;require(&#x27;aerial&#x27;).setup {}&quot;;
};
};
}
</code></pre><p>More details on the extraPlugins API is documented in the
<a class="link" href="https://notashelf.github.io/nvf/index.xhtml#ch-custom-plugins" target="_top">custom plugins section</a>.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="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 <a class="link" href="https://github.com/andir/npins" target="_top">npins</a>. You may also use your <span class="emphasis"><em>flake inputs</em></span> as
sources.</p><p>Example using plugin inputs:</p><pre><code class="programlisting nix">{
# In your flake.nix
inputs = {
aerial-nvim = {
url = &quot;github:stevearc/aerial.nvim&quot;
flake = false;
};
};
# Make sure that &#x27;inputs&#x27; is properly propagated into Nvf, for example, through
# specialArgs.
outputs = { ... };
}
</code></pre><p>In the case, you may use the input directly for the plugins source attribute in
<code class="literal">buildVimPlugin</code>.</p><pre><code class="programlisting nix"># Make sure that &#x27;inputs&#x27; is properly propagated! It will be missing otherwise
# and the resulting errors might be too obscure.
{inputs, ...}: let
aerial-from-source = pkgs.vimUtils.buildVimPlugin {
name = &quot;aerial-nvim&quot;;
src = inputs.aerial-nvim;
};
in {
vim.extraPlugins = {
aerial = {
package = aerial-from-source;
setup = &quot;require(&#x27;aerial&#x27;).setup {}&quot;;
};
};
}
</code></pre><p>Alternatively, if you do not want to keep track of the source using flake inputs
or npins, you may call <code class="literal">fetchFromGitHub</code> (or other fetchers) directly. An
example would look like this.</p><pre><code class="programlisting nix">regexplainer = buildVimPlugin {
name = &quot;nvim-regexplainer&quot;;
src = fetchFromGitHub {
owner = &quot;bennypowers&quot;;
repo = &quot;nvim-regexplainer&quot;;
rev = &quot;4250c8f3c1307876384e70eeedde5149249e154f&quot;;
hash = &quot;sha256-15DLbKtOgUPq4DcF71jFYu31faDn52k3P1x47GL3+b0=&quot;;
};
# The &#x27;buildVimPlugin&#x27; imposes some &quot;require checks&quot; on all plugins build from
# source. Failing tests, if they are not relevant, can be disabled using the
# &#x27;nvimSkipModule&#x27; argument to the &#x27;buildVimPlugin&#x27; function.
nvimSkipModule = [
&quot;regexplainer&quot;
&quot;regexplainer.buffers.init&quot;
&quot;regexplainer.buffers.popup&quot;
&quot;regexplainer.buffers.register&quot;
&quot;regexplainer.buffers.shared&quot;
&quot;regexplainer.buffers.split&quot;
&quot;regexplainer.component.descriptions&quot;
&quot;regexplainer.component.init&quot;
&quot;regexplainer.renderers.narrative.init&quot;
&quot;regexplainer.renderers.narrative.narrative&quot;
&quot;regexplainer.renderers.init&quot;
&quot;regexplainer.utils.defer&quot;
&quot;regexplainer.utils.init&quot;
&quot;regexplainer.utils.treesitter&quot;
];
}
</code></pre>
</div>
</div>
</div><div class="chapter"> <div class="titlepage"> <div> <div> <h1 id="ch-hacking" class="title" >Hacking nvf </h1> </div> </div></div><div class="toc"> <p><strong>Table of Contents</strong></p> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-contrib-getting-started">Getting Started</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-guidelines">Guidelines</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-testing-changes">Testing Changes</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-keybinds">Keybinds</a> </span></dt><dt> <span class="section"> <a href="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 nvfs 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 <a class="link" href="https://github.com/notashelf/nvf/issues" target="_top">open issues</a> and if no matching issue exists you may open a
<a class="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><div class="section"> <div class="titlepage"> <div> <div> <h1 id="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 GitHubs
<a class="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 <span class="strong"><strong>nvf</strong></span>, you should
create a separate branch based on the most recent <code class="literal">main</code> branch. Give your
branch a reasonably descriptive name (e.g. <code class="literal">feature/debugger</code> or
<code class="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
<a class="link" href="index.xhtml#sec-guidelines" title="Guidelines" >Contributing Guidelines</a>, push the branch to GitHub and
<a class="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 <span class="strong"><strong>nvf</strong></span> repository will guide
you through the rest of the process, and well gently nudge you in the correct
direction if there are any mistakes.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h1 id="sec-guidelines" class="title" style="clear: both">Guidelines </h1> </div> </div></div><div class="toc"> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-guidelines-documentation">Adding Documentation</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-guidelines-formatting">Formatting Code</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-guidelines-commit-message-style">Formatting Commits</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-guidelines-commit-style">Commit Style</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-guidelines-ex-commit-message">Example Commit</a> </span></dt><dt> <span class="section"> <a href="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
<a class="link" href="https://github.com/NotAShelf/nvf/discussions" target="_top">discussions tab</a> ideally (but not
necessarily) before you start developing.</p><div class="section"> <div class="titlepage"> <div> <div> <h2 id="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
<a class="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 <span class="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 <span class="strong"><strong>nvf</strong></span> Git repository:</p><pre><code class="programlisting console">$ nix build .#docs-html
$ xdg-open $PWD/result/share/doc/nvf/index.html
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-guidelines-formatting" class="title" style="clear: both">Formatting Code </h2> </div> </div></div><p>Make sure your code is formatted as described in
<a class="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><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-guidelines-commit-message-style" class="title" style="clear: both">Formatting Commits </h2> </div> </div></div><p>Similar to <a class="link" href="index.xhtml#sec-guidelines-code-style" title="Code Style" >code style guidelines</a> we encourage a
consistent commit message format as described in
<a class="link" href="index.xhtml#sec-guidelines-commit-style" title="Commit Style" >commit style guidelines</a>.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="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
<a class="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-managers own documentation</p><pre><code class="programlisting"> {component}: {description}
{long description}
</code></pre><p>where <code class="literal">{component}</code> refers to the code component (or module) your change
affects, <code class="literal">{description}</code> is a very brief description of your change, and
<code class="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
<code class="literal">{component}</code> part is optional. See
<a class="link" href="index.xhtml#sec-guidelines-ex-commit-message" title="Example Commit" >example commit message</a> for a commit message
that fulfills these requirements.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-guidelines-ex-commit-message" class="title" style="clear: both">Example Commit </h2> </div> </div></div><p>The commit
<a class="link" href="https://github.com/nix-community/home-manager/commit/69f8e47e9e74c8d3d060ca22e18246b7f7d988ef" target="_top">69f8e47e9e74c8d3d060ca22e18246b7f7d988ef</a>
in home-manager contains the following commit message.</p><pre><code class="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 <span class="strong"><strong>nvf</strong></span>, you would include the scope of
the commit followed by the description:</p><pre><code class="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 <code class="literal">modules/foo.nix</code>, we use the fixed
commit format <code class="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 <code class="literal">modules/languages/java.nix</code> you are recommended
to contain the parent as well - for example <code class="literal">languages/java: some major change</code>.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-guidelines-code-style" class="title" style="clear: both">Code Style </h2> </div> </div></div><div class="section"> <div class="titlepage"> <div> <div> <h3 id="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><div class="section"> <div class="titlepage"> <div> <div> <h3 id="sec-code-style-nix" class="title" >Nix </h3> </div> </div></div><p><span class="strong"><strong>nvf</strong></span> is formatted by the <a class="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 <code class="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 users 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><code class="programlisting nix"># parent modules should always be unfolded
# which means module = { value = ... } instead of module.value = { ... }
module = {
value = mkEnableOption &quot;some description&quot; // { 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 &lt; default &lt; description.
# Example, if present, would be between default and description
someOtherValue = mkOption {
type = lib.types.bool;
default = true;
description = &quot;Some other description&quot;;
};
};
}
</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 <span class="strong"><strong>do not</strong></span> want.</p><pre><code class="programlisting nix">module = {
key = mkEnableOption &quot;some description&quot; // {
default = true; # we want this to be inline
}; # ...
}
</code></pre><p>For lists, it is mostly up to your own discretion how you want to format them,
but please try to unfold lists if they contain multiple items and especially if
they are to include comments.</p><pre><code class="programlisting nix"># this is ok
acceptableList = [
item1 # comment
item2
item3 # some other comment
item4
];
# this is not ok
listToBeAvoided = [item1 item2 /* comment */ item3 item4];
# this is ok
acceptableList = [item1 item2];
# 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><div class="section"> <div class="titlepage"> <div> <div> <h1 id="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 <code class="literal">configuration.nix</code> (located in the root of
this project) inside <code class="literal">neovimConfiguration</code>. Enable it, and then run the maximal
configuration with <code class="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 <code class="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
<code class="literal">configuration.nix</code>, and then run it with <code class="literal">nix run .#maximal -Lv</code>. Same
procedure as adding a new module will apply here.</p>
</div><div class="section"> <div class="titlepage"> <div> <div> <h1 id="sec-keybinds" class="title" style="clear: both">Keybinds </h1> </div> </div></div><div class="toc"> <dl class="toc"> <dt> <span class="section"> <a href="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
<a class="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><div class="section"> <div class="titlepage"> <div> <div> <h2 id="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 <code class="literal">vim.keymaps</code>.</p><p>An example, simple keybinding, can look like this:</p><pre><code class="programlisting nix">{
vim.keymaps = [
{
key = &quot;&lt;leader&gt;wq&quot;;
mode = [&quot;n&quot;];
action = &quot;:wq&lt;CR&gt;&quot;;
silent = true;
desc = &quot;Save file and quit&quot;;
}
];
}
</code></pre><p>There are many settings available in the options. Please refer to the
<a class="link" href="https://notashelf.github.io/nvf/options.html#opt-vim.keymaps" target="_top">documentation</a> to
see a list of them.</p><p><span class="strong"><strong>nvf</strong></span> provides a helper function, so that you dont have to write the mapping
attribute sets every time:</p><div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc;"><li class="listitem"><p><code class="literal">mkKeymap</code>, which mimics neovims <code class="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><code class="programlisting nix"># plugindefinition.nix
{lib, ...}: let
inherit (lib.options) mkEnableOption;
inherit (lib.nvim.binds) mkMappingOption;
in {
options.vim.plugin = {
enable = mkEnableOption &quot;Enable plugin&quot;;
# Mappings should always be inside an attrset called mappings
mappings = {
workspaceDiagnostics = mkMappingOption &quot;Workspace diagnostics [trouble]&quot; &quot;&lt;leader&gt;lwd&quot;;
documentDiagnostics = mkMappingOption &quot;Document diagnostics [trouble]&quot; &quot;&lt;leader&gt;ld&quot;;
lspReferences = mkMappingOption &quot;LSP References [trouble]&quot; &quot;&lt;leader&gt;lr&quot;;
quickfix = mkMappingOption &quot;QuickFix [trouble]&quot; &quot;&lt;leader&gt;xq&quot;;
locList = mkMappingOption &quot;LOCList [trouble]&quot; &quot;&lt;leader&gt;xl&quot;;
symbols = mkMappingOption &quot;Symbols [trouble]&quot; &quot;&lt;leader&gt;xs&quot;;
};
}
</code></pre><pre><code class="programlisting nix"># config.nix
{
config,
lib,
options,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.nvim.binds) mkKeymap;
cfg = config.vim.plugin;
keys = cfg.mappings;
inherit (options.vim.lsp.trouble) mappings;
in {
config = mkIf cfg.enable {
vim.keymaps = [
(mkKeymap &quot;n&quot; keys.workspaceDiagnostics &quot;&lt;cmd&gt;Trouble toggle diagnostics&lt;CR&gt;&quot; {desc = mappings.workspaceDiagnostics.description;})
(mkKeymap &quot;n&quot; keys.documentDiagnostics &quot;&lt;cmd&gt;Trouble toggle diagnostics filter.buf=0&lt;CR&gt;&quot; {desc = mappings.documentDiagnostics.description;})
(mkKeymap &quot;n&quot; keys.lspReferences &quot;&lt;cmd&gt;Trouble toggle lsp_references&lt;CR&gt;&quot; {desc = mappings.lspReferences.description;})
(mkKeymap &quot;n&quot; keys.quickfix &quot;&lt;cmd&gt;Trouble toggle quickfix&lt;CR&gt;&quot; {desc = mappings.quickfix.description;})
(mkKeymap &quot;n&quot; keys.locList &quot;&lt;cmd&gt;Trouble toggle loclist&lt;CR&gt;&quot; {desc = mappings.locList.description;})
(mkKeymap &quot;n&quot; keys.symbols &quot;&lt;cmd&gt;Trouble toggle symbols&lt;CR&gt;&quot; {desc = mappings.symbols.description;})
];
};
}
</code></pre><div class="note"><h3 class="title">Note</h3><p>If you have come across a plugin that has an API that doesnt seem to easily
allow custom keybindings, dont be scared to implement a draft PR. Well help
you get it done.</p></div>
</div>
</div><div class="section"> <div class="titlepage"> <div> <div> <h1 id="sec-additional-plugins" class="title" style="clear: both">Adding Plugins </h1> </div> </div></div><div class="toc"> <dl class="toc"> <dt> <span class="section"> <a href="index.xhtml#sec-npins-for-plugins">With npins</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-pkgs-for-plugins">Packaging Complex Plugins</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-modular-setup-options">Modular setup options</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-details-of-toluaobject">Details of toLuaObject</a> </span></dt><dt> <span class="section"> <a href="index.xhtml#sec-lazy-plugins">Lazy plugins</a> </span></dt> </dl></div><p>There are two methods for adding new Neovim plugins to <span class="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><div class="section"> <div class="titlepage"> <div> <div> <h2 id="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 <span class="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 <code class="literal">npins</code>. For
example:</p><pre><code class="programlisting bash">nix-shell -p npins # or nix shell nixpkgs#npins if using flakes
</code></pre><p>Then run:</p><pre><code class="programlisting bash">npins add --name &lt;plugin name&gt; github &lt;owner&gt; &lt;repo&gt; -b &lt;branch&gt;
</code></pre><div class="note"><h3 class="title">Note</h3><p>Be sure to replace any non-alphanumeric characters with <code class="literal">-</code> for <code class="literal">--name</code>. For
example</p><pre><code class="programlisting bash">npins add --name lazydev-nvim github folke lazydev.nvim -b main
</code></pre></div><p>Once the <code class="literal">npins</code> command is done, you can start referencing the plugin as a
<span class="strong"><strong>string</strong></span>.</p><pre><code class="programlisting nix">{
config.vim.startPlugins = [&quot;lazydev-nvim&quot;];
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="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 <a class="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 <code class="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 <code class="literal">buildRustPackage</code> to build the library from the repository root, and
copy everything in the <code class="literal">postInstall</code> phase.</p><pre><code class="programlisting nix">postInstall = &#x27;&#x27;
cp -r {lua,plugin} &quot;$out&quot;
mkdir -p &quot;$out/doc&quot;
cp &#x27;doc/&#x27;*&#x27;.txt&#x27; &quot;$out/doc/&quot;
mkdir -p &quot;$out/target&quot;
mv &quot;$out/lib&quot; &quot;$out/target/release&quot;
&#x27;&#x27;;
</code></pre><p>In a similar fashion, you may utilize <code class="literal">stdenv.mkDerivation</code> and other Nixpkgs
builders to build your library from source, and copy the relevant files and Lua
plugin files in the <code class="literal">postInstall</code> phase. Do note, however, that you still need
to fetch the plugin sources somehow. npins is, once again, the recommended
option to fetch the plugin sources. Refer to the previous section on how to use
npins to add a new plugin.</p><p>Plugins built from source must go into the <code class="literal">flake/pkgs/by-name</code> overlay. It will
automatically create flake outputs for individual packages. Lastly, you must add
your package to the plugin builder (<code class="literal">pluginBuilders</code>) function manually in
<code class="literal">modules/wrapper/build/config.nix</code>. Once done, you may refer to your plugin as a
<span class="strong"><strong>string</strong></span>.</p><pre><code class="programlisting nix">{
config.vim.startPlugins = [&quot;blink-cmp&quot;];
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="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 <code class="literal">require(&#x27;plugin&#x27;).setup({...})</code>.</p><p>We use a special function that lets you easily add support for such setup
options in a modular way: <code class="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><code class="programlisting nix"># in modules/.../your-plugin/your-plugin.nix
{lib, ...}:
let
inherit (lib.types) bool int;
inherit (lib.nvim.types) mkPluginSetupOption;
in {
options.vim.your-plugin = {
setupOpts = mkPluginSetupOption &quot;plugin name&quot; {
enable_feature_a = mkOption {
type = bool;
default = false;
# ...
};
number_option = mkOption {
type = int;
default = 3;
# ...
};
};
};
}
</code></pre><pre><code class="programlisting nix"># in modules/.../your-plugin/config.nix
{lib, config, ...}:
let
cfg = config.vim.your-plugin;
in {
vim.luaConfigRC = lib.nvim.dag.entryAnywhere &#x27;&#x27;
require(&#x27;plugin-name&#x27;).setup(${lib.nvim.lua.toLuaObject cfg.setupOpts})
&#x27;&#x27;;
}
</code></pre><p>This above config will result in this Lua script:</p><pre><code class="programlisting lua">require(&#x27;plugin-name&#x27;).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><code class="programlisting nix"># in user&#x27;s config
{
vim.your-plugin.setupOpts = {
enable_feature_a = true;
number_option = 4;
another_field = &quot;hello&quot;;
size = { # nested fields work as well
top = 10;
};
};
}
</code></pre>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-details-of-toluaobject" class="title" style="clear: both">Details of toLuaObject </h2> </div> </div></div><p>As youve seen above, <code class="literal">toLuaObject</code> is used to convert our nix attrSet
<code class="literal">cfg.setupOpts</code>, into a lua table. Here are some rules of the conversion:</p><div class="orderedlist"><ol class="orderedlist " type="1"><li class="listitem"><p>Nix <code class="literal">null</code> converts to lua <code class="literal">nil</code></p></li><li class="listitem"><p>Number and strings convert to their lua counterparts</p></li><li class="listitem"><p>Nix attribute sets (<code class="literal">{}</code>) and lists (<code class="literal">[]</code>) convert into Lua dictionaries and
tables respectively. Here is an example of Nix -&gt; Lua conversion.</p><div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc;"><li class="listitem"><p><code class="literal">{foo = &quot;bar&quot;}</code> -&gt; <code class="literal">{[&quot;foo&quot;] = &quot;bar&quot;}</code></p></li><li class="listitem"><p><code class="literal">[&quot;foo&quot; &quot;bar&quot;]</code> -&gt; <code class="literal">{&quot;foo&quot;, &quot;bar&quot;}</code></p></li></ul></div></li><li class="listitem"><p>You can write raw Lua code using <code class="literal">lib.generators.mkLuaInline</code>. This function
is part of nixpkgs, and is accessible without relying on <span class="strong"><strong>nvf</strong></span>s extended
library.</p><div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc;"><li class="listitem"><p><code class="literal">mkLuaInline &quot;function add(a, b) return a + b end&quot;</code> will yield the
following result:</p></li></ul></div><pre><code class="programlisting nix">{
_type = &quot;lua-inline&quot;;
expr = &quot;function add(a, b) return a + b end&quot;;
}
</code></pre><p>The above expression will be interpreted as a Lua expression in the final
config. Without the <code class="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><code class="programlisting nix">{
vim.your-plugin.setupOpts = {
on_init = lib.generators.mkLuaInline &#x27;&#x27;
function()
print(&#x27;we can write lua!&#x27;)
end
&#x27;&#x27;;
};
}
</code></pre></li></ol></div>
</div><div class="section"> <div class="titlepage"> <div> <div> <h2 id="sec-lazy-plugins" class="title" style="clear: both">Lazy plugins </h2> </div> </div></div><p>If the plugin can be lazy-loaded, <code class="literal">vim.lazy.plugins</code> should be used to add it.
Lazy plugins are managed by <code class="literal">lz.n</code>.</p><pre><code class="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 = &quot;your-plugin&quot;;
# ıf your plugin uses the `require(&#x27;your-plugin&#x27;).setup{...}` pattern
setupModule = &quot;your-plugin&quot;;
inherit (cfg) setupOpts;
# Events that trigger this plugin to be loaded
event = [&quot;DirChanged&quot;];
cmd = [&quot;YourPluginCommand&quot;];
# Plugin Keymaps
keys = [
# We&#x27;ll cover this in detail in the &#x27;keybinds&#x27; section
{
key = &quot;&lt;leader&gt;d&quot;;
mode = &quot;n&quot;;
action = &quot;:YourPluginCommand&quot;;
}
];
};
}
</code></pre><p>This results in the following lua code:</p><pre><code class="programlisting lua">require(&#x27;lz.n&#x27;).load({
{
&quot;name-of-your-plugin&quot;,
after = function()
require(&#x27;your-plugin&#x27;).setup({
--[[ your setupOpts ]]--
})
end,
event = {&quot;DirChanged&quot;},
cmd = {&quot;YourPluginCommand&quot;},
keys = {
{&quot;&lt;leader&gt;d&quot;, &quot;:YourPluginCommand&quot;, mode = {&quot;n&quot;}},
},
}
})
</code></pre><p>A full list of options can be found in the <a class="link" href="https://notashelf.github.io/nvf/options.html#opt-vim.lazy.plugins" target="_top"><code class="literal">vim.lazy.plugins</code> spec</a> on the
rendered manual.</p>
</div>
</div>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left">&nbsp;</td>
<td width="20%" align="center">&nbsp;</td>
<td width="40%" align="right">&nbsp;<a accesskey="n" href="quirks.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">&nbsp;</td>
<td width="20%" align="center">&nbsp;</td>
<td width="40%" align="right" valign="top">&nbsp;Appendix A. Known Issues and Quirks</td>
</tr>
</table>
</div>
</body>
</html>