diff --git a/src/build.cc b/src/build.cc index c24d6a919d..6eb72e6a6f 100644 --- a/src/build.cc +++ b/src/build.cc @@ -203,7 +203,21 @@ string BuildStatus::FormatProgressStatus( char buf[32]; int percent; for (const char* s = progress_status_format; *s != '\0'; ++s) { - if (*s == '%') { + // Support ANSI color escape codes in NINJA_STATUS + if (strncmp(s, "\\033[", 5) == 0) { + const char *end = strchr(s + 5, 'm'); + if (end == NULL) { + // Not a valid ANSI color sequence, treat as regular text + } else { + out.append("\x1B["); + for (const char *t = s + 5; t <= end; ++t) { + out.push_back(*t); + } + s = end; + continue; + } + } + else if (*s == '%') { ++s; switch (*s) { case '%': diff --git a/src/util.cc b/src/util.cc index 61a038bb14..997219ab97 100644 --- a/src/util.cc +++ b/src/util.cc @@ -570,10 +570,23 @@ double GetLoadAverage() { } #endif // _WIN32 +// Calculate the width of a string accounting for ANSI escape codes +size_t CalculateWidth(const string& str) { + const int initial_width = str.size(); + size_t zero_width_start = str.find("\x1B["); + if (zero_width_start != string::npos) { + size_t zero_width_end = str.find("m", zero_width_start); + if (zero_width_end != string::npos) { + return initial_width - (zero_width_end - zero_width_start) - 1; + } + } + return initial_width; +} + string ElideMiddle(const string& str, size_t width) { const int kMargin = 3; // Space for "...". string result = str; - if (result.size() + kMargin > width) { + if (CalculateWidth(result) + kMargin > width) { size_t elide_size = (width - kMargin) / 2; result = result.substr(0, elide_size) + "..."