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)
77 std::fputs(
"\r", stdout);
78 std::fwrite(m_header.data(), 1, m_header.size(), stdout);
79 std::fwrite(msg.data(), 1, msg.size(), stdout);
80 clear_tail(msg.size());
91 void done(std::string_view post = {}) {
92 if (!m_active || m_done)
96 std::fputs(
"\r", stdout);
97 std::fwrite(m_header.data(), 1, m_header.size(), stdout);
99 std::fwrite(m_last_msg.data(), 1, m_last_msg.size(), stdout);
101 std::fwrite(post.data(), 1, post.size(), stdout);
102 std::fputc(
'\n', stdout);
109 void clear_tail(std::size_t new_size)
const {
110 for (
auto i = new_size; i < m_last_msg.size(); ++i) {
111 std::fputc(
' ', stdout);
123 const int len = (length - 1);
124 const int current = int(len *
double(i) /
double(
max - 1));
126 for (
auto j = 0; j < current; ++j) {
129 for (
auto j = current; j < len; ++j) {
132 std::cout <<
"] \r" << std::flush;
193template <std::
size_t Length = 60>
199 std::atomic<int> m_progress{0};
201 std::atomic<int> m_last_fill{-1};
206 static constexpr std::size_t bar_width = (Length >= 7) ? (Length - 7) : 1;
215 template <
typename T,
typename = std::enable_if_t<std::is_
integral_v<T>>>
217 : m_max(static_cast<int>(
max)), m_print(print) {
226 const int progress = ++m_progress;
227 if (progress > m_max)
229 const bool is_final = (progress == m_max);
232 const int current = int(bar_width *
double(progress) /
double(m_max));
233 if (!is_final && current <= m_last_fill.load(std::memory_order_relaxed))
236 print_prog_bar(progress);
243 void print_prog_bar(
int progress) {
244 const bool is_tty = isatty(fileno(stdout));
246 print_prog_bar_notty(progress);
250 const bool is_final = (progress == m_max);
253 const auto current = int(bar_width *
double(progress) /
double(m_max));
254 char buf[Length + 2];
257 for (
int j = 0; j < current; ++j)
259 for (
int j = current; j < (int)bar_width; ++j)
263 p += snprintf(p,
sizeof(buf) - std::size_t(p - buf) - 1,
"%d%%",
264 int(100.0 *
double(progress) /
double(m_max)));
265 *p++ = is_final ?
'\n' :
'\r';
270 bool did_print =
false;
282 m_last_fill.store(current, std::memory_order_relaxed);
288 void print_prog_bar_notty(
int progress) {
289 const bool is_initial = (progress == 0);
290 const bool is_final = (progress == m_max);
293 is_final ? 100 : int(100.0 *
double(progress) /
double(m_max));
296 static constexpr int n_entries =
static_cast<int>(Length) / 5;
297 static constexpr int interval =
298 (n_entries > 1) ? (100 / (n_entries - 1)) : 100;
299 const int slot = pct / interval;
301 if (!is_initial && !is_final &&
302 slot <= m_last_fill.load(std::memory_order_relaxed))
307 snprintf(buf,
sizeof(buf),
"100%%\n");
309 snprintf(buf,
sizeof(buf),
"%d%%, ", pct);
311 bool did_print =
false;
322 if (!is_final && did_print)
323 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:87
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:91
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:194
ProgressBar(T max, bool print=true)
Construct progress bar for max iterations.
Definition Widgets.hpp:216
void update()
Atomically increment progress counter and print updated bar.
Definition Widgets.hpp:223
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:122
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.