diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 0d7ad63a7..ee3a6e268 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -412,6 +412,7 @@ ProcessLineResult NixRepl::processLine(std::string line) << " :l, :load Load Nix expression and add it to scope\n" << " :lf, :load-flake Load Nix flake and add it to scope\n" << " :p, :print Evaluate and print expression recursively\n" + << " Strings are printed directly, without escaping.\n" << " :q, :quit Exit nix-repl\n" << " :r, :reload Reload all files\n" << " :sh Build dependencies of derivation, then start\n" @@ -619,7 +620,11 @@ ProcessLineResult NixRepl::processLine(std::string line) else if (command == ":p" || command == ":print") { Value v; evalString(arg, v); - printValue(std::cout, v); + if (v.type() == nString) { + std::cout << v.string.s; + } else { + printValue(std::cout, v); + } std::cout << std::endl; } diff --git a/tests/functional/repl_characterization/data/repl_printing.test b/tests/functional/repl_characterization/data/repl_printing.test new file mode 100644 index 000000000..1206281e7 --- /dev/null +++ b/tests/functional/repl_characterization/data/repl_printing.test @@ -0,0 +1,92 @@ +Printing a string with escapes in it will render as a string normally. + + nix-repl> "meow\n\nmeowmeowmeow" + "meow\n\nmeowmeowmeow" + +But with :p on the string itself it will print it literally to the output. + + nix-repl> :p "meow\n\nmeowmeowmeow" + meow + + meowmeowmeow + + nix-repl> builtins.listToAttrs (builtins.genList (x: { name = "meow${toString x}"; value = { meow = { inherit x; s = "meowmeow\n\n${toString x}"; }; }; }) 10) + { + meow0 = { ... }; + meow1 = { ... }; + meow2 = { ... }; + meow3 = { ... }; + meow4 = { ... }; + meow5 = { ... }; + meow6 = { ... }; + meow7 = { ... }; + meow8 = { ... }; + meow9 = { ... }; + } + +Also, :p will expand attrs, but it will leave the strings escaped as normal if +they aren't the top level item being printed. + + nix-repl> :p builtins.listToAttrs (builtins.genList (x: { name = "meow${toString x}"; value = { meow = { inherit x; s = "meowmeow\n\n${toString x}"; }; }; }) 10) + { + meow0 = { + meow = { + s = "meowmeow\n\n0"; + x = 0; + }; + }; + meow1 = { + meow = { + s = "meowmeow\n\n1"; + x = 1; + }; + }; + meow2 = { + meow = { + s = "meowmeow\n\n2"; + x = 2; + }; + }; + meow3 = { + meow = { + s = "meowmeow\n\n3"; + x = 3; + }; + }; + meow4 = { + meow = { + s = "meowmeow\n\n4"; + x = 4; + }; + }; + meow5 = { + meow = { + s = "meowmeow\n\n5"; + x = 5; + }; + }; + meow6 = { + meow = { + s = "meowmeow\n\n6"; + x = 6; + }; + }; + meow7 = { + meow = { + s = "meowmeow\n\n7"; + x = 7; + }; + }; + meow8 = { + meow = { + s = "meowmeow\n\n8"; + x = 8; + }; + }; + meow9 = { + meow = { + s = "meowmeow\n\n9"; + x = 9; + }; + }; + } diff --git a/tests/functional/repl_characterization/repl_characterization.cc b/tests/functional/repl_characterization/repl_characterization.cc index fa5a7ba74..ae4d4030f 100644 --- a/tests/functional/repl_characterization/repl_characterization.cc +++ b/tests/functional/repl_characterization/repl_characterization.cc @@ -185,5 +185,6 @@ REPL_TEST(regression_9917); REPL_TEST(regression_9918); REPL_TEST(regression_l145); REPL_TEST(stack_vars); +REPL_TEST(repl_printing); }; // namespace nix diff --git a/tests/unit/libexpr-support/tests/libexpr.hh b/tests/unit/libexpr-support/tests/libexpr.hh index b8e65aafe..4055784ca 100644 --- a/tests/unit/libexpr-support/tests/libexpr.hh +++ b/tests/unit/libexpr-support/tests/libexpr.hh @@ -71,7 +71,7 @@ namespace nix { if (arg.type() != nString) { return false; } - return std::string_view(arg.string.s) == s; + return std::string_view(arg.string.s) == std::string_view(s); } MATCHER_P(IsIntEq, v, fmt("The string is equal to \"%1%\"", v)) { @@ -106,7 +106,7 @@ namespace nix { if (arg.type() != nPath) { *result_listener << "Expected a path got " << arg.type(); return false; - } else if (std::string_view(arg.string.s) != p) { + } else if (std::string_view(arg._path) != p) { *result_listener << "Expected a path that equals \"" << p << "\" but got: " << arg.string.s; return false; }