53 std::string m_last_msg{};
57 explicit LiveMessage(std::string_view header,
bool active =
true)
58 : m_header(header), m_is_tty(isatty(fileno(stdout))), m_active(active) {
59 if (m_active && !m_is_tty) {
60 std::fwrite(m_header.data(), 1, m_header.size(), stdout);
74 if (!m_active || m_done)
78 std::fputs(
"\r", stdout);
79 std::fwrite(m_header.data(), 1, m_header.size(), stdout);
80 std::fwrite(msg.data(), 1, msg.size(), stdout);
90 void done(std::string_view post = {}) {
91 if (!m_active || m_done)
95 std::fputs(
"\r", stdout);
96 std::fwrite(m_header.data(), 1, m_header.size(), stdout);
98 std::fwrite(m_last_msg.data(), 1, m_last_msg.size(), stdout);
100 std::fwrite(post.data(), 1, post.size(), stdout);
101 std::fputc(
'\n', stdout);
113 const int len = (length - 1);
114 const int current = int(len *
double(i) /
double(
max - 1));
116 for (
auto j = 0; j < current; ++j) {
119 for (
auto j = current; j < len; ++j) {
122 std::cout <<
"] \r" << std::flush;
183template <std::
size_t Length = 60>
189 std::atomic<int> m_progress{0};
191 std::atomic<int> m_last_fill{-1};
196 static constexpr std::size_t bar_width = (Length >= 7) ? (Length - 7) : 1;
205 template <
typename T,
typename = std::enable_if_t<std::is_
integral_v<T>>>
207 : m_max(static_cast<int>(
max)), m_print(print) {
216 const int progress = ++m_progress;
217 if (progress > m_max)
219 const bool is_final = (progress == m_max);
222 const int current = int(bar_width *
double(progress) /
double(m_max));
223 if (!is_final && current <= m_last_fill.load(std::memory_order_relaxed))
226 print_prog_bar(progress);
233 void print_prog_bar(
int progress) {
234 const bool is_tty = isatty(fileno(stdout));
236 print_prog_bar_notty(progress);
240 const bool is_final = (progress == m_max);
243 const auto current = int(bar_width *
double(progress) /
double(m_max));
244 char buf[Length + 2];
247 for (
int j = 0; j < current; ++j)
249 for (
int j = current; j < (int)bar_width; ++j)
253 p += snprintf(p,
sizeof(buf) - std::size_t(p - buf) - 1,
"%d%%",
254 int(100.0 *
double(progress) /
double(m_max)));
255 *p++ = is_final ?
'\n' :
'\r';
260 bool did_print =
false;
272 m_last_fill.store(current, std::memory_order_relaxed);
278 void print_prog_bar_notty(
int progress) {
279 const bool is_initial = (progress == 0);
280 const bool is_final = (progress == m_max);
283 is_final ? 100 : int(100.0 *
double(progress) /
double(m_max));
286 static constexpr int n_entries =
static_cast<int>(Length) / 5;
287 static constexpr int interval =
288 (n_entries > 1) ? (100 / (n_entries - 1)) : 100;
289 const int slot = pct / interval;
291 if (!is_initial && !is_final &&
292 slot <= m_last_fill.load(std::memory_order_relaxed))
297 snprintf(buf,
sizeof(buf),
"100%%\n");
299 snprintf(buf,
sizeof(buf),
"%d%%, ", pct);
301 bool did_print =
false;
312 if (!is_final && did_print)
313 m_last_fill.store(slot, std::memory_order_relaxed);
Live status line for iterative loops; overwrites itself on a TTY.
Definition Widgets.hpp:48
void operator()(std::string_view msg)
Update the status message. see update()
Definition Widgets.hpp:86
void done(std::string_view post={})
Finalise: print last message + optional post, then newline. Safe to call multiple times (only the fir...
Definition Widgets.hpp:90
void update(std::string_view msg)
Update the status message. On TTY overwrites the current line; on non-TTY buffers silently until done...
Definition Widgets.hpp:73
Thread-safe progress bar for OpenMP parallel loops.
Definition Widgets.hpp:184
ProgressBar(T max, bool print=true)
Construct progress bar for max iterations.
Definition Widgets.hpp:206
void update()
Atomically increment progress counter and print updated bar.
Definition Widgets.hpp:213
General-purpose utility library.
Definition Array.hpp:23
void progbar(int i, int max, int length=50)
Basic progress bar. Prints new line if (and only if) i==(max-1)
Definition Widgets.hpp:112
T max(T first, Args... rest)
Returns the maximum of any number of parameters (variadic).
Definition Maths.hpp:28
Include instead of <omp.h> to allow compilation with or without OpenMP.