nvf/docs/manual/hacking/additional-plugins.md
Ching Pei Yang 21fcace3ed
treewide: implement lazy loading via lz.n for selected plugins (#407)
* flake: add lz.n and lzn-auto-require

* lazy: init module

* lzn-auto-require: add init lua code

* wrapper: fix opt plugin format

* lib.binds: add lz.n variant of bind functions

* telescope: lazy load

* nvim-tree: lazy load

* dapui: lazy load

* trouble: lazy load

* toggleterm: lazy load

* cheatsheet: lazy load

* diffview: lazy load

* icon-picker: lazy load

* leap: lazy load

* fidget: lazy load

* docs: add section on lazy plugins

* lazy: support lazy.enable=false

* comment-nvim: lazy load

* surround-nvim: lazy load

* neo-tree: lazy load

* fixup! lazy: init module

* dap: appease the nix gods (fix statix lint)

* flake.lock: fix merge mistake

* doc: update release note

* fixup! doc: update release note

* neo-tree: fix duplicate neo-tree install

* lazy: use attrsOf for lazy.plugins

* treewide: update lazy.plugins syntax

* docs: update lazy.plugins syntax

* lazy: cleanup

* Update docs/manual/hacking/additional-plugins.md

Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com>

* formatting nitpick

Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com>

* typo tee hee :3

Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com>

* typo tee hee :4

Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com>

* flake: update lz.n

* lazy: update lz.n plugin spec

* lazy: allow lines in place of str for lua code

* copilot: lazy load

* cmp: lazy load

this moves cmp itself to lazy.plugins but other plugins that call cmp
are not yet lazy so cmp is technically not yet lazy

* luasnip: lazy load

* flake: add rtp.nvim

* cmp: actually lazy load source

* fixup! cmp: actually lazy load source

* format

* docs: fix broken link

* cmp-nvim-lsp: lazy load

* lazy: allow key mode of str type

* cmp: install sourcess via cmp.sourcePlugins

* Update docs/manual/hacking/additional-plugins.md

Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com>

* lazy: refactor common var

* nvim-dap-ui: add setupOpts

* refactor: re-order plugin and lz.n configs

lazy: make lzn-auto-require togglable

* docs: update dag-entries

* trouble: remove redundant import

* lazy: remove unused module arg

* toggleterm: make lazygit keybind optional

* toggleterm: use toLuaObject for clarity

* surround: rework keymap config

* remove stale FIXME

* lsp: use cmp_nvim_lsp capabilities

* cmp: deduplicate attr key

* theme: ensure themes load before lazy plugins

* doc: update description of `theme` dag entry

* lsp: avoid loading cmp on startup

* doc: update configuration docs on custom plugins

* cmp: skip trigger_load if lazy disabled

* treesitter: remove redundant code

* lsp: mark hack as HACK

* comment: remove redundant plugin

* Squash merge v0.7 into feature/lzn

---------

Co-authored-by: raf <raf@notashelf.dev>
Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com>
2024-11-04 16:50:50 +01:00

185 lines
4.1 KiB
Markdown

# Adding Plugins {#sec-additional-plugins}
To add a new Neovim plugin, first add the source url in the inputs section of `flake.nix`
with the prefix `plugin-`
```nix
{
inputs = {
# ...
plugin-neodev-nvim = {
url = "github:folke/neodev.nvim";
flake = false;
};
# ...
};
}
```
The addition of the `plugin-` prefix will allow **nvf** to autodiscover the
input from the flake inputs automatically, allowing you to refer to it in areas
that require a very specific plugin type as defined in `lib/types/plugins.nix`
You can now reference this plugin using its string name, the plugin will be
built with the name and source URL from the flake input, allowing you to
refer to it as a **string**.
```nix
config.vim.startPlugins = ["neodev-nvim"];
```
## Modular setup options {#sec-modular-setup-options}
Most plugins is initialized with a call to `require('plugin').setup({...})`.
We use a special function that lets you easily add support for such setup options in a modular way:
`mkPluginSetupOption`.
Once you have added the source of the plugin as shown above, you can define the setup options like
this:
```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 "plugin name" {
enable_feature_a = mkOption {
type = bool;
default = false;
# ...
};
number_option = mkOption {
type = int;
default = 3;
# ...
};
};
};
}
```
```nix
# in modules/.../your-plugin/config.nix
{lib, config, ...}:
let
cfg = config.vim.your-plugin;
in {
vim.luaConfigRC = lib.nvim.dag.entryAnywhere ''
require('plugin-name').setup(${lib.nvim.lua.toLuaObject cfg.setupOpts})
'';
}
```
This above config will result in this lua script:
```lua
require('plugin-name').setup({
enable_feature_a = false,
number_option = 3,
})
```
Now users can set any of the pre-defined option field, and can also add their own fields!
```nix
# in user's config
{
vim.your-plugin.setupOpts = {
enable_feature_a = true;
number_option = 4;
another_field = "hello";
size = { # nested fields work as well
top = 10;
};
};
}
```
## Details of toLuaObject {#sec-details-of-toluaobject}
As you've seen above, `toLuaObject` is used to convert our nix attrSet
`cfg.setupOpts`, into a lua table. Here are some rules of the conversion:
1. nix `null` converts to lua `nil`
2. number and strings convert to their lua counterparts
3. nix attrSet/list convert into lua tables
4. you can write raw lua code using `lib.generators.mkLuaInline`. This
function is part of nixpkgs.
Example:
```nix
vim.your-plugin.setupOpts = {
on_init = lib.generators.mkLuaInline ''
function()
print('we can write lua!')
end
'';
}
```
## Lazy plugins {#sec-lazy-plugins}
If the plugin can be lazy-loaded, `vim.lazy.plugins` should be used to add it. Lazy
plugins are managed by `lz.n`.
```nix
# in modules/.../your-plugin/config.nix
{lib, config, ...}:
let
cfg = config.vim.your-plugin;
in {
vim.lazy.plugins.your-plugin = {
# instead of vim.startPlugins, use this:
package = "your-plugin";
# if your plugin uses the `require('your-plugin').setup{...}` pattern
setupModule = "your-plugin";
inherit (cfg) setupOpts;
# events that trigger this plugin to be loaded
event = ["DirChanged"];
cmd = ["YourPluginCommand"];
# keymaps
keys = [
# we'll cover this in detail in the keymaps section
{
key = "<leader>d";
mode = "n";
action = ":YourPluginCommand";
}
];
};
;
}
```
This results in the following lua code:
```lua
require('lz.n').load({
{
"name-of-your-plugin",
after = function()
require('your-plugin').setup({--[[ your setupOpts ]]})
end,
event = {"DirChanged"},
cmd = {"YourPluginCommand"},
keys = {
{"<leader>d", ":YourPluginCommand", mode = {"n"}},
},
}
})
```
A full list of options can be found
[here](https://notashelf.github.io/nvf/options.html#opt-vim.lazy.plugins