Move escapeString
to its own file
Change-Id: Ie5c954ec73c46c9d3c679ef99a83a29cc7a08352
This commit is contained in:
parent
5a54b0a20c
commit
a5a25894c1
10 changed files with 142 additions and 74 deletions
|
@ -4,6 +4,7 @@
|
||||||
#include "symbol-table.hh"
|
#include "symbol-table.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "print.hh"
|
#include "print.hh"
|
||||||
|
#include "escape-string.hh"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ void ExprFloat::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
|
|
||||||
void ExprString::show(const SymbolTable & symbols, std::ostream & str) const
|
void ExprString::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
printLiteralString(str, s);
|
escapeString(str, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprPath::show(const SymbolTable & symbols, std::ostream & str) const
|
void ExprPath::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "print.hh"
|
#include "print.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "signals.hh"
|
#include "signals.hh"
|
||||||
|
#include "escape-string.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ void printAmbiguous(
|
||||||
printLiteralBool(str, v.boolean);
|
printLiteralBool(str, v.boolean);
|
||||||
break;
|
break;
|
||||||
case nString:
|
case nString:
|
||||||
printLiteralString(str, v.string.s);
|
escapeString(str, v.string.s);
|
||||||
break;
|
break;
|
||||||
case nPath:
|
case nPath:
|
||||||
str << v.path().to_string(); // !!! escaping?
|
str << v.path().to_string(); // !!! escaping?
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "escape-string.hh"
|
||||||
#include "print.hh"
|
#include "print.hh"
|
||||||
#include "ansicolor.hh"
|
#include "ansicolor.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
@ -11,57 +12,6 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
void printElided(
|
|
||||||
std::ostream & output,
|
|
||||||
unsigned int value,
|
|
||||||
const std::string_view single,
|
|
||||||
const std::string_view plural,
|
|
||||||
bool ansiColors)
|
|
||||||
{
|
|
||||||
if (ansiColors)
|
|
||||||
output << ANSI_FAINT;
|
|
||||||
output << "«";
|
|
||||||
pluralize(output, value, single, plural);
|
|
||||||
output << " elided»";
|
|
||||||
if (ansiColors)
|
|
||||||
output << ANSI_NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
printLiteralString(std::ostream & str, const std::string_view string, size_t maxLength, bool ansiColors)
|
|
||||||
{
|
|
||||||
size_t charsPrinted = 0;
|
|
||||||
if (ansiColors)
|
|
||||||
str << ANSI_MAGENTA;
|
|
||||||
str << "\"";
|
|
||||||
for (auto i = string.begin(); i != string.end(); ++i) {
|
|
||||||
if (charsPrinted >= maxLength) {
|
|
||||||
str << "\" ";
|
|
||||||
printElided(str, string.length() - charsPrinted, "byte", "bytes", ansiColors);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*i == '\"' || *i == '\\') str << "\\" << *i;
|
|
||||||
else if (*i == '\n') str << "\\n";
|
|
||||||
else if (*i == '\r') str << "\\r";
|
|
||||||
else if (*i == '\t') str << "\\t";
|
|
||||||
else if (*i == '$' && *(i+1) == '{') str << "\\" << *i;
|
|
||||||
else str << *i;
|
|
||||||
charsPrinted++;
|
|
||||||
}
|
|
||||||
str << "\"";
|
|
||||||
if (ansiColors)
|
|
||||||
str << ANSI_NORMAL;
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
printLiteralString(std::ostream & str, const std::string_view string)
|
|
||||||
{
|
|
||||||
return printLiteralString(str, string, std::numeric_limits<size_t>::max(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &
|
std::ostream &
|
||||||
printLiteralBool(std::ostream & str, bool boolean)
|
printLiteralBool(std::ostream & str, bool boolean)
|
||||||
{
|
{
|
||||||
|
@ -93,7 +43,7 @@ printIdentifier(std::ostream & str, std::string_view s) {
|
||||||
else {
|
else {
|
||||||
char c = s[0];
|
char c = s[0];
|
||||||
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')) {
|
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')) {
|
||||||
printLiteralString(str, s);
|
escapeString(str, s);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
for (auto c : s)
|
for (auto c : s)
|
||||||
|
@ -101,7 +51,7 @@ printIdentifier(std::ostream & str, std::string_view s) {
|
||||||
(c >= 'A' && c <= 'Z') ||
|
(c >= 'A' && c <= 'Z') ||
|
||||||
(c >= '0' && c <= '9') ||
|
(c >= '0' && c <= '9') ||
|
||||||
c == '_' || c == '\'' || c == '-')) {
|
c == '_' || c == '\'' || c == '-')) {
|
||||||
printLiteralString(str, s);
|
escapeString(str, s);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
str << s;
|
str << s;
|
||||||
|
@ -129,7 +79,7 @@ printAttributeName(std::ostream & str, std::string_view name) {
|
||||||
if (isVarName(name))
|
if (isVarName(name))
|
||||||
str << name;
|
str << name;
|
||||||
else
|
else
|
||||||
printLiteralString(str, name);
|
escapeString(str, name);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +198,13 @@ private:
|
||||||
|
|
||||||
void printString(Value & v)
|
void printString(Value & v)
|
||||||
{
|
{
|
||||||
printLiteralString(output, v.string.s, options.maxStringLength, options.ansiColors);
|
// NB: Non-printing characters won't be escaped.
|
||||||
|
escapeString(
|
||||||
|
output,
|
||||||
|
v.string.s,
|
||||||
|
options.maxStringLength,
|
||||||
|
options.ansiColors
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printPath(Value & v)
|
void printPath(Value & v)
|
||||||
|
|
|
@ -11,28 +11,13 @@
|
||||||
|
|
||||||
#include "fmt.hh"
|
#include "fmt.hh"
|
||||||
#include "print-options.hh"
|
#include "print-options.hh"
|
||||||
|
#include "print-elided.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
class EvalState;
|
class EvalState;
|
||||||
struct Value;
|
struct Value;
|
||||||
|
|
||||||
/**
|
|
||||||
* Print a string as a Nix string literal.
|
|
||||||
*
|
|
||||||
* Quotes and fairly minimal escaping are added.
|
|
||||||
*
|
|
||||||
* @param o The output stream to print to
|
|
||||||
* @param s The logical string
|
|
||||||
*/
|
|
||||||
std::ostream & printLiteralString(std::ostream & o, std::string_view s);
|
|
||||||
inline std::ostream & printLiteralString(std::ostream & o, const char * s) {
|
|
||||||
return printLiteralString(o, std::string_view(s));
|
|
||||||
}
|
|
||||||
inline std::ostream & printLiteralString(std::ostream & o, const std::string & s) {
|
|
||||||
return printLiteralString(o, std::string_view(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Print `true` or `false`. */
|
/** Print `true` or `false`. */
|
||||||
std::ostream & printLiteralBool(std::ostream & o, bool b);
|
std::ostream & printLiteralBool(std::ostream & o, bool b);
|
||||||
|
|
||||||
|
|
40
src/libutil/escape-string.cc
Normal file
40
src/libutil/escape-string.cc
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include <iomanip>
|
||||||
|
#include <ostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "ansicolor.hh"
|
||||||
|
#include "escape-char.hh"
|
||||||
|
#include "english.hh"
|
||||||
|
#include "escape-string.hh"
|
||||||
|
#include "print-elided.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
std::ostream &
|
||||||
|
escapeString(std::ostream & str, const std::string_view string, size_t maxLength, bool ansiColors)
|
||||||
|
{
|
||||||
|
size_t charsPrinted = 0;
|
||||||
|
if (ansiColors)
|
||||||
|
str << ANSI_MAGENTA;
|
||||||
|
str << "\"";
|
||||||
|
for (auto i = string.begin(); i != string.end(); ++i) {
|
||||||
|
if (charsPrinted >= maxLength) {
|
||||||
|
str << "\" ";
|
||||||
|
printElided(str, string.length() - charsPrinted, "byte", "bytes", ansiColors);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
if (*i == '\"' || *i == '\\') str << "\\" << *i;
|
||||||
|
else if (*i == '\n') str << "\\n";
|
||||||
|
else if (*i == '\r') str << "\\r";
|
||||||
|
else if (*i == '\t') str << "\\t";
|
||||||
|
else if (*i == '$' && *(i+1) == '{') str << "\\" << *i;
|
||||||
|
else str << *i;
|
||||||
|
charsPrinted++;
|
||||||
|
}
|
||||||
|
str << "\"";
|
||||||
|
if (ansiColors)
|
||||||
|
str << ANSI_NORMAL;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // namespace nix
|
34
src/libutil/escape-string.hh
Normal file
34
src/libutil/escape-string.hh
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape a string for output.
|
||||||
|
*
|
||||||
|
* With default optional parameters, the output string will round-trip through
|
||||||
|
* the Nix evaluator (i.e. you can copy/paste this function's output into the
|
||||||
|
* REPL and have it evaluate as the string that got passed in).
|
||||||
|
*
|
||||||
|
* With non-default optional parameters, the output string will be
|
||||||
|
* human-readable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::ostream & escapeString(
|
||||||
|
std::ostream & output,
|
||||||
|
const std::string_view string,
|
||||||
|
size_t maxLength = std::numeric_limits<size_t>::max(),
|
||||||
|
bool ansiColors = false
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape a string for output, writing the escaped result to a new string.
|
||||||
|
*/
|
||||||
|
inline std::ostream & escapeString(std::ostream & output, const char * string)
|
||||||
|
{
|
||||||
|
return escapeString(output, std::string_view(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nix
|
|
@ -9,6 +9,7 @@ libutil_sources = files(
|
||||||
'english.cc',
|
'english.cc',
|
||||||
'error.cc',
|
'error.cc',
|
||||||
'escape-char.cc',
|
'escape-char.cc',
|
||||||
|
'escape-string.cc',
|
||||||
'exit.cc',
|
'exit.cc',
|
||||||
'experimental-features.cc',
|
'experimental-features.cc',
|
||||||
'filesystem.cc',
|
'filesystem.cc',
|
||||||
|
@ -19,6 +20,7 @@ libutil_sources = files(
|
||||||
'logging.cc',
|
'logging.cc',
|
||||||
'namespaces.cc',
|
'namespaces.cc',
|
||||||
'position.cc',
|
'position.cc',
|
||||||
|
'print-elided.cc',
|
||||||
'references.cc',
|
'references.cc',
|
||||||
'serialise.cc',
|
'serialise.cc',
|
||||||
'shlex.cc',
|
'shlex.cc',
|
||||||
|
@ -52,6 +54,7 @@ libutil_headers = files(
|
||||||
'english.hh',
|
'english.hh',
|
||||||
'error.hh',
|
'error.hh',
|
||||||
'escape-char.hh',
|
'escape-char.hh',
|
||||||
|
'escape-string.hh',
|
||||||
'exit.hh',
|
'exit.hh',
|
||||||
'experimental-features.hh',
|
'experimental-features.hh',
|
||||||
'experimental-features-json.hh',
|
'experimental-features-json.hh',
|
||||||
|
@ -70,6 +73,7 @@ libutil_headers = files(
|
||||||
'namespaces.hh',
|
'namespaces.hh',
|
||||||
'pool.hh',
|
'pool.hh',
|
||||||
'position.hh',
|
'position.hh',
|
||||||
|
'print-elided.hh',
|
||||||
'ref.hh',
|
'ref.hh',
|
||||||
'references.hh',
|
'references.hh',
|
||||||
'regex-combinators.hh',
|
'regex-combinators.hh',
|
||||||
|
|
23
src/libutil/print-elided.cc
Normal file
23
src/libutil/print-elided.cc
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#include "print-elided.hh"
|
||||||
|
#include "ansicolor.hh"
|
||||||
|
#include "english.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
void printElided(
|
||||||
|
std::ostream & output,
|
||||||
|
unsigned int value,
|
||||||
|
const std::string_view single,
|
||||||
|
const std::string_view plural,
|
||||||
|
bool ansiColors)
|
||||||
|
{
|
||||||
|
if (ansiColors)
|
||||||
|
output << ANSI_FAINT;
|
||||||
|
output << "«";
|
||||||
|
pluralize(output, value, single, plural);
|
||||||
|
output << " elided»";
|
||||||
|
if (ansiColors)
|
||||||
|
output << ANSI_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
src/libutil/print-elided.hh
Normal file
23
src/libutil/print-elided.hh
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print an `«... elided»` placeholder.
|
||||||
|
*
|
||||||
|
* Arguments are forwarded to `pluralize`.
|
||||||
|
*
|
||||||
|
* If `ansiColors` is set, the output will be wrapped in `ANSI_FAINT`.
|
||||||
|
*/
|
||||||
|
void printElided(
|
||||||
|
std::ostream & output,
|
||||||
|
unsigned int value,
|
||||||
|
const std::string_view single,
|
||||||
|
const std::string_view plural,
|
||||||
|
bool ansiColors
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
#include "cli-literate-parser.hh"
|
#include "cli-literate-parser.hh"
|
||||||
|
#include "escape-string.hh"
|
||||||
#include "libexpr/print.hh"
|
#include "libexpr/print.hh"
|
||||||
#include "escape-char.hh"
|
#include "escape-char.hh"
|
||||||
#include "types.hh"
|
#include "types.hh"
|
||||||
|
@ -41,7 +42,7 @@ auto CLILiterateParser::Node::print() const -> std::string
|
||||||
s << "Output ";
|
s << "Output ";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printLiteralString(s, this->text);
|
escapeString(s, this->text);
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue