2021-12-20 23:48:26 +00:00
|
|
|
{ lib }: { config, folder, inputs, ... }@args: with lib; let
|
2021-12-20 23:51:02 +00:00
|
|
|
# Made by kat witch (kittywitch)
|
2021-12-21 15:26:21 +00:00
|
|
|
pureTreeGrab = { base, path }:
|
|
|
|
let
|
|
|
|
realPath = toString path;
|
|
|
|
dirContents = builtins.readDir path;
|
|
|
|
isDirectory = entry: dirContents."${entry}" == "directory";
|
|
|
|
isHidden = entry: hasPrefix "." entry;
|
|
|
|
isDir = entry: _: (isDirectory entry) && !(isHidden entry);
|
|
|
|
directories = filterAttrs isDir dirContents;
|
|
|
|
isNixFile = entry: _:
|
|
|
|
let
|
|
|
|
result = builtins.match "(.*)\\.nix" entry;
|
|
|
|
in
|
|
|
|
result != null && builtins.length result > 0;
|
|
|
|
nixFiles = filterAttrs isNixFile dirContents;
|
|
|
|
getPath = entry: "${realPath}/${entry}";
|
|
|
|
getPaths = entries: mapAttrs'
|
|
|
|
(n: v:
|
|
|
|
nameValuePair (removeSuffix ".nix" n) (getPath n)
|
|
|
|
)
|
|
|
|
entries;
|
|
|
|
nixFilePaths = getPaths nixFiles;
|
|
|
|
dirPaths = getPaths directories;
|
|
|
|
recursedPaths = mapAttrs
|
|
|
|
(_: fullPath: pureTreeGrab {
|
|
|
|
inherit base;
|
|
|
|
path = fullPath;
|
|
|
|
})
|
|
|
|
dirPaths;
|
|
|
|
contents = recursedPaths // nixFilePaths;
|
|
|
|
in
|
|
|
|
contents;
|
2021-12-20 23:48:26 +00:00
|
|
|
configTreeStruct = { config, ... }: {
|
|
|
|
options.treeConfig = mkOption {
|
|
|
|
type = with types; attrsOf (submodule ({ name, options, config, ... }: {
|
|
|
|
options = {
|
|
|
|
evaluateDefault = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
description = "Replace the contents of this branch or leaf with those provided by the evaluation of default.nix.";
|
|
|
|
default = false;
|
|
|
|
};
|
|
|
|
aliasDefault = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
description = "Replace the contents of this branch or leaf with the default.nix.";
|
|
|
|
default = false;
|
|
|
|
};
|
|
|
|
excludes = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
description = "Exclude files or folders from the recurser.";
|
2021-12-21 15:26:21 +00:00
|
|
|
default = [ ];
|
2021-12-20 23:48:26 +00:00
|
|
|
};
|
|
|
|
functor = {
|
|
|
|
enable = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
description = "Provide a functor for the path provided";
|
|
|
|
default = false;
|
|
|
|
};
|
|
|
|
external = mkOption {
|
|
|
|
type = types.listOf types.unspecified;
|
|
|
|
description = "Add external imports into the functor.";
|
2021-12-21 15:26:21 +00:00
|
|
|
default = [ ];
|
2021-12-20 23:48:26 +00:00
|
|
|
};
|
|
|
|
excludes = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
description = "Exclude files or folders from the functor.";
|
2021-12-21 15:26:21 +00:00
|
|
|
default = [ ];
|
2021-12-20 23:48:26 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
config.treeConfig = {
|
2021-12-21 15:26:21 +00:00
|
|
|
"*" = { };
|
2021-12-20 23:48:26 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
configTree.treeConfig = config;
|
|
|
|
configTreeModule = (evalModules {
|
|
|
|
modules = [
|
|
|
|
configTreeStruct
|
|
|
|
configTree
|
|
|
|
];
|
|
|
|
}).config.treeConfig;
|
2021-12-21 15:26:21 +00:00
|
|
|
mapAttrsRecursive = f: set:
|
|
|
|
let
|
|
|
|
recurse = path: set:
|
|
|
|
let
|
|
|
|
g = name: value:
|
|
|
|
if isAttrs value
|
|
|
|
then f (path ++ [ name ]) (recurse (path ++ [ name ]) value)
|
|
|
|
else f (path ++ [ name ]) value;
|
|
|
|
in
|
|
|
|
mapAttrs g set;
|
|
|
|
in
|
|
|
|
recurse [ ] set;
|
2021-12-20 23:48:26 +00:00
|
|
|
getPathString = path: concatStringsSep "/" path;
|
|
|
|
getConfig = path: default: configTreeModule.${getPathString path} or default;
|
|
|
|
revtail = path: sublist 0 (length path - 1) path;
|
2021-12-21 15:26:21 +00:00
|
|
|
getConfigRecursive = path:
|
|
|
|
let
|
|
|
|
parentPath = revtail path;
|
|
|
|
in
|
|
|
|
getConfig (path ++ singleton "*") (getConfigRecursive parentPath);
|
|
|
|
processLeaves = tree: config: mapAttrsRecursive
|
|
|
|
(path: value:
|
|
|
|
let
|
|
|
|
pathString = getPathString path;
|
|
|
|
leafConfig = getConfig path (getConfigRecursive (revtail path));
|
|
|
|
processConfig = path: value:
|
|
|
|
let
|
|
|
|
processFunctor = prev: prev // {
|
|
|
|
__functor = self: { ... }: {
|
|
|
|
imports = attrValues (removeAttrs prev leafConfig.functor.excludes) ++ leafConfig.functor.external;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
processAliasDefault = prev: prev.default;
|
|
|
|
processDefault = prev: import prev.default (args // {
|
|
|
|
inherit lib;
|
|
|
|
tree = {
|
|
|
|
prev = removeAttrs prev (singleton "default");
|
|
|
|
pure = pureTree;
|
|
|
|
impure = impureTree;
|
|
|
|
};
|
|
|
|
});
|
|
|
|
processExcludes = prev: removeAttrs prev leafConfig.excludes;
|
|
|
|
processes = optionals (isAttrs value) (
|
|
|
|
optional (leafConfig.excludes != [ ]) processExcludes
|
|
|
|
++ optional leafConfig.evaluateDefault processDefault
|
|
|
|
++ optional leafConfig.aliasDefault processAliasDefault
|
|
|
|
++ optional leafConfig.functor.enable processFunctor
|
|
|
|
);
|
|
|
|
in
|
|
|
|
pipe value processes;
|
|
|
|
in
|
|
|
|
processConfig path value)
|
|
|
|
tree;
|
2021-12-20 23:48:26 +00:00
|
|
|
pureTree = pureTreeGrab { base = folder; path = folder; };
|
|
|
|
impureTree = processLeaves pureTree configTreeModule;
|
2021-12-21 15:26:21 +00:00
|
|
|
in
|
|
|
|
{
|
2021-12-20 23:48:26 +00:00
|
|
|
config = configTreeModule;
|
|
|
|
pure = pureTree;
|
|
|
|
impure = impureTree;
|
|
|
|
}
|