diff options
Diffstat (limited to 'nixpkgs/lib/generators.nix')
-rw-r--r-- | nixpkgs/lib/generators.nix | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/nixpkgs/lib/generators.nix b/nixpkgs/lib/generators.nix index 0cec4d2dd620..79ae9055ce3d 100644 --- a/nixpkgs/lib/generators.nix +++ b/nixpkgs/lib/generators.nix @@ -197,6 +197,30 @@ rec { */ toYAML = {}@args: toJSON args; + withRecursion = + args@{ + /* If this option is not null, the given value will stop evaluating at a certain depth */ + depthLimit + /* If this option is true, an error will be thrown, if a certain given depth is exceeded */ + , throwOnDepthLimit ? true + }: + assert builtins.isInt depthLimit; + let + transform = depth: + if depthLimit != null && depth > depthLimit then + if throwOnDepthLimit + then throw "Exceeded maximum eval-depth limit of ${toString depthLimit} while trying to evaluate with `generators.withRecursion'!" + else const "<unevaluated>" + else id; + mapAny = with builtins; depth: v: + let + evalNext = x: mapAny (depth + 1) (transform (depth + 1) x); + in + if isAttrs v then mapAttrs (const evalNext) v + else if isList v then map evalNext v + else transform (depth + 1) v; + in + mapAny 0; /* Pretty print a value, akin to `builtins.trace`. * Should probably be a builtin as well. @@ -208,7 +232,8 @@ rec { allowPrettyValues ? false, /* If this option is true, the output is indented with newlines for attribute sets and lists */ multiline ? true - }@args: let + }@args: + let go = indent: v: with builtins; let isPath = v: typeOf v == "path"; introSpace = if multiline then "\n${indent} " else " "; |