about summary refs log tree commit diff
path: root/src/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/util.cc35
-rw-r--r--src/libutil/util.hh12
2 files changed, 47 insertions, 0 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 14aab7cded32..0600352ff537 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -453,6 +453,7 @@ void printMsg_(Verbosity level, const FormatOrString & fs)
     else if (logType == ltEscapes && level != lvlInfo)
         prefix = "\033[" + escVerbosity(level) + "s";
     string s = (format("%1%%2%\n") % prefix % fs.s).str();
+    if (!isatty(STDERR_FILENO)) s = filterANSIEscapes(s);
     writeToStderr(s);
 }
 
@@ -1106,4 +1107,38 @@ 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;
+            }
+        } 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();
+            }
+        }
+    }
+    t += r;
+    return t;
+}
+
+
 }
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 5f2d95339f30..f6f5d1b3fee7 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -369,4 +369,16 @@ string decodeOctalEscaped(const string & s);
 void ignoreException();
 
 
+/* Some ANSI escape sequences. */
+#define ANSI_NORMAL "\e[0m"
+#define ANSI_BOLD "\e[1m"
+#define ANSI_RED "\e[31;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);
+
+
 }