From 950b6401f98d1a56fefb2d6101e0513cc601824c Mon Sep 17 00:00:00 2001 From: Ivan Shapovalov Date: Fri, 1 Mar 2024 22:12:44 +0100 Subject: [PATCH 1/4] libmain/progress-bar: try harder to avoid escape sequences if !isTTY --- src/libmain/progress-bar.cc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index 3aa012ee1..afba29e1b 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -123,14 +123,18 @@ public: } void pause() override { - state_.lock()->paused = true; - writeToStderr("\r\e[K"); + auto state (state_.lock()); + state->paused = true; + if (state->active) + writeToStderr("\r\e[K"); } void resume() override { - state_.lock()->paused = false; - writeToStderr("\r\e[K"); - state_.lock()->haveUpdate = true; + auto state (state_.lock()); + state->paused = false; + if (state->active) + writeToStderr("\r\e[K"); + state->haveUpdate = true; updateCV.notify_one(); } @@ -162,9 +166,7 @@ public: writeToStderr("\r\e[K" + filterANSIEscapes(s, !isTTY) + ANSI_NORMAL "\n"); draw(state); } else { - auto s2 = s + ANSI_NORMAL "\n"; - if (!isTTY) s2 = filterANSIEscapes(s2, true); - writeToStderr(s2); + writeToStderr(filterANSIEscapes(s, !isTTY) + "\n"); } } @@ -519,7 +521,7 @@ public: std::optional ask(std::string_view msg) override { auto state(state_.lock()); - if (!state->active || !isatty(STDIN_FILENO)) return {}; + if (!state->active) return {}; std::cerr << fmt("\r\e[K%s ", msg); auto s = trim(readLine(STDIN_FILENO)); if (s.size() != 1) return {}; From d9fc4bf5c5a2ad075d4500b005abc839eb98e581 Mon Sep 17 00:00:00 2001 From: Ivan Shapovalov Date: Fri, 1 Mar 2024 23:11:24 +0100 Subject: [PATCH 2/4] treewide: replace usages of isatty(STDERR_FILENO) with shouldANSI() --- src/nix-env/nix-env.cc | 3 ++- src/nix/main.cc | 5 ++++- src/nix/prefetch.cc | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 5e3de20c5..b42fa06bc 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -16,6 +16,7 @@ #include "xml-writer.hh" #include "legacy.hh" #include "eval-settings.hh" // for defexpr +#include "terminal.hh" #include #include @@ -1089,7 +1090,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) return; } - bool tty = isatty(STDOUT_FILENO); + bool tty = shouldANSI(); RunPager pager; Table table; diff --git a/src/nix/main.cc b/src/nix/main.cc index 5af5f2e41..c88b35005 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -16,6 +16,7 @@ #include "loggers.hh" #include "markdown.hh" #include "memory-input-accessor.hh" +#include "terminal.hh" #include #include @@ -375,7 +376,9 @@ void mainWrapped(int argc, char * * argv) setLogFormat("bar"); settings.verboseBuild = false; - if (isatty(STDERR_FILENO)) { + + // If on a terminal, progress will be displayed via progress bars etc. (thus verbosity=notice) + if (nix::shouldANSI()) { verbosity = lvlNotice; } else { verbosity = lvlInfo; diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index fabec5d88..f96381408 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -11,6 +11,7 @@ #include "legacy.hh" #include "posix-source-accessor.hh" #include "misc-store-flags.hh" +#include "terminal.hh" #include @@ -188,7 +189,7 @@ static int main_nix_prefetch_url(int argc, char * * argv) Finally f([]() { stopProgressBar(); }); - if (isatty(STDERR_FILENO)) + if (shouldANSI()) startProgressBar(); auto store = openStore(); From 8c1eeb4681dc2acc60f23341d79470a0340ccdf5 Mon Sep 17 00:00:00 2001 From: Ivan Shapovalov Date: Fri, 1 Mar 2024 23:13:00 +0100 Subject: [PATCH 3/4] treewide: shouldANSI() -> isTTY() --- src/libcmd/markdown.cc | 2 +- src/libmain/progress-bar.cc | 2 +- src/libutil/logging.cc | 2 +- src/libutil/terminal.cc | 2 +- src/libutil/terminal.hh | 2 +- src/nix-env/nix-env.cc | 2 +- src/nix/main.cc | 2 +- src/nix/prefetch.cc | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libcmd/markdown.cc b/src/libcmd/markdown.cc index a4e3c5a77..d62ff0d96 100644 --- a/src/libcmd/markdown.cc +++ b/src/libcmd/markdown.cc @@ -50,7 +50,7 @@ std::string renderMarkdownToTerminal(std::string_view markdown) if (!rndr_res) throw Error("allocation error while rendering Markdown"); - return filterANSIEscapes(std::string(buf->data, buf->size), !shouldANSI()); + return filterANSIEscapes(std::string(buf->data, buf->size), !isTTY()); #else return std::string(markdown); #endif diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index afba29e1b..ce45eae2b 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -537,7 +537,7 @@ public: Logger * makeProgressBar() { - return new ProgressBar(shouldANSI()); + return new ProgressBar(isTTY()); } void startProgressBar() diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 89fbd194a..83db492ca 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -52,7 +52,7 @@ public: : printBuildLogs(printBuildLogs) { systemd = getEnv("IN_SYSTEMD") == "1"; - tty = shouldANSI(); + tty = isTTY(); } bool isVerbose() override { diff --git a/src/libutil/terminal.cc b/src/libutil/terminal.cc index 8febc8771..2ff923405 100644 --- a/src/libutil/terminal.cc +++ b/src/libutil/terminal.cc @@ -7,7 +7,7 @@ namespace nix { -bool shouldANSI() +bool isTTY() { return isatty(STDERR_FILENO) && getEnv("TERM").value_or("dumb") != "dumb" diff --git a/src/libutil/terminal.hh b/src/libutil/terminal.hh index 9cb191308..9d8d0c743 100644 --- a/src/libutil/terminal.hh +++ b/src/libutil/terminal.hh @@ -8,7 +8,7 @@ namespace nix { * Determine whether ANSI escape sequences are appropriate for the * present output. */ -bool shouldANSI(); +bool isTTY(); /** * Truncate a string to 'width' printable characters. If 'filterAll' diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index b42fa06bc..0fa9501c1 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1090,7 +1090,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) return; } - bool tty = shouldANSI(); + bool tty = isTTY(); RunPager pager; Table table; diff --git a/src/nix/main.cc b/src/nix/main.cc index c88b35005..22f9e7931 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -378,7 +378,7 @@ void mainWrapped(int argc, char * * argv) settings.verboseBuild = false; // If on a terminal, progress will be displayed via progress bars etc. (thus verbosity=notice) - if (nix::shouldANSI()) { + if (nix::isTTY()) { verbosity = lvlNotice; } else { verbosity = lvlInfo; diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index f96381408..b64e6d899 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -189,7 +189,7 @@ static int main_nix_prefetch_url(int argc, char * * argv) Finally f([]() { stopProgressBar(); }); - if (shouldANSI()) + if (isTTY()) startProgressBar(); auto store = openStore(); From c6f0407103ff64e86b5cc340980c010d49b31e8a Mon Sep 17 00:00:00 2001 From: Ivan Shapovalov Date: Fri, 1 Mar 2024 23:17:44 +0100 Subject: [PATCH 4/4] libutil/terminal: cache isTTY() --- src/libutil/terminal.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libutil/terminal.cc b/src/libutil/terminal.cc index 2ff923405..096252f03 100644 --- a/src/libutil/terminal.cc +++ b/src/libutil/terminal.cc @@ -9,9 +9,12 @@ namespace nix { bool isTTY() { - return isatty(STDERR_FILENO) + static const bool tty = + isatty(STDERR_FILENO) && getEnv("TERM").value_or("dumb") != "dumb" && !(getEnv("NO_COLOR").has_value() || getEnv("NOCOLOR").has_value()); + + return tty; } std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int width)