{pkgs, ...}: let inherit (pkgs) lib; inherit (lib) concatMap evalModules fix literalExample mkEnableOption mkOption mkPackageOption optional types; initModule = types.submodule { options = { init = mkOption { type = with types; nullOr (either path str); default = null; description = '' Lua code to call before plugins loaded ''; }; postInit = mkOption { type = with types; nullOr (either path str); default = null; description = '' Lua code called after init but before import ''; }; config = mkOption { type = with types; nullOr (either path str); default = null; description = '' Lua code called after all plugins are loaded ''; }; }; }; pluginModule = types.submodule { options = { init = mkOption { type = with types; nullOr (either path str); default = null; description = '' The init configuration of your plugin. This will be called before loading your plugin. ''; }; config = mkOption { type = with types; nullOr (either path str); default = null; description = '' The configuration of your plugin. This will be called after loading your plugin. ''; }; plugin = mkOption { # TODO Type should allow `basicPluginType` type = with types; nullOr package; default = null; description = '' Ensure thoses plugins are loaded before the current one ''; }; dependencies = mkOption { type = with types; listOf package; default = []; description = '' Ensure thoses plugins are loaded before the current one ''; }; extraLuaPackages = mkOption { type = with types; listOf package; default = []; description = '' Ensure those packages are available ''; }; lazy = mkEnableOption "loading lazily the plugin"; events = mkOption { # TODO See eventType type = with types; listOf str; default = []; description = '' List of events on which the plugin should be loaded ''; }; cmd = mkOption { type = with types; listOf str; default = []; description = '' List of commands on which the plugin should be loaded ''; }; ft = mkOption { type = with types; listOf str; default = []; description = '' List of filetypes on which the plugin should be loaded ''; }; keymaps = mkOption { # TODO See keymapType type = with types; listOf str; default = []; description = '' List of keystrokes on which the plugin should be loaded ''; }; # priority = mkOption { # type = types.int; # default = []; # description = '' # Priority of the module. Influence the order of loading plugins. # Highest values get loaded before. # ''; # }; }; }; runtimeModule = types.submodule { options = { version = mkOption { type = with types; nullOr str; description = "Optional version of your runtime"; default = null; example = "2025.10.16"; }; src = mkOption { type = with types; either path attrs; description = "Files to include in your runtime"; example = ./my-runtime; }; extraOptions = mkOption { type = types.attrs; description = "Extra options to pass to `vimUtils.buildVimPlugin`"; default = {}; example.nvimRequireCheck = ["my-module.my-submodule"]; }; }; }; convertPkgToPlugin = pkg: { plugin = pkg; }; extraLuaPackagesType = (with types; functionTo package) // { merge = loc: defs: let fnList = concatMap (def: def.value) defs; concatPackages = ps: fn: fn ps; in ps: concatMap (concatPackages ps) fnList; }; defaultModule = { config, lib, ... }: { options = { package = mkPackageOption pkgs "neovim-unwrapped" {}; plugins = mkOption { description = '' List of plugins to enable in this installation ''; type = with types; listOf (coercedTo package convertPkgToPlugin pluginModule); default = []; }; # Will probably be not needed # dependenciesExtraArgs = mkOption { # default = {}; # }; extraLuaPackages = mkOption { description = '' function to define extra lua packages that should be included in neovim environment. ''; type = extraLuaPackagesType; example = literalExample "p: [p.nvim-nio]"; defaultText = literalExample "_: []"; default = _: []; }; runtime = mkOption { type = types.nullOr runtimeModule; default = null; description = '' Your runtime submodule. You can configure what files should be indluded in your runtime ''; }; init = mkOption { default = null; description = '' init.lua configuration ''; type = with types; nullOr (oneOf [path str initModule]); example = ./init.lua; }; viAlias = mkEnableOption "creation on `vi` alias"; vimAlias = mkEnableOption "creation on `vim` alias"; vimdiffAlias = mkEnableOption "creation on `vimdiff` alias"; nvimdiffAlias = mkEnableOption "creation on `nvimdiff` alias"; neovimOptions = mkOption { type = types.attrs; description = "The resulting configuration passed to `pkgs.wrapNeovimUnstable`"; default = pkgs.neovimUtils.makeNeovimConfig { # inherit customRC; # plugins = extractPlugins plugins; # extraLuaPackages = ps: # (extractLuaPackagesFn plugins ps) ++ (extraLuaPackages ps); }; }; neovimPackage = mkOption { type = types.package; description = "The neovim package generated from your configuration."; # defaultText = lib.literalExpression "pkgs.hello"; default = pkgs.wrapNeovimUnstable config.package config.neovimOptions; }; }; }; in fix (sLib: { inherit defaultModule; evalSlothModules = { modules ? [], specialArgs ? {}, }: let moduleConfig = evalModules { specialArgs = specialArgs // {inherit pkgs;}; modules = modules ++ [sLib.defaultModule]; }; in moduleConfig.config; mkNeovimPkg = { modules ? [], specialArgs ? {}, }: (sLib.evalSlothModules {inherit modules specialArgs;}).neovimPackage; })