aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/build.cc2
-rw-r--r--src/libutil/logging.cc2
-rw-r--r--src/libutil/util.cc67
-rw-r--r--src/libutil/util.hh10
-rw-r--r--src/nix/progress-bar.cc43
-rw-r--r--tests/misc.sh2
6 files changed, 54 insertions, 72 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 5be7ce60d..9f669f7e4 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -3428,7 +3428,7 @@ void DerivationGoal::flushLine()
else {
if (settings.verboseBuild &&
(settings.printRepeatedBuilds || curRound == 1))
- printError(filterANSIEscapes(currentLogLine, true));
+ printError(currentLogLine);
else {
logTail.push_back(currentLogLine);
if (logTail.size() > settings.logLines) logTail.pop_front();
diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc
index 6924e0080..27a631a37 100644
--- a/src/libutil/logging.cc
+++ b/src/libutil/logging.cc
@@ -44,7 +44,7 @@ public:
prefix = std::string("<") + c + ">";
}
- writeToStderr(prefix + (tty ? fs.s : filterANSIEscapes(fs.s)) + "\n");
+ writeToStderr(prefix + filterANSIEscapes(fs.s) + "\n");
}
void startActivity(ActivityId act, Verbosity lvl, ActivityType type,
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 272997397..f7a12d21b 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -1178,36 +1178,51 @@ void ignoreException()
}
-string filterANSIEscapes(const string & s, bool nixOnly)
-{
- string t, r;
- enum { stTop, stEscape, stCSI } state = stTop;
- for (auto c : s) {
- if (state == stTop) {
- if (c == '\e') {
- state = stEscape;
- r = c;
- } else
- t += c;
- } else if (state == stEscape) {
- r += c;
- if (c == '[')
- state = stCSI;
- else {
- t += r;
- state = stTop;
+std::string filterANSIEscapes(const std::string & s, unsigned int width)
+{
+ std::string t, e;
+ size_t w = 0;
+ auto i = s.begin();
+
+ while (w < (size_t) width && i != s.end()) {
+
+ if (*i == '\e') {
+ std::string e;
+ e += *i++;
+ char last = 0;
+
+ if (i != s.end() && *i == '[') {
+ e += *i++;
+ // eat parameter bytes
+ while (i != s.end() && *i >= 0x30 && *i <= 0x3f) e += *i++;
+ // eat intermediate bytes
+ while (i != s.end() && *i >= 0x20 && *i <= 0x2f) e += *i++;
+ // eat final byte
+ if (i != s.end() && *i >= 0x40 && *i <= 0x7e) e += last = *i++;
+ } else {
+ if (i != s.end() && *i >= 0x40 && *i <= 0x5f) e += *i++;
}
- } else {
- r += c;
- if (c >= 0x40 && c <= 0x7e) {
- if (nixOnly && (c != 'p' && c != 'q' && c != 's' && c != 'a' && c != 'b'))
- t += r;
- state = stTop;
- r.clear();
+
+ if (last == 'm')
+ t += e;
+ }
+
+ else if (*i == '\t') {
+ i++; t += ' '; w++;
+ while (w < (size_t) width && w % 8) {
+ t += ' '; w++;
}
}
+
+ else if (*i == '\r')
+ // do nothing for now
+ ;
+
+ else {
+ t += *i++; w++;
+ }
}
- t += r;
+
return t;
}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 75eb97515..47e02bc89 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -388,10 +388,12 @@ void ignoreException();
#define ANSI_BLUE "\e[34;1m"
-/* Filter out ANSI escape codes from the given string. If ‘nixOnly’ is
- set, only filter escape codes generated by Nixpkgs' stdenv (used to
- denote nesting etc.). */
-string filterANSIEscapes(const string & s, bool nixOnly = false);
+/* Truncate a string to 'width' printable characters. Certain ANSI
+ escape sequences (such as colour setting) are copied but not
+ included in the character count. Other ANSI escape sequences are
+ filtered. Also, tabs are expanded to spaces. */
+std::string filterANSIEscapes(const std::string & s,
+ unsigned int width = std::numeric_limits<unsigned int>::max());
/* Base64 encoding/decoding. */
diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc
index 252d12c5d..e6553c06f 100644
--- a/src/nix/progress-bar.cc
+++ b/src/nix/progress-bar.cc
@@ -23,44 +23,6 @@ static uint64_t getI(const std::vector<Logger::Field> & fields, size_t n)
return fields[n].i;
}
-/* Truncate a string to 'width' printable characters. ANSI escape
- sequences are copied but not included in the character count. Also,
- tabs are expanded to spaces. */
-static std::string ansiTruncate(const std::string & s, int width)
-{
- if (width <= 0) return s;
-
- std::string t;
- size_t w = 0;
- auto i = s.begin();
-
- while (w < (size_t) width && i != s.end()) {
- if (*i == '\e') {
- t += *i++;
- if (i != s.end() && *i == '[') {
- t += *i++;
- while (i != s.end() && (*i < 0x40 || *i > 0x7e)) {
- t += *i++;
- }
- if (i != s.end()) t += *i++;
- }
- }
-
- else if (*i == '\t') {
- t += ' '; w++;
- while (w < (size_t) width && w & 8) {
- t += ' '; w++;
- }
- }
-
- else {
- t += *i++; w++;
- }
- }
-
- return t;
-}
-
class ProgressBar : public Logger
{
private:
@@ -343,7 +305,10 @@ public:
}
}
- writeToStderr("\r" + ansiTruncate(line, getWindowSize().second) + "\e[K");
+ auto width = getWindowSize().second;
+ if (width <= 0) std::numeric_limits<decltype(width)>::max();
+
+ writeToStderr("\r" + filterANSIEscapes(line, width) + "\e[K");
}
std::string getStatus(State & state)
diff --git a/tests/misc.sh b/tests/misc.sh
index 6d0ab3adc..eda016416 100644
--- a/tests/misc.sh
+++ b/tests/misc.sh
@@ -16,4 +16,4 @@ nix-env --foo 2>&1 | grep "no operation"
nix-env -q --foo 2>&1 | grep "unknown flag"
# Eval Errors.
-nix-instantiate --eval -E 'let a = {} // a; in a.foo' 2>&1 | grep "infinite recursion encountered, at (string):1:15$"
+nix-instantiate --eval -E 'let a = {} // a; in a.foo' 2>&1 | grep "infinite recursion encountered, at .*(string).*:1:15$"