diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 1a93a54fe..a79d7c482 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -123,7 +123,8 @@ struct NixRepl .force = true, .derivationPaths = true, .maxDepth = maxDepth, - .prettyIndent = 2 + .prettyIndent = 2, + .errors = ErrorPrintBehavior::ThrowTopLevel, }); } }; diff --git a/src/libexpr/print-options.hh b/src/libexpr/print-options.hh index 6c5e80c61..080ba26b8 100644 --- a/src/libexpr/print-options.hh +++ b/src/libexpr/print-options.hh @@ -8,6 +8,29 @@ 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. */ @@ -68,6 +91,11 @@ struct PrintOptions */ size_t prettyIndent = 0; + /** + * How to handle errors encountered while printing values. + */ + ErrorPrintBehavior errors = ErrorPrintBehavior::Print; + /** * True if pretty-printing is enabled. */ @@ -86,7 +114,7 @@ static PrintOptions errorPrintOptions = PrintOptions { .maxDepth = 10, .maxAttrs = 10, .maxListItems = 10, - .maxStringLength = 1024 + .maxStringLength = 1024, }; } diff --git a/src/libexpr/print.cc b/src/libexpr/print.cc index 9d280f623..f67e94750 100644 --- a/src/libexpr/print.cc +++ b/src/libexpr/print.cc @@ -271,25 +271,21 @@ private: void printDerivation(Value & v) { - try { - Bindings::iterator i = v.attrs->find(state.sDrvPath); - NixStringContext context; - std::string storePath; - if (i != v.attrs->end()) - storePath = state.store->printStorePath(state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation")); + Bindings::iterator i = v.attrs->find(state.sDrvPath); + NixStringContext context; + std::string storePath; + if (i != v.attrs->end()) + storePath = state.store->printStorePath(state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation")); - if (options.ansiColors) - output << ANSI_GREEN; - output << "«derivation"; - if (!storePath.empty()) { - output << " " << storePath; - } - output << "»"; - if (options.ansiColors) - output << ANSI_NORMAL; - } catch (Error & e) { - printError_(e); + if (options.ansiColors) + output << ANSI_GREEN; + output << "«derivation"; + if (!storePath.empty()) { + output << " " << storePath; } + output << "»"; + if (options.ansiColors) + output << ANSI_NORMAL; } bool shouldPrettyPrintAttrs(AttrVec & v) @@ -510,64 +506,68 @@ private: output.flush(); checkInterrupt(); - if (options.force) { - try { + try { + if (options.force) { state.forceValue(v, v.determinePos(noPos)); - } catch (Error & e) { - printError_(e); - return; } - } - switch (v.type()) { + switch (v.type()) { - case nInt: - printInt(v); - break; + case nInt: + printInt(v); + break; - case nFloat: - printFloat(v); - break; + case nFloat: + printFloat(v); + break; - case nBool: - printBool(v); - break; + case nBool: + printBool(v); + break; - case nString: - printString(v); - break; + case nString: + printString(v); + break; - case nPath: - printPath(v); - break; + case nPath: + printPath(v); + break; - case nNull: - printNull(); - break; + case nNull: + printNull(); + break; - case nAttrs: - printAttrs(v, depth); - break; + case nAttrs: + printAttrs(v, depth); + break; - case nList: - printList(v, depth); - break; + case nList: + printList(v, depth); + break; - case nFunction: - printFunction(v); - break; + case nFunction: + printFunction(v); + break; - case nThunk: - printThunk(v); - break; + case nThunk: + printThunk(v); + break; - case nExternal: - printExternal(v); - break; + case nExternal: + printExternal(v); + break; - default: - printUnknown(); - break; + default: + printUnknown(); + break; + } + } catch (Error & e) { + if (options.errors == ErrorPrintBehavior::Throw + || (options.errors == ErrorPrintBehavior::ThrowTopLevel + && depth == 0)) { + throw; + } + printError_(e); } }