summaryrefslogtreecommitdiffstats
path: root/lib/generators.nix
diff options
context:
space:
mode:
authorMaximilian Bosch <maximilian@mbosch.me>2021-08-26 00:28:49 +0200
committerMaximilian Bosch <maximilian@mbosch.me>2021-08-26 00:28:49 +0200
commit5773ae93f75cfd504d7971c1b26955fa50a00744 (patch)
treed5f19ba068e4efee4f711e1dad969cf3b3c61470 /lib/generators.nix
parentb6d3c9f821b704fbfb68d20a76520fa9e160df36 (diff)
lib/generators: move limit detection into `withRecursion`
As suggested in #131205. Now it's possible to pretty-print a value with `lib.generators` like this: with lib.generators; toPretty { } (withRecursion { depthLimit = 10; } /* arbitrarily complex value */) Also, this can be used for any other pretty-printer now if needed.
Diffstat (limited to 'lib/generators.nix')
-rw-r--r--lib/generators.nix45
1 files changed, 30 insertions, 15 deletions
diff --git a/lib/generators.nix b/lib/generators.nix
index b1639b677f65..9271b9746aee 100644
--- a/lib/generators.nix
+++ b/lib/generators.nix
@@ -195,6 +195,30 @@ rec {
*/
toYAML = {}@args: toJSON args;
+ withRecursion =
+ args@{
+ /* If this option is not null, `toPretty` 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 pretty-print 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.
@@ -205,23 +229,14 @@ rec {
(This means fn is type Val -> String.) */
allowPrettyValues ? false,
/* If this option is true, the output is indented with newlines for attribute sets and lists */
- multiline ? true,
- /* If this option is not null, `toPretty` will stop evaluating at a certain depth */
- depthLimit ? null,
- /* If this option is true, an error will be thrown, if a certain given depth is exceeded */
- throwOnDepthLimit ? false
+ multiline ? true
}@args:
- assert depthLimit != null -> builtins.isInt depthLimit;
- assert throwOnDepthLimit -> depthLimit != null;
let
- go = depth: indent: v: with builtins;
+ go = indent: v: with builtins;
let isPath = v: typeOf v == "path";
introSpace = if multiline then "\n${indent} " else " ";
outroSpace = if multiline then "\n${indent}" else " ";
- in if depthLimit != null && depth > depthLimit then
- if throwOnDepthLimit then throw "Exceeded maximum eval-depth limit of ${toString depthLimit} while trying to pretty-print with `generators.toPretty'!"
- else "<unevaluated>"
- else if isInt v then toString v
+ in if isInt v then toString v
else if isFloat v then "~${toString v}"
else if isString v then
let
@@ -243,7 +258,7 @@ rec {
else if isList v then
if v == [] then "[ ]"
else "[" + introSpace
- + libStr.concatMapStringsSep introSpace (go (depth + 1) (indent + " ")) v
+ + libStr.concatMapStringsSep introSpace (go (indent + " ")) v
+ outroSpace + "]"
else if isFunction v then
let fna = lib.functionArgs v;
@@ -262,10 +277,10 @@ rec {
else "{" + introSpace
+ libStr.concatStringsSep introSpace (libAttr.mapAttrsToList
(name: value:
- "${libStr.escapeNixIdentifier name} = ${go (depth + 1) (indent + " ") value};") v)
+ "${libStr.escapeNixIdentifier name} = ${go (indent + " ") value};") v)
+ outroSpace + "}"
else abort "generators.toPretty: should never happen (v = ${v})";
- in go 0 "";
+ in go "";
# PLIST handling
toPlist = {}: v: let