Merge changes Ic91ca404,I142cf38f into main

* changes:
  libmain/progress-bar: implement synchronized updates
  libmain/progress-bar: fix writeToStdout in multiline mode
This commit is contained in:
alois31
2025-03-09 17:17:58 +00:00
committed by Gerrit Code Review
3 changed files with 31 additions and 29 deletions
@@ -0,0 +1,9 @@
---
synopsis: Fix interference of the multiline progress bar with output
category: Fixes
cls: [2774]
credits: [alois31]
---
In some situations, the progress indicator of the multiline progress bar would interfere with persistent output.
This would result in progress bar headers being visible in place of the desired text, for example the outputs shown after a `:b` command in the repl.
The underlying ordering issue has been fixed, so that the undesired interference does not happen any more.
+20 -27
View File
@@ -91,7 +91,8 @@ void ProgressBar::resume()
while (state->paused == 0) {
if (!state->haveUpdate)
state.wait_for(updateCV, nextWakeup);
nextWakeup = draw(*state, {});
eraseProgressDisplay(*state);
nextWakeup = restoreProgressDisplay(*state);
state.wait_for(quitCV, std::chrono::milliseconds(50));
}
eraseProgressDisplay(*state);
@@ -122,13 +123,9 @@ void ProgressBar::logEI(const ErrorInfo & ei)
void ProgressBar::log(State & state, Verbosity lvl, std::string_view s)
{
if (state.paused == 0) {
draw(state, s);
} else {
auto s2 = s + ANSI_NORMAL "\n";
if (!isTTY) s2 = filterANSIEscapes(s2, true);
writeLogsToStderr(s2);
}
if (state.paused == 0) eraseProgressDisplay(state);
writeLogsToStderr(filterANSIEscapes(s + ANSI_NORMAL "\n", !isTTY));
restoreProgressDisplay(state);
}
void ProgressBar::startActivity(
@@ -323,6 +320,9 @@ void ProgressBar::update(State & state)
void ProgressBar::eraseProgressDisplay(State & state)
{
if (state.paused == 0) {
writeLogsToStderr("\e[?2026h"); // begin synchronized update
}
if (printMultiline && (state.lastLines >= 1)) {
// FIXME: make sure this works on windows
writeLogsToStderr(fmt("\e[G\e[%dF\e[J", state.lastLines));
@@ -331,12 +331,12 @@ void ProgressBar::eraseProgressDisplay(State & state)
}
}
std::chrono::milliseconds ProgressBar::draw(State & state, const std::optional<std::string_view> & s)
std::chrono::milliseconds ProgressBar::restoreProgressDisplay(State & state)
{
auto nextWakeup = A_LONG_TIME;
state.haveUpdate = false;
if (state.paused > 0) return nextWakeup;
if (state.paused > 0) return nextWakeup; // when paused, the progress display should not actually be shown
auto windowSize = getWindowSize();
auto width = windowSize.second;
@@ -344,13 +344,8 @@ std::chrono::milliseconds ProgressBar::draw(State & state, const std::optional<s
width = std::numeric_limits<decltype(width)>::max();
}
eraseProgressDisplay(state);
state.lastLines = 0;
if (s != std::nullopt)
writeLogsToStderr(filterANSIEscapes(s.value(), !isTTY) + ANSI_NORMAL "\n");
std::string line;
std::string status = getStatus(state);
if (!status.empty()) {
@@ -363,8 +358,8 @@ std::chrono::milliseconds ProgressBar::draw(State & state, const std::optional<s
state.lastLines++;
}
auto height = windowSize.first > 0 ? windowSize.first : 25;
auto moreActivities = 0;
auto height = windowSize.first > 0 ? windowSize.first : 25;
auto moreActivities = 0;
auto now = std::chrono::steady_clock::now();
std::string activity_line;
@@ -422,6 +417,8 @@ std::chrono::milliseconds ProgressBar::draw(State & state, const std::optional<s
}
}
writeLogsToStderr("\e[?2026l"); // end synchronized update
return nextWakeup;
}
@@ -546,15 +543,9 @@ std::string ProgressBar::getStatus(State & state)
void ProgressBar::writeToStdout(std::string_view s)
{
auto state(state_.lock());
if (state->paused == 0) {
if (isTTY && !printMultiline) {
eraseProgressDisplay(*state);
}
Logger::writeToStdout(s);
draw(*state, {});
} else {
Logger::writeToStdout(s);
}
if (state->paused == 0) eraseProgressDisplay(*state);
Logger::writeToStdout(s);
restoreProgressDisplay(*state);
}
std::optional<char> ProgressBar::ask(std::string_view msg)
@@ -562,10 +553,12 @@ std::optional<char> ProgressBar::ask(std::string_view msg)
auto state(state_.lock());
if (state->paused > 0 || !isatty(STDIN_FILENO)) return {};
eraseProgressDisplay(*state);
writeLogsToStderr("\e[?2026l"); // end synchronized update
std::cerr << msg;
auto s = trim(readLine(STDIN_FILENO));
writeLogsToStderr("\e[?2026h"); // begin synchronized update
if (s.size() != 1) return {};
draw(*state, {});
restoreProgressDisplay(*state);
return s[0];
}
+2 -2
View File
@@ -97,8 +97,6 @@ struct ProgressBar : public Logger
void update(State & state);
std::chrono::milliseconds draw(State & state, const std::optional<std::string_view> & s);
std::string getStatus(State & state);
void writeToStdout(std::string_view s) override;
@@ -111,6 +109,8 @@ struct ProgressBar : public Logger
private:
void eraseProgressDisplay(State & state);
std::chrono::milliseconds restoreProgressDisplay(State & state);
};
Logger * makeProgressBar();