1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#pragma once
/**
 * @file
 * @brief Options for printing Nix values.
 */

#include <cstddef>
#include <limits>

namespace nix {

/**
 * How errors should be handled when printing values.
 */
enum class ErrorPrintBehavior {
    /**
     * Print the first line of the error in brackets: `«error: oh no!»`
     */
    Print,
    /**
     * Throw the error to the code that attempted to print the value, instead
     * of suppressing it it.
     */
    Throw,
    /**
     * Only throw the error if encountered at the top level of the expression.
     *
     * This will cause expressions like `builtins.throw "uh oh!"` to throw
     * errors, but will print attribute sets and other nested structures
     * containing values that error (like `nixpkgs`) normally.
     */
    ThrowTopLevel,
};

/**
 * Options for printing Nix values.
 */
struct PrintOptions
{
    /**
     * If true, output ANSI color sequences.
     */
    bool ansiColors = false;

    /**
     * If true, force values.
     */
    bool force = false;

    /**
     * Determines at what depth derivations start getting printed as paths.
     * When `force` is true and our print depth is greater than or equal to
     * this value, print derivations as `«derivation /nix/store/...»`
     * instead of as attribute sets.
     */
    size_t derivationPathDepth = std::numeric_limits<size_t>::max();

    /**
     * If true, track which values have been printed and skip them on
     * subsequent encounters. Useful for self-referential values.
     */
    bool trackRepeated = true;

    /**
     * Maximum depth to evaluate to.
     */
    size_t maxDepth = std::numeric_limits<size_t>::max();

    /**
     * Maximum number of attributes in attribute sets to print.
     *
     * Note that this is a limit for the entire print invocation, not for each
     * attribute set encountered.
     */
    size_t maxAttrs = std::numeric_limits<size_t>::max();

    /**
     * Maximum number of list items to print.
     *
     * Note that this is a limit for the entire print invocation, not for each
     * list encountered.
     */
    size_t maxListItems = std::numeric_limits<size_t>::max();

    /**
     * Maximum string length to print.
     */
    size_t maxStringLength = std::numeric_limits<size_t>::max();

    /**
     * Indentation width for pretty-printing.
     *
     * If set to 0 (the default), values are not pretty-printed.
     */
    size_t prettyIndent = 0;

    /**
     * How to handle errors encountered while printing values.
     */
    ErrorPrintBehavior errors = ErrorPrintBehavior::Print;

    /**
     * True if pretty-printing is enabled.
     */
    inline bool shouldPrettyPrint()
    {
        return prettyIndent > 0;
    }
};

/**
 * `PrintOptions` for unknown and therefore potentially large values in error messages,
 * to avoid printing "too much" output.
 */
static PrintOptions errorPrintOptions = PrintOptions {
    .ansiColors = true,
    .maxDepth = 10,
    .maxAttrs = 10,
    .maxListItems = 10,
    .maxStringLength = 1024,
};

}