From fabe787feb2df23a51a5056af4d1dae91d9c02c6 Mon Sep 17 00:00:00 2001 From: LeMarsu Date: Mon, 6 Oct 2025 17:47:49 +0200 Subject: [PATCH] feat: can use flakeModules perSystem to build package with new ongoing module API --- flake.lock | 16 ++++ flake.nix | 8 +- flakeModule.nix | 51 ++++++++++ lib/default.nix | 9 +- lib/lib.nix | 248 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 326 insertions(+), 6 deletions(-) create mode 100644 flakeModule.nix create mode 100644 lib/lib.nix diff --git a/flake.lock b/flake.lock index 1333f2a..75643cd 100644 --- a/flake.lock +++ b/flake.lock @@ -49,6 +49,21 @@ "type": "github" } }, + "nixpkgs-lib_2": { + "locked": { + "lastModified": 1754788789, + "narHash": "sha256-x2rJ+Ovzq0sCMpgfgGaaqgBSwY+LST+WbZ6TytnT9Rk=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "a73b9c743612e4244d865a2fdee11865283c04e6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1660438583, @@ -68,6 +83,7 @@ "inputs": { "flake-parts": "flake-parts", "nixpkgs": "nixpkgs", + "nixpkgs-lib": "nixpkgs-lib_2", "yants": "yants" } }, diff --git a/flake.nix b/flake.nix index 4779fb8..afc3b4e 100644 --- a/flake.nix +++ b/flake.nix @@ -3,16 +3,18 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + nixpkgs-lib.url = "github:nix-community/nixpkgs.lib"; yants.url = "github:divnix/yants"; flake-parts.url = "github:hercules-ci/flake-parts"; }; - outputs = {flake-parts, ...} @ inputs: let - in (flake-parts.lib.mkFlake {inherit inputs;} { + outputs = {flake-parts, ...} @ inputs: (flake-parts.lib.mkFlake {inherit inputs;} { systems = ["x86_64-linux"]; - imports = [ + imports = with flake-parts.flakeModules; [ + flakeModules ./dev + ./flakeModule.nix ./lib ]; }); diff --git a/flakeModule.nix b/flakeModule.nix new file mode 100644 index 0000000..1ee749a --- /dev/null +++ b/flakeModule.nix @@ -0,0 +1,51 @@ +{config, ...}: { + config.flake.flakeModules.default = { + lib, + flake-parts-lib, + ... + }: let + inherit (lib) attrsToList listToAttrs mkOption types; + inherit (flake-parts-lib) mkPerSystemOption; + topConfig = config; + in { + options.perSystem = mkPerSystemOption ({ + pkgs, + config, + ... + }: let + cfg = config.sloth; + inherit (cfg) lib; + + packageModule = types.submodule { + options.modules = mkOption { + description = "modules used to create your neovim package"; + type = with types; listOf attrs; + default = []; + }; + }; + + buildPackage = { name, value }: { + inherit name; + value = (lib.evalSlothModules {inherit (value) modules;}).neovimPackage; + }; + packagesList = map buildPackage (attrsToList cfg.packages); + in { + options.sloth = { + lib = mkOption { + type = types.attrs; + description = "sloth’s lib"; + default = topConfig.flake.mkLib {inherit pkgs;}; + defaultText = "mkLib { inherit pkgs; }"; + }; + + packages = mkOption { + description = "neovim package to create with sloth"; + default = {}; + type = with types; attrsOf packageModule; + }; + }; + + config.packages = listToAttrs packagesList; + }); + }; +} diff --git a/lib/default.nix b/lib/default.nix index 15f3192..598d998 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -12,8 +12,11 @@ types = import ./types.nix {inherit (inputs) yants;}; in { - flake.lib = { - mkNeovimPkg = import ./mkNeovimPkg.nix {inherit version types;}; - mkPluginsFromInputs = import ./mkPluginsFromInputs.nix; + flake = { + lib = { + mkNeovimPkg = import ./mkNeovimPkg.nix {inherit version types;}; + mkPluginsFromInputs = import ./mkPluginsFromInputs.nix; + }; + mkLib = import ./lib.nix; }; } diff --git a/lib/lib.nix b/lib/lib.nix new file mode 100644 index 0000000..19a692a --- /dev/null +++ b/lib/lib.nix @@ -0,0 +1,248 @@ +{pkgs, ...}: let + inherit (pkgs) lib; + inherit (lib) concatMap evalModules 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 { + evalSlothModules = { + modules ? [], + specialArgs ? {}, + }: let + moduleConfig = evalModules { + specialArgs = specialArgs // {inherit pkgs;}; + modules = modules ++ [defaultModule]; + }; + in + moduleConfig.config; +}