diff --git a/lib/helpers.nix b/lib/helpers.nix index 9303780438..876ec1e94c 100644 --- a/lib/helpers.nix +++ b/lib/helpers.nix @@ -8,13 +8,21 @@ let nixvimBuilders = import ./builders.nix { inherit lib pkgs; }; nixvimTypes = import ./types.nix { inherit lib nixvimOptions; }; nixvimUtils = import ./utils.nix { inherit lib nixvimTypes _nixvimTests; }; - nixvimOptions = import ./options.nix { inherit lib nixvimTypes nixvimUtils; }; + nixvimOptions = import ./options.nix { + inherit + lib + nixvimTypes + nixvimUtils + nixvimKeymaps + ; + }; nixvimDeprecation = import ./deprecation.nix { inherit lib; }; + nixvimKeymaps = import ./keymap-helpers.nix { inherit lib nixvimOptions nixvimTypes; }; in rec { maintainers = import ./maintainers.nix; lua = import ./to-lua.nix { inherit lib; }; - keymaps = import ./keymap-helpers.nix { inherit lib nixvimOptions nixvimTypes; }; + keymaps = nixvimKeymaps; autocmd = import ./autocmd-helpers.nix { inherit lib nixvimOptions nixvimTypes; }; neovim-plugin = import ./neovim-plugin.nix { inherit diff --git a/lib/maintainers.nix b/lib/maintainers.nix index 52cef13ff2..589fc43e04 100644 --- a/lib/maintainers.nix +++ b/lib/maintainers.nix @@ -70,4 +70,10 @@ githubId = 4646110; name = "Nikita Shirokov"; }; + psfloyd = { + email = "peter.racoon@gmail.com"; + github = "psfloyd"; + githubId = 30784060; + name = "Pedro Sánchez"; + }; } diff --git a/lib/neovim-plugin.nix b/lib/neovim-plugin.nix index 46d7969f96..7c419fb506 100644 --- a/lib/neovim-plugin.nix +++ b/lib/neovim-plugin.nix @@ -48,9 +48,12 @@ with lib; extraPackages ? [ ], callSetup ? true, installPackage ? true, + allowLazyLoad ? true, + lazyLoad ? { }, }: let namespace = if isColorscheme then "colorschemes" else "plugins"; + cfg = config.${namespace}.${name}; in { meta = { @@ -99,21 +102,36 @@ with lib; example = settingsExample; }; } + // optionalAttrs allowLazyLoad { + lazyLoad = nixvimOptions.mkLazyLoadOption { + inherit originalName cfg; + optionsForPlugin = true; + lazyLoad = { + # TODO: extract extraConfigLua and extraConfigLuaPre from extraConfig + after = optionalString callSetup '' + require('${luaName}')${setup}(${optionalString (cfg ? settings) (toLuaObject cfg.settings)}) + ''; + colorscheme = if (isColorscheme && (colorscheme != null)) then [ colorscheme ] else null; + } // lazyLoad; + }; + } // extraOptions; config = let - cfg = config.${namespace}.${name}; extraConfigNamespace = if isColorscheme then "extraConfigLuaPre" else "extraConfigLua"; + lazyLoaded = if (cfg ? lazyLoad) then cfg.lazyLoad.enable else false; in mkIf cfg.enable (mkMerge [ { extraPlugins = (optional installPackage cfg.package) ++ extraPlugins; inherit extraPackages; - ${extraConfigNamespace} = optionalString callSetup '' + ${extraConfigNamespace} = optionalString (callSetup && !lazyLoaded) '' require('${luaName}')${setup}(${optionalString (cfg ? settings) (toLuaObject cfg.settings)}) ''; + + plugins.lz-n.plugins = mkIf lazyLoaded [ cfg.lazyLoad ]; } (optionalAttrs (isColorscheme && (colorscheme != null)) { colorscheme = mkDefault colorscheme; }) (extraConfig cfg) diff --git a/lib/options.nix b/lib/options.nix index 016d12d10c..144916d4a6 100644 --- a/lib/options.nix +++ b/lib/options.nix @@ -2,6 +2,7 @@ lib, nixvimTypes, nixvimUtils, + nixvimKeymaps, }: with lib; with nixvimUtils; @@ -368,4 +369,70 @@ rec { else example; }; + + mkLazyLoadOption = + { + originalName ? "this plugin", + cfg ? { }, + lazyLoad ? { }, + optionsForPlugin ? false, + }: + let + lazyLoadPluginDefault = { + enable = false; + name = originalName; + enabledInSpec = true; + } // lazyLoad; + getPluginDefault = n: if (lazyLoadPluginDefault ? ${n}) then lazyLoadPluginDefault.${n} else null; + in + mkOption { + description = "Lazy-load settings for ${originalName}."; + type = + with nixvimTypes; + submodule { + options = with defaultNullOpts; { + # enable option only has an effect when it is a sub-option for a plugin generated by mkNeovimPlugin + enable = mkOption { + type = bool; + default = getPluginDefault "enable"; + description = "Enable lazy-loading for ${originalName}"; + # Only show this option when it is a sub-option for a plugin + visible = optionsForPlugin; + }; + name = mkOption { + type = str; + default = getPluginDefault "name"; + description = "The plugin's name (not the module name). This is what is passed to the load(name) function."; + }; + enabledInSpec = mkStrLuaFnOr bool (getPluginDefault "enabledInSpec") '' + When false, or if the function returns false, then ${originalName} will not be included in the spec. + This option corresponds to the `enabled` property of lz.n. + ''; + beforeAll = mkLuaFn (getPluginDefault "beforeAll") "Always executed before any plugins are loaded."; + before = mkLuaFn (getPluginDefault "before") "Executed before ${originalName} is loaded."; + after = mkLuaFn (getPluginDefault "after") "Executed after ${originalName} is loaded."; + event = + mkNullable (listOf str) (getPluginDefault "event") + "Lazy-load on event. Events can be specified as BufEnter or with a pattern like BufEnter *.lua"; + cmd = mkNullable (listOf str) (getPluginDefault "cmd") "Lazy-load on command."; + ft = mkNullable (listOf str) (getPluginDefault "ft") "Lazy-load on filetype."; + keys = + mkNullable (listOf nixvimKeymaps.mapOptionSubmodule) (getPluginDefault "keys") + "Lazy-load on key mapping. Use the same format as `config.keymaps`."; + colorscheme = mkNullable (listOf str) (getPluginDefault "colorscheme") "Lazy-load on colorscheme."; + priority = mkNullable number (getPluginDefault "priority") '' + Only useful for start plugins (not lazy-loaded) to force loading certain plugins first. + Default priority is 50 (or 1000 if colorscheme is set). + ''; + load = mkLuaFn (getPluginDefault "load") "Can be used to override the vim.g.lz_n.load() function for ${originalName}."; + }; + config = mkIf (cfg != { }) ( + mapAttrs ( + name: value: if (builtins.typeOf value == "list") then value else mkDefault value + ) lazyLoadPluginDefault + ); + }; + default = lazyLoadPluginDefault; + }; + } diff --git a/plugins/default.nix b/plugins/default.nix index e4e687b6e2..2a69a367d6 100644 --- a/plugins/default.nix +++ b/plugins/default.nix @@ -118,6 +118,7 @@ ./pluginmanagers/packer.nix ./pluginmanagers/lazy.nix + ./pluginmanagers/lz-n.nix ./snippets/friendly-snippets.nix ./snippets/luasnip diff --git a/plugins/languages/qmk.nix b/plugins/languages/qmk.nix index 1b4dd71b20..af72c9e5c0 100644 --- a/plugins/languages/qmk.nix +++ b/plugins/languages/qmk.nix @@ -16,6 +16,7 @@ helpers.neovim-plugin.mkNeovimPlugin config { settingsOptions = { name = mkOption { type = types.str; + default = ""; example = "LAYOUT_preonic_grid"; description = '' The name of your layout, for example `LAYOUT_preonic_grid` for the preonic keyboard, for @@ -25,6 +26,7 @@ helpers.neovim-plugin.mkNeovimPlugin config { layout = mkOption { type = with types; listOf str; + default = [ ]; example = [ "x x" "x^x" diff --git a/plugins/pluginmanagers/lz-n.nix b/plugins/pluginmanagers/lz-n.nix new file mode 100644 index 0000000000..5d3cf534c9 --- /dev/null +++ b/plugins/pluginmanagers/lz-n.nix @@ -0,0 +1,96 @@ +{ + lib, + helpers, + config, + pkgs, + ... +}: +let + inherit (helpers) mkNullOrLuaFn' nixvimTypes mkLazyLoadOption; + + name = "lz-n"; + originalName = "lz.n"; + cfg = config.plugins.${name}; +in +with lib; +helpers.neovim-plugin.mkNeovimPlugin config { + inherit name originalName; + maintainers = with helpers.maintainers; [ psfloyd ]; + defaultPackage = pkgs.vimPlugins.lz-n; + + settingsDescription = '' + The configuration options for **${originalName}** using `vim.g.lz_n`. + + `{ load = "fun"; }` -> `vim.g.lz_n = { load = fun, }` + ''; + + settingsOptions = { + load = mkNullOrLuaFn' { + description = '' + Function used by `lz.n` to load plugins. + ''; + default = null; + pluginDefault = "vim.cmd.packadd"; + }; + }; + + settingsExample = { + load = "vim.cmd.packadd"; + }; + + callSetup = false; # Does not use setup + allowLazyLoad = false; + + extraOptions = with nixvimTypes; { + plugins = mkOption { + description = "List of plugins processed by lz.n"; + default = [ ]; + type = listOf (mkLazyLoadOption { }).type; + }; + }; + + extraConfig = cfg: { + globals.lz_n = cfg.settings; + extraConfigLua = + let + processKeymap = + keymaps: + if keymaps == null then + null + else + map ( + keymap: + { + __unkeyed_1 = keymap.key; + __unkeyed_2 = keymap.action; + inherit (keymap) mode; + } + // keymap.options + ) keymaps; + pluginToLua = plugin: { + "__unkeyed" = plugin.name; + inherit (plugin) + beforeAll + before + after + event + cmd + ft + colorscheme + priority + load + ; + enabled = plugin.enabledInSpec; + keys = processKeymap plugin.keys; + }; + pluginListToLua = map pluginToLua; + plugins = pluginListToLua cfg.plugins; + pluginSpecs = if length plugins == 1 then head plugins else plugins; + in + mkIf (cfg.plugins != [ ]) '' + require('lz.n').load( + ${helpers.toLuaObject pluginSpecs} + ) + ''; + }; +} diff --git a/tests/test-sources/plugins/pluginmanagers/lz-n.nix b/tests/test-sources/plugins/pluginmanagers/lz-n.nix new file mode 100644 index 0000000000..889c8133a8 --- /dev/null +++ b/tests/test-sources/plugins/pluginmanagers/lz-n.nix @@ -0,0 +1,86 @@ +{ pkgs, ... }: +{ + # Empty configuration + empty = { + plugins.lz-n.enable = true; + }; + + # Settings + example = { + plugins.lz-n = { + enable = true; + settings = { + load = "vim.cmd.packadd"; + }; + }; + + }; + + test = { + extraPlugins = with pkgs.vimPlugins; [ + neo-tree-nvim + telescope-nvim + onedarker-nvim + vimtex + + ]; + plugins.lz-n = { + enable = true; + plugins = [ + # On keymap with setup function + { + name = "neo-tree.nvim"; + keys = [ + { + mode = [ "n" ]; + key = "ft"; + action = "Neotree toggle"; + options = { + desc = "NeoTree toggle"; + }; + } + { + mode = [ + "n" + "v" + ]; + key = "gft"; + action = "Neotree toggle"; + options = { + desc = "NeoTree toggle"; + }; + } + ]; + after = # lua + '' + function() + require("neo-tree").setup() + end + ''; + } + # On command no setup function + { + name = "telescope.nvim"; + cmd = [ "Telescope" ]; + } + # On colorschme + { + name = "onedarker.nvim"; + colorscheme = [ "onedarker" ]; + } + # On filetype with before function + { + name = "vimtex"; + ft = [ "plaintex" ]; + before = # lua + '' + function() + vim.g.vimtex_compiler_method = "latexrun" + end + ''; + } + ]; + }; + }; + +}