Skip to content

Commit

Permalink
plugins/lazy.nvim: make pluginType freeform
Browse files Browse the repository at this point in the history
  • Loading branch information
my7h3le committed Sep 1, 2024
1 parent 78abafe commit 2ca79f3
Show file tree
Hide file tree
Showing 2 changed files with 189 additions and 161 deletions.
342 changes: 181 additions & 161 deletions plugins/pluginmanagers/lazy.nix
Original file line number Diff line number Diff line change
Expand Up @@ -36,182 +36,202 @@ let
processedPlugins = builtins.concatLists (builtins.map processPlugin lazyPlugins);
lazyPath = pkgs.linkFarm "lazy-plugins" processedPlugins;
in
{
options = {
plugins.lazy = {
enable = mkEnableOption "lazy.nvim";

plugins =
with types;
let
pluginType = either package (submodule {
options = {
dir = helpers.mkNullOrOption str "A directory pointing to a local plugin";

pkg = mkOption {
type = package;
description = "Vim plugin to install";
};

name = helpers.mkNullOrOption str "Name of the plugin to install";

dev = helpers.defaultNullOpts.mkBool false ''
When true, a local plugin directory will be used instead.
See config.dev
'';

lazy = helpers.defaultNullOpts.mkBool true ''
When true, the plugin will only be loaded when needed.
Lazy-loaded plugins are automatically loaded when their Lua modules are required,
or when one of the lazy-loading handlers triggers
'';

enabled = helpers.defaultNullOpts.mkStrLuaFnOr types.bool "`true`" ''
When false then this plugin will not be included in the spec. (accepts fun():boolean)
'';

cond = helpers.defaultNullOpts.mkStrLuaFnOr types.bool "`true`" ''
When false, or if the function returns false,
then this plugin will not be loaded. Useful to disable some plugins in vscode,
or firenvim for example. (accepts fun(LazyPlugin):boolean)
'';

dependencies = helpers.mkNullOrOption (helpers.nixvimTypes.eitherRecursive str listOfPlugins) "Plugin dependencies";

init = helpers.mkNullOrLuaFn "init functions are always executed during startup";

config = helpers.mkNullOrStrLuaFnOr (types.enum [ true ]) ''
config is executed when the plugin loads.
The default implementation will automatically run require(MAIN).setup(opts).
Lazy uses several heuristics to determine the plugin's MAIN module automatically based on the plugin's name.
See also opts. To use the default implementation without opts set config to true.
'';

main = helpers.mkNullOrOption str ''
You can specify the main module to use for config() and opts(),
in case it can not be determined automatically. See config()
'';

submodules = helpers.defaultNullOpts.mkBool true ''
When false, git submodules will not be fetched.
Defaults to true
'';

event =
with helpers.nixvimTypes;
helpers.mkNullOrOption (maybeRaw (either str (listOf str))) "Lazy-load on event. Events can be specified as BufEnter or with a pattern like BufEnter *.lua";
nixvim.neovim-plugin.mkNeovimPlugin config {
name = "lazy";
maintainers = [ maintainers.MattSturgeon ];
defaultPackage = pkgs.vimPlugins.lazy-nvim;

cmd =
with helpers.nixvimTypes;
helpers.mkNullOrOption (maybeRaw (either str (listOf str))) "Lazy-load on command";
callSetup = false; # Does not use setup

ft =
with helpers.nixvimTypes;
helpers.mkNullOrOption (maybeRaw (either str (listOf str))) "Lazy-load on filetype";

keys =
with helpers.nixvimTypes;
helpers.mkNullOrOption (maybeRaw (either str (listOf str))) "Lazy-load on key mapping";

module = helpers.mkNullOrOption (enum [ false ]) ''
Do not automatically load this Lua module when it's required somewhere
'';
settingsOptions = {
dev = helpers.defaultNullOpts.mkAttrsOf types.anything { } ''
Options provided to `require("lazy").setup.dev`.
'';
};

priority = helpers.mkNullOrOption number ''
Only useful for start plugins (lazy=false) to force loading certain plugins first.
Default priority is 50. It's recommended to set this to a high number for colorschemes.
'';
extraOptions =
let
lazyPluginType =
with types;
either package (submodule {
freeformType = types.attrsOf types.anything;
options = {
dir = helpers.mkNullOrOption str "A directory pointing to a local plugin";

pkg = mkOption {
type = package;
description = "Vim plugin to install";
};

optional = helpers.defaultNullOpts.mkBool false ''
When a spec is tagged optional, it will only be included in the final spec,
when the same plugin has been specified at least once somewhere else without optional.
This is mainly useful for Neovim distros, to allow setting options on plugins that may/may not be part
of the user's plugins
name = helpers.mkNullOrOption str "Name of the plugin to install";

dev = helpers.defaultNullOpts.mkBool false ''
When true, a local plugin directory will be used instead.
See config.dev
'';

lazy = helpers.defaultNullOpts.mkBool true ''
When true, the plugin will only be loaded when needed.
Lazy-loaded plugins are automatically loaded when their Lua modules are required,
or when one of the lazy-loading handlers triggers
'';

enabled = helpers.defaultNullOpts.mkStrLuaFnOr types.bool "`true`" ''
When false then this plugin will not be included in the spec. (accepts fun():boolean)
'';

cond = helpers.defaultNullOpts.mkStrLuaFnOr types.bool "`true`" ''
When false, or if the function returns false,
then this plugin will not be loaded. Useful to disable some plugins in vscode,
or firenvim for example. (accepts fun(LazyPlugin):boolean)
'';

dependencies = helpers.mkNullOrOption (helpers.nixvimTypes.eitherRecursive str listOfPlugins) "Plugin dependencies";

init = helpers.mkNullOrLuaFn "init functions are always executed during startup";

config = helpers.mkNullOrStrLuaFnOr (types.enum [ true ]) ''
config is executed when the plugin loads.
The default implementation will automatically run require(MAIN).setup(opts).
Lazy uses several heuristics to determine the plugin's MAIN module automatically based on the plugin's name.
See also opts. To use the default implementation without opts set config to true.
'';

main = helpers.mkNullOrOption str ''
You can specify the main module to use for config() and opts(),
in case it can not be determined automatically. See config()
'';

submodules = helpers.defaultNullOpts.mkBool true ''
When false, git submodules will not be fetched.
Defaults to true
'';

event =
with helpers.nixvimTypes;
helpers.mkNullOrOption (maybeRaw (either str (listOf str))) "Lazy-load on event. Events can be specified as BufEnter or with a pattern like BufEnter *.lua";

cmd =
with helpers.nixvimTypes;
helpers.mkNullOrOption (maybeRaw (either str (listOf str))) "Lazy-load on command";

ft =
with helpers.nixvimTypes;
helpers.mkNullOrOption (maybeRaw (either str (listOf str))) "Lazy-load on filetype";

keys =
with helpers.nixvimTypes;
helpers.mkNullOrOption (maybeRaw (either str (listOf str))) "Lazy-load on key mapping";

module = helpers.mkNullOrOption (enum [ false ]) ''
Do not automatically load this Lua module when it's required somewhere
'';

priority = helpers.mkNullOrOption number ''
Only useful for start plugins (lazy=false) to force loading certain plugins first.
Default priority is 50. It's recommended to set this to a high number for colorschemes.
'';

optional = helpers.defaultNullOpts.mkBool false ''
When a spec is tagged optional, it will only be included in the final spec,
when the same plugin has been specified at least once somewhere else without optional.
This is mainly useful for Neovim distros, to allow setting options on plugins that may/may not be part
of the user's plugins
'';

opts =
with helpers.nixvimTypes;
helpers.mkNullOrOption (maybeRaw (attrsOf anything)) ''
opts should be a table (will be merged with parent specs),
return a table (replaces parent specs) or should change a table.
The table will be passed to the Plugin.config() function.
Setting this value will imply Plugin.config()
'';
};
});

opts =
with helpers.nixvimTypes;
helpers.mkNullOrOption (maybeRaw (attrsOf anything)) ''
opts should be a table (will be merged with parent specs),
return a table (replaces parent specs) or should change a table.
The table will be passed to the Plugin.config() function.
Setting this value will imply Plugin.config()
'';
};
});
listOfPlugins = types.listOf lazyPluginType;
in
{
plugins = mkOption {
type = listOfPlugins;
default = [ ];
description = "List of plugins";
};
};

listOfPlugins = types.listOf pluginType;
in
mkOption {
type = listOfPlugins;
default = [ ];
description = "List of plugins";
extraConfig =
cfg:
let
setupOptions =
cfg.settings
// optionalAttrs (cfg.settings.dev == null) {
dev = {
path = "${lazyPath}";
pattern = [ "." ];
fallback = false;
};
};
};
};

config = mkIf cfg.enable {
extraPlugins = [ pkgs.vimPlugins.lazy-nvim ];
extraPackages = [ pkgs.git ];

extraConfigLua =
let
pluginToLua =
plugin:
let
keyExists = keyToCheck: attrSet: lib.elem keyToCheck (lib.attrNames attrSet);
in
if isDerivation plugin then
{ dir = "${lazyPath}/${lib.getName plugin}"; }
else
{
"__unkeyed" = plugin.name;

inherit (plugin)
cmd
cond
config
dev
enabled
event
ft
init
keys
lazy
main
module
name
optional
opts
priority
submodules
;

dependencies = helpers.ifNonNull' plugin.dependencies (
if isList plugin.dependencies then (pluginListToLua plugin.dependencies) else plugin.dependencies
);

dir =
if plugin ? dir && plugin.dir != null then plugin.dir else "${lazyPath}/${lib.getName plugin.pkg}";
};
pluginToLua =
plugin:
let
keyExists = keyToCheck: attrSet: lib.elem keyToCheck (lib.attrNames attrSet);
converted =
if isDerivation plugin then
{ dir = "${lazyPath}/${lib.getName plugin}"; }
else
let
handledPluginOptions = {
"__unkeyed" = plugin.name;

inherit (plugin)
cmd
cond
config
dev
enabled
event
ft
init
keys
lazy
main
module
name
optional
opts
priority
submodules
;

dependencies = helpers.ifNonNull' plugin.dependencies (
if isList plugin.dependencies then (pluginListToLua plugin.dependencies) else plugin.dependencies
);

dir =
if plugin ? dir && plugin.dir != null then plugin.dir else "${lazyPath}/${lib.getName plugin.pkg}";
};
freeformPluginOptions = lib.removeAttrs plugin ((lib.attrNames handledPluginOptions) ++ [ "pkg" ]);
combinedPluginOptions = freeformPluginOptions // handledPluginOptions;
in
combinedPluginOptions;
in
converted;

pluginListToLua = map pluginToLua;
pluginListToLua = map pluginToLua;

plugins = pluginListToLua cfg.plugins;
pluginsTemp = pluginListToLua cfg.plugins;

packedPlugins = if length plugins == 1 then head plugins else plugins;
in
mkIf (cfg.plugins != [ ]) ''
packedPlugins = if length pluginsTemp == 1 then head pluginsTemp else pluginsTemp;
in
{
extraConfigLua = mkIf (cfg.plugins != [ ]) ''
require('lazy').setup(
{
dev = {
path = "${lazyPath}",
patterns = {"."},
fallback = false
},
spec = ${helpers.toLuaObject packedPlugins}
${nixvim.toLuaObject (setupOptions // { spec = packedPlugins; })}
}
)
'';
};
};
}
8 changes: 8 additions & 0 deletions tests/test-sources/plugins/pluginmanagers/lazy.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
plugins = [
vim-closer

# Test freeform
{
pkg = vim-dispatch;
# The below is not actually a property in the `lazy.nvim` plugin spec
# but is purely to test freeform capabilities of the `pluginType`.
blah = "test";
}

# Load on specific commands
{
pkg = vim-dispatch;
Expand Down

0 comments on commit 2ca79f3

Please sign in to comment.