forked from lix-project/lix
ProgressBar: Delay before showing a new activity
Some activities are numerous but usually very short (e.g. copying a source file to the store) which would cause a lot of flickering. So only show activities that have been running for at least 10 ms.
This commit is contained in:
parent
e62160579f
commit
c3769c6846
|
@ -8,6 +8,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -48,6 +49,7 @@ private:
|
||||||
bool visible = true;
|
bool visible = true;
|
||||||
ActivityId parent;
|
ActivityId parent;
|
||||||
std::optional<std::string> name;
|
std::optional<std::string> name;
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock> startTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ActivitiesByType
|
struct ActivitiesByType
|
||||||
|
@ -91,10 +93,11 @@ public:
|
||||||
state_.lock()->active = isTTY;
|
state_.lock()->active = isTTY;
|
||||||
updateThread = std::thread([&]() {
|
updateThread = std::thread([&]() {
|
||||||
auto state(state_.lock());
|
auto state(state_.lock());
|
||||||
|
auto nextWakeup = std::chrono::milliseconds::max();
|
||||||
while (state->active) {
|
while (state->active) {
|
||||||
if (!state->haveUpdate)
|
if (!state->haveUpdate)
|
||||||
state.wait(updateCV);
|
state.wait_for(updateCV, nextWakeup);
|
||||||
draw(*state);
|
nextWakeup = draw(*state);
|
||||||
state.wait_for(quitCV, std::chrono::milliseconds(50));
|
state.wait_for(quitCV, std::chrono::milliseconds(50));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -118,7 +121,8 @@ public:
|
||||||
updateThread.join();
|
updateThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isVerbose() override {
|
bool isVerbose() override
|
||||||
|
{
|
||||||
return printBuildLogs;
|
return printBuildLogs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +163,13 @@ public:
|
||||||
if (lvl <= verbosity && !s.empty() && type != actBuildWaiting)
|
if (lvl <= verbosity && !s.empty() && type != actBuildWaiting)
|
||||||
log(*state, lvl, s + "...");
|
log(*state, lvl, s + "...");
|
||||||
|
|
||||||
state->activities.emplace_back(ActInfo());
|
state->activities.emplace_back(ActInfo {
|
||||||
|
.s = s,
|
||||||
|
.type = type,
|
||||||
|
.parent = parent,
|
||||||
|
.startTime = std::chrono::steady_clock::now()
|
||||||
|
});
|
||||||
auto i = std::prev(state->activities.end());
|
auto i = std::prev(state->activities.end());
|
||||||
i->s = s;
|
|
||||||
i->type = type;
|
|
||||||
i->parent = parent;
|
|
||||||
state->its.emplace(act, i);
|
state->its.emplace(act, i);
|
||||||
state->activitiesByType[type].its.emplace(act, i);
|
state->activitiesByType[type].its.emplace(act, i);
|
||||||
|
|
||||||
|
@ -327,10 +333,12 @@ public:
|
||||||
updateCV.notify_one();
|
updateCV.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(State & state)
|
std::chrono::milliseconds draw(State & state)
|
||||||
{
|
{
|
||||||
|
auto nextWakeup = std::chrono::milliseconds::max();
|
||||||
|
|
||||||
state.haveUpdate = false;
|
state.haveUpdate = false;
|
||||||
if (!state.active) return;
|
if (!state.active) return nextWakeup;
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
|
@ -341,12 +349,25 @@ public:
|
||||||
line += "]";
|
line += "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (!state.activities.empty()) {
|
if (!state.activities.empty()) {
|
||||||
if (!status.empty()) line += " ";
|
if (!status.empty()) line += " ";
|
||||||
auto i = state.activities.rbegin();
|
auto i = state.activities.rbegin();
|
||||||
|
|
||||||
while (i != state.activities.rend() && (!i->visible || (i->s.empty() && i->lastLine.empty())))
|
while (i != state.activities.rend()) {
|
||||||
|
if (i->visible && (!i->s.empty() || !i->lastLine.empty())) {
|
||||||
|
/* Don't show activities until some time has
|
||||||
|
passed, to avoid displaying very short
|
||||||
|
activities. */
|
||||||
|
auto delay = std::chrono::milliseconds(10);
|
||||||
|
if (i->startTime + delay < now)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
nextWakeup = std::min(nextWakeup, std::chrono::duration_cast<std::chrono::milliseconds>(delay - (now - i->startTime)));
|
||||||
|
}
|
||||||
++i;
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
if (i != state.activities.rend()) {
|
if (i != state.activities.rend()) {
|
||||||
line += i->s;
|
line += i->s;
|
||||||
|
@ -366,6 +387,8 @@ public:
|
||||||
if (width <= 0) width = std::numeric_limits<decltype(width)>::max();
|
if (width <= 0) width = std::numeric_limits<decltype(width)>::max();
|
||||||
|
|
||||||
writeToStderr("\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K");
|
writeToStderr("\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K");
|
||||||
|
|
||||||
|
return nextWakeup;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getStatus(State & state)
|
std::string getStatus(State & state)
|
||||||
|
|
Loading…
Reference in a new issue