diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2018-02-07T14·19+0100 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2018-02-07T14·23+0100 |
commit | 84989d3af23c717744b8ddeacd6828bc87e7eda1 (patch) | |
tree | edbd50b08c19559a56c2b0350ed6f44c44c0e731 /src/libutil/util.cc | |
parent | cfdfad5c3451731879a5a693059c094f107c2bc8 (diff) |
Improve filtering of ANSI escape sequences in build logs
All ANSI sequences except color setting are now filtered out. In particular, terminal resets (such as from NixOS VM tests) are filtered out. Also, fix the completely broken tab character handling.
Diffstat (limited to 'src/libutil/util.cc')
-rw-r--r-- | src/libutil/util.cc | 67 |
1 files changed, 41 insertions, 26 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 272997397794..f7a12d21b244 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; } |