diff --git a/lib/default.nix b/lib/default.nix index 47079086..cb478522 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -26,13 +26,13 @@ lib.makeExtensible ( # plugin aliases neovim-plugin = { - inherit (self.plugins) + inherit (self.plugins.neovim) extraOptionsOptions mkNeovimPlugin ; }; vim-plugin = { - inherit (self.plugins) + inherit (self.plugins.vim) mkSettingsOption mkSettingsOptionDescription mkVimPlugin diff --git a/lib/plugins/default.nix b/lib/plugins/default.nix index 63a63d4d..cf507021 100644 --- a/lib/plugins/default.nix +++ b/lib/plugins/default.nix @@ -1,12 +1,12 @@ -{ call }: -let +{ + call, + lib, +}: +{ neovim = call ./neovim.nix { }; vim = call ./vim.nix { }; -in -# TODO: be a bit more deliberate -# NOTE: remove the overridable stuff from `call`; -# I don't want to think about how (a // b) interacts with them yet -builtins.removeAttrs (neovim // vim) [ - "override" - "overrideDerivation" -] + + # Aliases + inherit (lib.nixvim.plugins.neovim) mkNeovimPlugin; + inherit (lib.nixvim.plugins.vim) mkVimPlugin; +} diff --git a/lib/plugins/mk-neovim-plugin.nix b/lib/plugins/mk-neovim-plugin.nix new file mode 100644 index 00000000..369aac33 --- /dev/null +++ b/lib/plugins/mk-neovim-plugin.nix @@ -0,0 +1,202 @@ +{ lib }: +{ + name, + maintainers, + url ? throw "default", + imports ? [ ], + description ? null, + # deprecations + deprecateExtraOptions ? false, + optionsRenamedToSettings ? [ ], + # colorscheme + isColorscheme ? false, + colorscheme ? name, + # luaConfig + configLocation ? if isColorscheme then "extraConfigLuaPre" else "extraConfigLua", + # Some plugin are not supposed to generate lua configuration code. + # For example, they might just be configured through some other mean, like global variables + hasLuaConfig ? true, + # options + packPathName ? name, + # Can be a string, a list of strings, or a module option: + # - A string will be intrpreted as `pkgs.vimPlugins.${package}` + # - A list will be interpreted as a "pkgs path", e.g. `pkgs.${elem1}.${elem2}.${etc...}` + # - An option will be used as-is, but should be built using `lib.mkPackageOption` + # Defaults to `name`, i.e. `pkgs.vimPlugins.${name}` + package ? name, + settingsOptions ? { }, + settingsExample ? null, + settingsDescription ? "Options provided to the `require('${moduleName}')${setup}` function.", + hasSettings ? true, + extraOptions ? { }, + # config + moduleName ? name, + setup ? ".setup", + extraConfig ? cfg: { }, + extraPlugins ? [ ], + extraPackages ? [ ], + callSetup ? true, +}@args: +let + namespace = if isColorscheme then "colorschemes" else "plugins"; + loc = [ + namespace + name + ]; + + module = + { + config, + options, + pkgs, + ... + }: + let + cfg = lib.getAttrFromPath loc config; + opts = lib.getAttrFromPath loc options; + + setupCode = '' + require('${moduleName}')${setup}(${ + lib.optionalString (cfg ? settings) (lib.nixvim.toLuaObject cfg.settings) + }) + ''; + + luaConfigAtLocation = lib.nixvim.modules.mkConfigAt configLocation cfg.luaConfig.content; + in + { + meta = { + inherit maintainers; + nixvimInfo = { + inherit description; + url = args.url or opts.package.default.meta.homepage; + path = loc; + }; + }; + + options = lib.setAttrByPath loc ( + { + enable = lib.mkEnableOption packPathName; + lazyLoad = lib.nixvim.mkLazyLoadOption packPathName; + package = + if lib.isOption package then + package + else + lib.mkPackageOption pkgs packPathName { + default = + if builtins.isList package then + package + else + [ + "vimPlugins" + package + ]; + }; + packageDecorator = lib.mkOption { + type = lib.types.functionTo lib.types.package; + default = lib.id; + defaultText = lib.literalExpression "x: x"; + description = '' + Additional transformations to apply to the final installed package. + The result of these transformations is **not** visible in the `package` option's value. + ''; + internal = true; + }; + } + // lib.optionalAttrs hasSettings { + settings = lib.nixvim.mkSettingsOption { + description = settingsDescription; + options = settingsOptions; + example = settingsExample; + }; + } + // lib.optionalAttrs hasLuaConfig { + luaConfig = lib.mkOption { + type = lib.types.pluginLuaConfig; + default = { }; + description = "The plugin's lua configuration"; + }; + } + // extraOptions + ); + + config = + assert lib.assertMsg ( + callSetup -> hasLuaConfig + ) "This plugin is supposed to call the `setup()` function but has `hasLuaConfig` set to false"; + lib.mkIf cfg.enable ( + lib.mkMerge ( + [ + { + inherit extraPackages; + extraPlugins = extraPlugins ++ [ + (cfg.packageDecorator cfg.package) + ]; + } + + (lib.optionalAttrs (isColorscheme && colorscheme != null) { + colorscheme = lib.mkDefault colorscheme; + }) + + # Apply any additional configuration added to `extraConfig` + (lib.optionalAttrs (args ? extraConfig) ( + lib.nixvim.modules.applyExtraConfig { + inherit extraConfig cfg opts; + } + )) + ] + # Lua configuration code generation + ++ lib.optionals hasLuaConfig [ + + # Add the plugin setup code `require('foo').setup(...)` to the lua configuration + (lib.optionalAttrs callSetup (lib.setAttrByPath loc { luaConfig.content = setupCode; })) + + # When NOT lazy loading, write `luaConfig.content` to `configLocation` + (lib.mkIf (!cfg.lazyLoad.enable) luaConfigAtLocation) + + # When lazy loading is enabled for this plugin, route its configuration to the enabled provider + (lib.mkIf cfg.lazyLoad.enable { + assertions = [ + { + assertion = (isColorscheme && colorscheme != null) || cfg.lazyLoad.settings != { }; + message = "You have enabled lazy loading for ${packPathName} but have not provided any configuration."; + } + ]; + plugins.lz-n = { + plugins = [ + ( + { + __unkeyed-1 = packPathName; + # Use provided after, otherwise fallback to normal function wrapped lua content + after = + let + after = cfg.lazyLoad.settings.after or null; + default = "function()\n " + cfg.luaConfig.content + " \nend"; + in + if (lib.isString after || lib.types.rawLua.check after) then after else default; + colorscheme = lib.mkIf isColorscheme (cfg.lazyLoad.settings.colorscheme or colorscheme); + } + // lib.removeAttrs cfg.lazyLoad.settings [ + "after" + "colorscheme" + ] + ) + ]; + }; + }) + ] + ) + ); + }; +in +{ + imports = + let + settingsPath = loc ++ [ "settings" ]; + in + imports + ++ [ module ] + ++ lib.optional deprecateExtraOptions ( + lib.mkRenamedOptionModule (loc ++ [ "extraOptions" ]) settingsPath + ) + ++ lib.nixvim.mkSettingsRenamedOptionModules loc settingsPath optionsRenamedToSettings; +} diff --git a/lib/plugins/mk-vim-plugin.nix b/lib/plugins/mk-vim-plugin.nix new file mode 100644 index 00000000..20ceddc1 --- /dev/null +++ b/lib/plugins/mk-vim-plugin.nix @@ -0,0 +1,138 @@ +{ lib }: +let + inherit (lib.nixvim.plugins.vim) + mkSettingsOption + ; +in +{ + name, + url ? throw "default", + maintainers, + imports ? [ ], + description ? null, + # deprecations + deprecateExtraConfig ? false, + optionsRenamedToSettings ? [ ], + # colorscheme + isColorscheme ? false, + colorscheme ? name, + # options + packPathName ? name, + # Can be a string, a list of strings, or a module option: + # - A string will be intrpreted as `pkgs.vimPlugins.${package}` + # - A list will be interpreted as a "pkgs path", e.g. `pkgs.${elem1}.${elem2}.${etc...}` + # - An option will be used as-is, but should be built using `lib.mkPackageOption` + # Defaults to `name`, i.e. `pkgs.vimPlugins.${name}` + package ? name, + settingsOptions ? { }, + settingsExample ? null, + globalPrefix ? "", + extraOptions ? { }, + # config + extraConfig ? cfg: { }, + extraPlugins ? [ ], + extraPackages ? [ ], +}@args: +let + namespace = if isColorscheme then "colorschemes" else "plugins"; + loc = [ + namespace + name + ]; + + createSettingsOption = lib.isString globalPrefix && globalPrefix != ""; + + settingsOption = lib.optionalAttrs createSettingsOption { + settings = mkSettingsOption { + options = settingsOptions; + example = settingsExample; + inherit name globalPrefix; + }; + }; + + module = + { + config, + options, + pkgs, + ... + }: + let + cfg = lib.getAttrFromPath loc config; + opts = lib.getAttrFromPath loc options; + in + { + meta = { + inherit maintainers; + nixvimInfo = { + inherit description; + url = args.url or opts.package.default.meta.homepage; + path = loc; + }; + }; + + options = lib.setAttrByPath loc ( + { + enable = lib.mkEnableOption packPathName; + package = + if lib.isOption package then + package + else + lib.mkPackageOption pkgs packPathName { + default = + if builtins.isList package then + package + else + [ + "vimPlugins" + package + ]; + }; + packageDecorator = lib.mkOption { + type = lib.types.functionTo lib.types.package; + default = lib.id; + defaultText = lib.literalExpression "x: x"; + description = '' + Additional transformations to apply to the final installed package. + The result of these transformations is **not** visible in the `package` option's value. + ''; + internal = true; + }; + } + // settingsOption + // extraOptions + ); + + config = lib.mkIf cfg.enable ( + lib.mkMerge [ + { + inherit extraPackages; + extraPlugins = extraPlugins ++ [ + (cfg.packageDecorator cfg.package) + ]; + globals = lib.nixvim.applyPrefixToAttrs globalPrefix (cfg.settings or { }); + } + (lib.optionalAttrs (isColorscheme && colorscheme != null) { + colorscheme = lib.mkDefault colorscheme; + }) + (lib.optionalAttrs (args ? extraConfig) ( + lib.nixvim.modules.applyExtraConfig { + inherit extraConfig cfg opts; + } + )) + ] + ); + }; +in +{ + imports = + let + settingsPath = loc ++ [ "settings" ]; + in + imports + ++ [ module ] + ++ lib.optional (deprecateExtraConfig && createSettingsOption) ( + lib.mkRenamedOptionModule (loc ++ [ "extraConfig" ]) settingsPath + ) + ++ lib.nixvim.mkSettingsRenamedOptionModules loc settingsPath optionsRenamedToSettings; +} diff --git a/lib/plugins/neovim.nix b/lib/plugins/neovim.nix index bcaee2c3..7735f0cb 100644 --- a/lib/plugins/neovim.nix +++ b/lib/plugins/neovim.nix @@ -1,5 +1,10 @@ -{ lib }: { + call, + lib, +}: +{ + mkNeovimPlugin = call ./mk-neovim-plugin.nix { }; + # TODO: DEPRECATED: use the `settings` option instead extraOptionsOptions = { extraOptions = lib.mkOption { @@ -11,207 +16,4 @@ ''; }; }; - - mkNeovimPlugin = - { - name, - maintainers, - url ? throw "default", - imports ? [ ], - description ? null, - # deprecations - deprecateExtraOptions ? false, - optionsRenamedToSettings ? [ ], - # colorscheme - isColorscheme ? false, - colorscheme ? name, - # luaConfig - configLocation ? if isColorscheme then "extraConfigLuaPre" else "extraConfigLua", - # Some plugin are not supposed to generate lua configuration code. - # For example, they might just be configured through some other mean, like global variables - hasLuaConfig ? true, - # options - packPathName ? name, - # Can be a string, a list of strings, or a module option: - # - A string will be intrpreted as `pkgs.vimPlugins.${package}` - # - A list will be interpreted as a "pkgs path", e.g. `pkgs.${elem1}.${elem2}.${etc...}` - # - An option will be used as-is, but should be built using `lib.mkPackageOption` - # Defaults to `name`, i.e. `pkgs.vimPlugins.${name}` - package ? name, - settingsOptions ? { }, - settingsExample ? null, - settingsDescription ? "Options provided to the `require('${moduleName}')${setup}` function.", - hasSettings ? true, - extraOptions ? { }, - # config - moduleName ? name, - setup ? ".setup", - extraConfig ? cfg: { }, - extraPlugins ? [ ], - extraPackages ? [ ], - callSetup ? true, - }@args: - let - namespace = if isColorscheme then "colorschemes" else "plugins"; - loc = [ - namespace - name - ]; - - module = - { - config, - options, - pkgs, - ... - }: - let - cfg = lib.getAttrFromPath loc config; - opts = lib.getAttrFromPath loc options; - - setupCode = '' - require('${moduleName}')${setup}(${ - lib.optionalString (cfg ? settings) (lib.nixvim.toLuaObject cfg.settings) - }) - ''; - - luaConfigAtLocation = lib.nixvim.modules.mkConfigAt configLocation cfg.luaConfig.content; - in - { - meta = { - inherit maintainers; - nixvimInfo = { - inherit description; - url = args.url or opts.package.default.meta.homepage; - path = loc; - }; - }; - - options = lib.setAttrByPath loc ( - { - enable = lib.mkEnableOption packPathName; - lazyLoad = lib.nixvim.mkLazyLoadOption packPathName; - package = - if lib.isOption package then - package - else - lib.mkPackageOption pkgs packPathName { - default = - if builtins.isList package then - package - else - [ - "vimPlugins" - package - ]; - }; - packageDecorator = lib.mkOption { - type = lib.types.functionTo lib.types.package; - default = lib.id; - defaultText = lib.literalExpression "x: x"; - description = '' - Additional transformations to apply to the final installed package. - The result of these transformations is **not** visible in the `package` option's value. - ''; - internal = true; - }; - } - // lib.optionalAttrs hasSettings { - settings = lib.nixvim.mkSettingsOption { - description = settingsDescription; - options = settingsOptions; - example = settingsExample; - }; - } - // lib.optionalAttrs hasLuaConfig { - luaConfig = lib.mkOption { - type = lib.types.pluginLuaConfig; - default = { }; - description = "The plugin's lua configuration"; - }; - } - // extraOptions - ); - - config = - assert lib.assertMsg ( - callSetup -> hasLuaConfig - ) "This plugin is supposed to call the `setup()` function but has `hasLuaConfig` set to false"; - lib.mkIf cfg.enable ( - lib.mkMerge ( - [ - { - inherit extraPackages; - extraPlugins = extraPlugins ++ [ - (cfg.packageDecorator cfg.package) - ]; - } - - (lib.optionalAttrs (isColorscheme && colorscheme != null) { - colorscheme = lib.mkDefault colorscheme; - }) - - # Apply any additional configuration added to `extraConfig` - (lib.optionalAttrs (args ? extraConfig) ( - lib.nixvim.modules.applyExtraConfig { - inherit extraConfig cfg opts; - } - )) - ] - # Lua configuration code generation - ++ lib.optionals hasLuaConfig [ - - # Add the plugin setup code `require('foo').setup(...)` to the lua configuration - (lib.optionalAttrs callSetup (lib.setAttrByPath loc { luaConfig.content = setupCode; })) - - # When NOT lazy loading, write `luaConfig.content` to `configLocation` - (lib.mkIf (!cfg.lazyLoad.enable) luaConfigAtLocation) - - # When lazy loading is enabled for this plugin, route its configuration to the enabled provider - (lib.mkIf cfg.lazyLoad.enable { - assertions = [ - { - assertion = (isColorscheme && colorscheme != null) || cfg.lazyLoad.settings != { }; - message = "You have enabled lazy loading for ${packPathName} but have not provided any configuration."; - } - ]; - plugins.lz-n = { - plugins = [ - ( - { - __unkeyed-1 = packPathName; - # Use provided after, otherwise fallback to normal function wrapped lua content - after = - let - after = cfg.lazyLoad.settings.after or null; - default = "function()\n " + cfg.luaConfig.content + " \nend"; - in - if (lib.isString after || lib.types.rawLua.check after) then after else default; - colorscheme = lib.mkIf isColorscheme (cfg.lazyLoad.settings.colorscheme or colorscheme); - } - // lib.removeAttrs cfg.lazyLoad.settings [ - "after" - "colorscheme" - ] - ) - ]; - }; - }) - ] - ) - ); - }; - in - { - imports = - let - settingsPath = loc ++ [ "settings" ]; - in - imports - ++ [ module ] - ++ lib.optional deprecateExtraOptions ( - lib.mkRenamedOptionModule (loc ++ [ "extraOptions" ]) settingsPath - ) - ++ lib.nixvim.mkSettingsRenamedOptionModules loc settingsPath optionsRenamedToSettings; - }; } diff --git a/lib/plugins/vim.nix b/lib/plugins/vim.nix index 004570da..f1bcb2cb 100644 --- a/lib/plugins/vim.nix +++ b/lib/plugins/vim.nix @@ -1,5 +1,15 @@ -{ lib }: -rec { +{ + call, + lib, +}: +let + inherit (lib.nixvim.plugins.vim) + mkSettingsOptionDescription + ; +in +{ + mkVimPlugin = call ./mk-vim-plugin.nix { }; + mkSettingsOptionDescription = { name, globalPrefix }: '' @@ -23,138 +33,4 @@ rec { inherit options example; description = mkSettingsOptionDescription { inherit name globalPrefix; }; }; - - mkVimPlugin = - { - name, - url ? throw "default", - maintainers, - imports ? [ ], - description ? null, - # deprecations - deprecateExtraConfig ? false, - optionsRenamedToSettings ? [ ], - # colorscheme - isColorscheme ? false, - colorscheme ? name, - # options - packPathName ? name, - # Can be a string, a list of strings, or a module option: - # - A string will be intrpreted as `pkgs.vimPlugins.${package}` - # - A list will be interpreted as a "pkgs path", e.g. `pkgs.${elem1}.${elem2}.${etc...}` - # - An option will be used as-is, but should be built using `lib.mkPackageOption` - # Defaults to `name`, i.e. `pkgs.vimPlugins.${name}` - package ? name, - settingsOptions ? { }, - settingsExample ? null, - globalPrefix ? "", - extraOptions ? { }, - # config - extraConfig ? cfg: { }, - extraPlugins ? [ ], - extraPackages ? [ ], - }@args: - let - namespace = if isColorscheme then "colorschemes" else "plugins"; - loc = [ - namespace - name - ]; - - createSettingsOption = lib.isString globalPrefix && globalPrefix != ""; - - settingsOption = lib.optionalAttrs createSettingsOption { - settings = mkSettingsOption { - options = settingsOptions; - example = settingsExample; - inherit name globalPrefix; - }; - }; - - module = - { - config, - options, - pkgs, - ... - }: - let - cfg = lib.getAttrFromPath loc config; - opts = lib.getAttrFromPath loc options; - in - { - meta = { - inherit maintainers; - nixvimInfo = { - inherit description; - url = args.url or opts.package.default.meta.homepage; - path = loc; - }; - }; - - options = lib.setAttrByPath loc ( - { - enable = lib.mkEnableOption packPathName; - package = - if lib.isOption package then - package - else - lib.mkPackageOption pkgs packPathName { - default = - if builtins.isList package then - package - else - [ - "vimPlugins" - package - ]; - }; - packageDecorator = lib.mkOption { - type = lib.types.functionTo lib.types.package; - default = lib.id; - defaultText = lib.literalExpression "x: x"; - description = '' - Additional transformations to apply to the final installed package. - The result of these transformations is **not** visible in the `package` option's value. - ''; - internal = true; - }; - } - // settingsOption - // extraOptions - ); - - config = lib.mkIf cfg.enable ( - lib.mkMerge [ - { - inherit extraPackages; - extraPlugins = extraPlugins ++ [ - (cfg.packageDecorator cfg.package) - ]; - globals = lib.nixvim.applyPrefixToAttrs globalPrefix (cfg.settings or { }); - } - (lib.optionalAttrs (isColorscheme && colorscheme != null) { - colorscheme = lib.mkDefault colorscheme; - }) - (lib.optionalAttrs (args ? extraConfig) ( - lib.nixvim.modules.applyExtraConfig { - inherit extraConfig cfg opts; - } - )) - ] - ); - }; - in - { - imports = - let - settingsPath = loc ++ [ "settings" ]; - in - imports - ++ [ module ] - ++ lib.optional (deprecateExtraConfig && createSettingsOption) ( - lib.mkRenamedOptionModule (loc ++ [ "extraConfig" ]) settingsPath - ) - ++ lib.nixvim.mkSettingsRenamedOptionModules loc settingsPath optionsRenamedToSettings; - }; }