diff --git a/README.md b/README.md index d4ae7a7..aacfdf1 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Paths that have a component that begins with an underscore are ignored. ## API usage -The following goes recursively through the provided `./modules` path and imports the files whose names end with `.nix`. +The following goes recursively through `./modules` and imports all `.nix` files. ```nix {config, ...} { @@ -35,6 +35,10 @@ The following goes recursively through the provided `./modules` path and imports } ``` +For more advanced usage, `import-tree` can be configured via its builder API. +This means that the result of calling a function on an `import-tree` object +is itself another `import-tree` object. + ## Obtaining the API @@ -89,16 +93,34 @@ The following is valid usage: } ``` +As an special case, when the single argument given to an `import-tree` object is an +attribute-set *meaning it is _NOT_ a path or list of paths*, the `import-tree` object +assumes it is being imported as a module. This way, a pre-configured `import-tree` can +also be used directly in a list of module imports. + +This is useful for authors exposing pre-configured `import-tree`s that users can directly +add to their import list or continue configuring themselves using the API. + +```nix +let + # imagine this configured tree is actually provided by some flake or library. + # users can directly import it or continue using API methods on it. + configured-tree = import-tree.addPath [./a [./b]]; # paths are configured by library author. +in { + imports = [ configured-tree ]; # but then imported or further configured by the library user. +} +``` + ## Configurable behavior -`import-tree` functions with custom behavior can be obtained using a builder pattern. +`import-tree` objects with custom behavior can be obtained using a builder pattern. For example: ```nix lib.pipe import-tree [ - (i: i.mapWith lib.traceVal) # trace all paths + (i: i.mapWith lib.traceVal) # trace all paths. useful for debugging what is being imported. (i: i.filtered (lib.hasInfix ".mod.")) # filter nix files by some predicate - (i: i ./modules) # finally, call the configured callable with a path + (i: i ./modules) # finally, call the configured import-tree with a path ] ``` diff --git a/checkmate.nix b/checkmate.nix index 9db7cd7..883aa39 100644 --- a/checkmate.nix +++ b/checkmate.nix @@ -121,6 +121,24 @@ in oneElement inner.imports; expected = ./tree/x/y.nix; }; + + import-tree."test evaluates returned module as part of module-eval" = { + expr = + let + res = lib.modules.evalModules { modules = [ (it ./tree/modules) ]; }; + in + res.config.hello; + expected = "world"; + }; + + import-tree."test can itself be used as a module" = { + expr = + let + res = lib.modules.evalModules { modules = [ (it.addPath ./tree/modules) ]; }; + in + res.config.hello; + expected = "world"; + }; }; } diff --git a/default.nix b/default.nix index 448e68a..346dd79 100644 --- a/default.nix +++ b/default.nix @@ -58,18 +58,27 @@ let attrs: k: f: attrs // { ${k} = f attrs.${k}; }; - functor = self: perform self.config; + functor = + self: args: + let + imported-as-module = builtins.isAttrs args; + module = { + imports = [ (perform self.__config [ ]) ]; + }; + result = perform self.__config args; + in + if imported-as-module then module else result; callable = let - config = { + __config = { # Accumulated configuration mapf = (i: i); filterf = _: true; paths = [ ]; __functor = self: f: { - config = (f self); + __config = (f self); __functor = functor; # Configuration updates (accumulating) @@ -88,7 +97,7 @@ let }; }; in - config (c: c); + __config (c: c); in callable diff --git a/tree/modules/hello-option/mod.nix b/tree/modules/hello-option/mod.nix new file mode 100644 index 0000000..c44450c --- /dev/null +++ b/tree/modules/hello-option/mod.nix @@ -0,0 +1,7 @@ +{ lib, ... }: +{ + options.hello = lib.mkOption { + type = lib.types.str; + default = "goodbye"; + }; +} diff --git a/tree/modules/hello-world/mod.nix b/tree/modules/hello-world/mod.nix new file mode 100644 index 0000000..03a8e7a --- /dev/null +++ b/tree/modules/hello-world/mod.nix @@ -0,0 +1,3 @@ +{ + hello = "world"; +}