diff --git a/flake.nix b/flake.nix index fb2f612..680e12a 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ ]; imports = [ - ./modules/flake/lib.nix + ./modules/flake/lib ./modules/flake/pkgs ./modules/flake/modules ./modules/flake/configurations diff --git a/modules/flake/lib.nix b/modules/flake/lib/default.nix similarity index 99% rename from modules/flake/lib.nix rename to modules/flake/lib/default.nix index aede7bc..34d3084 100644 --- a/modules/flake/lib.nix +++ b/modules/flake/lib/default.nix @@ -1,6 +1,10 @@ { lib, config, self, ... }: { + imports = [ + ./things.nix + ]; + options = let inherit (lib) types; in { diff --git a/modules/flake/lib/things.nix b/modules/flake/lib/things.nix new file mode 100644 index 0000000..72bfd7f --- /dev/null +++ b/modules/flake/lib/things.nix @@ -0,0 +1,112 @@ +{ lib, config, self, inputs, ... }: + +let + inherit (config.lib) + and + eq + hasFiles + ; +in +{ + config.lib = rec { + # Try to passthru `inputs` by default + defaultThingHandle = { raw, thingType }: name: result: let + thing = + if raw + then result + else result.${thingType}; + passthru = { + inherit inputs; + }; + handledThing = + if and [ + (builtins.isFunction + thing) + # FIXME: check for subset, not `eq` + (eq + (lib.pipe thing [ builtins.functionArgs builtins.attrNames ]) + (lib.pipe passthru [ builtins.attrNames ])) + ] + # { inputs, ... }: { foo, ... }: bar + then thing passthru + # { foo, ... }: bar + else thing; + handledResult = + if raw + then handledThing + else result // { ${thingType} = handledThing; }; + in handledResult; + + # TODO: make `passthru` more generic (maybe take `thing` as arg and decide itself what to do?) + createThings = + { baseDir + , thingType ? "thing" + , filter ? (name: type: true) + , handle ? (defaultThingHandle { inherit raw thingType; }) + , raw ? true + , extras ? {} + , ... + }: + assert raw -> extras == {}; + lib.pipe baseDir [ + # Read given directory + builtins.readDir + # Filter out unwanted things + (lib.filterAttrs + filter) + # Map each entry to a thing + (lib.mapAttrs' + (name: type: + let + # BUG: cannot use `append` because of `${self}` (not a path) + # thingDir = lib.path.append baseDir "${name}"; + thingDir = "${baseDir}/${name}"; + importedExtras = lib.pipe extras [ + (lib.mapAttrs (name: { default, ... }: + assert name != "default"; + assert name != thingType; + let + extraPath = "${thingDir}/${name}.nix"; + in + if builtins.pathExists extraPath + then import extraPath + else default)) + ]; + thing = import thingDir; + result = + if raw + then thing + else lib.attrsets.unionOfDisjoint + { ${thingType} = thing; } + importedExtras; + in + if and [ + (type == "directory") + (hasFiles [ "default.nix" ] (builtins.readDir thingDir)) + ] then + # Classic thing in a directory + lib.nameValuePair + name + result + else if and [ + (type == "regular") + (lib.hasSuffix ".nix" name) + ] then + # Classic thing in a file + lib.nameValuePair + (lib.removeSuffix ".nix" name) + result + else + # Invalid thing + lib.nameValuePair + name + null)) + # Filter invalid things + (lib.filterAttrs + (thingName: thing: + thing != null)) + # Handle if needed + (lib.mapAttrs handle) + ]; + }; +} diff --git a/modules/flake/modules/default.nix b/modules/flake/modules/default.nix index 098b792..0521066 100644 --- a/modules/flake/modules/default.nix +++ b/modules/flake/modules/default.nix @@ -2,66 +2,18 @@ let inherit (config.lib) - eq - and - hasFiles + createThings configuration-type-to-outputs-modules; in let # Modules helpers moduleTypes = ["nixos" "nix-on-droid" "nix-darwin" "home-manager" "flake"]; - createModules = baseDir: { passthru ? { inherit inputs; }, ... }: - lib.pipe baseDir [ - # Read given directory - builtins.readDir - # Map each entry to a module - (lib.mapAttrs' - (name: type: - let - # BUG: cannot use `append` because of `${self}` (not a path) - # moduleDir = lib.path.append baseDir "${name}"; - moduleDir = "${baseDir}/${name}"; - in - if and [ - (type == "directory") - (hasFiles [ "default.nix" ] (builtins.readDir moduleDir)) - ] then - # Classic module in a directory - lib.nameValuePair - name - (import moduleDir) - else if and [ - (type == "regular") - (lib.hasSuffix ".nix" name) - ] then - # Classic module in a file - lib.nameValuePair - (lib.removeSuffix ".nix" name) - (import moduleDir) - else - # Invalid module - lib.nameValuePair - name - null)) - # Filter invalid modules - (lib.filterAttrs - (moduleName: module: - module != null)) - # Passthru if needed - (lib.mapAttrs - (moduleName: module: - if and [ - (builtins.isFunction - module) - # FIXME: check for subset, not `eq` - (eq - (lib.pipe module [ builtins.functionArgs builtins.attrNames ]) - (lib.pipe passthru [ builtins.attrNames ])) - ] - then module passthru - else module)) - ]; + createModules = baseDir: + createThings { + inherit baseDir; + thingType = "module"; + }; in { options = let @@ -115,7 +67,7 @@ in default = lib.optionalAttrs config.flake.autoModules.${moduleType}.enable - (createModules config.flake.autoModules.${moduleType}.dir { }); + (createModules config.flake.autoModules.${moduleType}.dir); }; }; }; diff --git a/modules/flake/packages/default.nix b/modules/flake/packages/default.nix index 58f0eb2..2013daf 100644 --- a/modules/flake/packages/default.nix +++ b/modules/flake/packages/default.nix @@ -2,70 +2,18 @@ let inherit (config.lib) - eq - and - hasFiles; + createThings; in let - createPackages = baseDir: { passthru ? { inherit inputs; }, ... }: - lib.pipe baseDir [ - # Read given directory - builtins.readDir - # Map each entry to a package - (lib.mapAttrs' - (name: type: - let - packageDir = "${baseDir}/${name}"; - systems = let - systemsPath = "${baseDir}/${name}/systems.nix"; - in - # NOTE: If the package can restrict for which systems it wants to be built - if builtins.pathExists systemsPath - then import systemsPath - else lib.const true; - package = import packageDir; - result = { - inherit package systems; - }; - in - if and [ - (type == "directory") - (hasFiles [ "default.nix" ] (builtins.readDir packageDir)) - ] then - # NOTE: Classic package in a directory - lib.nameValuePair - name - result - else if and [ - (type == "regular") - (lib.hasSuffix ".nix" name) - ] then - # NOTE: Classic package in a file - lib.nameValuePair - (lib.removeSuffix ".nix" name) - result - else - # NOTE: Invalid package - lib.nameValuePair - name - null)) - # Filter invalid packages - (lib.filterAttrs - (packageName: package: - package != null)) - # Passthru if needed - (lib.mapAttrs - (packageName: package: - if and [ - (builtins.isFunction - package) - (eq - (lib.pipe package [ builtins.functionArgs builtins.attrNames ]) - (lib.pipe passthru [ builtins.attrNames ])) - ] - then package passthru - else package)) - ]; + createPackages = baseDir: + createThings { + inherit baseDir; + thingType = "package"; + raw = false; + extras.systems = { + default = lib.const true; + }; + }; in { options = let @@ -99,7 +47,7 @@ in default = lib.optionalAttrs config.flake.autoPackages.enable - (createPackages config.flake.autoPackages.dir { }); + (createPackages config.flake.autoPackages.dir); }; }; });