···102102]
103103```
104104105105-Here is a less readable equivalent:
105105+Here is a simpler but less readable equivalent:
106106107107```nix
108108((import-tree.mapWith lib.traceVal).filtered (lib.hasInfix ".mod.")) ./modules
109109```
110110111111-### `import-tree.withLib`
111111+### `import-tree.filtered`
112112+113113+`filtered` takes a predicate function `path -> bool`. Only paths for which the filter returns `true` are selected:
112114113115> \[!NOTE\]
114114-> `withLib` is required prior to invocation of any of `.leafs` or `.pipeTo`.
115115-> Because with the use of those functions the implementation does not have access to a `lib` that is provided as a module argument.
116116+> Only files with suffix `.nix` are candidates.
116117117118```nix
118118-# import-tree.withLib : lib -> import-tree
119119+# import-tree.filtered : (path -> bool) -> import-tree
119120120120-import-tree.withLib pkgs.lib
121121+import-tree.filtered (lib.hasInfix ".mod.") ./some-dir
121122```
122123123123-### `import-tree.filtered`
124124+`filtered` can be applied multiple times, in which case only the files matching _all_ filters will be selected:
124125125125-`filtered` takes a predicate function `path -> bool`. `true` means included.
126126+```nix
127127+lib.pipe import-tree [
128128+ (i: i.filtered (lib.hasInfix ".mod."))
129129+ (i: i.filtered (lib.hasSuffix "default.nix"))
130130+ (i: i ./some-dir)
131131+]
132132+```
126133127127-> \[!NOTE\]
128128-> Only files with suffix `.nix` are candidates.
134134+Or, in a simpler but less readable way:
129135130136```nix
131131-# import-tree.filtered : (path -> bool) -> import-tree
132132-133133-import-tree.filtered (lib.hasInfix ".mod.") ./some-dir
137137+(import-tree.filtered (lib.hasInfix ".mod.")).filtered (lib.hasSuffix "default.nix") ./some-dir
134138```
135139136140### `import-tree.matching`
137141138138-`matching` takes a regular expression. The regex should match the full path for the path to be selected. Match is done with `lib.strings.match`;
142142+`matching` takes a regular expression. The regex should match the full path for the path to be selected. Matching is done with `builtins.match`.
139143140144```nix
141145# import-tree.matching : regex -> import-tree
···143147import-tree.matching ".*/[a-z]+@(foo|bar)\.nix" ./some-dir
144148```
145149150150+`matching` can be applied multiple times, in which case only the paths matching _all_ regex patterns will be selected, and can be combined with any number of `filtered`, in any order.
151151+146152### `import-tree.mapWith`
147153148154`mapWith` can be used to transform each path by providing a function.
149149-e.g. to convert the path into a module explicitly.
155155+156156+e.g. to convert the path into a module explicitly:
150157151158```nix
152159# import-tree.mapWith : (path -> any) -> import-tree
···158165})
159166```
160167168168+`mapWith` can be applied multiple times, composing the transformations:
169169+170170+```nix
171171+lib.pipe import-tree [
172172+ (i: i.mapWith (lib.removeSuffix ".nix"))
173173+ (i: i.mapWith builtins.stringLength)
174174+] ./some-dir
175175+```
176176+177177+The above example first removes the `.nix` suffix from all selected paths, then takes their lengths.
178178+179179+Or, in a simpler but less readable way:
180180+181181+```nix
182182+((import-tree.mapWith (lib.removeSuffix ".nix")).mapWith builtins.stringLength) ./some-dir
183183+```
184184+185185+`mapWith` can be combined with any number of `filtered` and `matching` calls, in any order, but the (composed) transformation is applied _after_ the filters, and only to the paths that match all of them.
186186+187187+### `import-tree.withLib`
188188+189189+> \[!NOTE\]
190190+> `withLib` is required prior to invocation of any of `.leafs` or `.pipeTo`.
191191+> Because with the use of those functions the implementation does not have access to a `lib` that is provided as a module argument.
192192+193193+```nix
194194+# import-tree.withLib : lib -> import-tree
195195+196196+import-tree.withLib pkgs.lib
197197+```
198198+161199### `import-tree.pipeTo`
162200163201`pipeTo` takes a function that will receive the list of paths.
···171209172210### `import-tree.leafs`
173211174174-`leafs` takes no arguments, it is equivalent to calling `import-tree.pipeTo lib.id`, that is, instead of producing a nix module, just return the list of results.
212212+`leafs` takes no arguments, it is equivalent to calling `import-tree.pipeTo lib.id`. That is, instead of producing a nix module, just return the list of results.
175213176214```nix
177215# import-tree.leafs : import-tree
···226264However, one advantage of this is that the dependency tree would be flat,
227265giving the final user's flake absolute control on what inputs are used,
228266without having to worry whether some third-party forgot to use `foo.inputs.nixpkgs.follows = "nixpkgs";` on any flake we are trying to re-use.
267267+268268+## Testing
269269+270270+`import-tree` uses [`checkmate`](https://github.com/vic/checkmate) for testing.
271271+272272+The test suite can be found in [`checkmate.nix`](checkmate.nix). To run it locally:
273273+274274+```sh
275275+nix flake check ./checkmate
276276+```