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:
@@ -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
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user