24#include <readline/readline.h>
30#include <boost/algorithm/string/trim.hpp>
31#include <boost/thread.hpp>
77 *backup_fd = dup(old_fd);
82 if (pipe(pipe_fds) < 0) {
86 int flags = fcntl(pipe_fds[0], F_GETFL, 0);
87 if (fcntl(pipe_fds[0], F_SETFL, flags | O_NONBLOCK) < 0) {
91 if (dup2(pipe_fds[1], old_fd) < 0) {
113class Screen :
public boost::noncopyable {
132 rl_catch_signals = 0;
133 rl_deprep_term_function =
nullptr;
134 rl_prep_term_function =
nullptr;
139 rl_catch_sigwinch = 0;
172 m_screen = newterm(
nullptr, outfd, infd);
180 keypad(stdscr, TRUE);
184 use_default_colors();
197 ::sigaction(SIGINT, &
prev_signal[SIGINT],
nullptr);
198 ::sigaction(SIGTERM, &
prev_signal[SIGTERM],
nullptr);
199 ::sigaction(SIGABRT, &
prev_signal[SIGABRT],
nullptr);
200 ::sigaction(SIGSEGV, &
prev_signal[SIGSEGV],
nullptr);
201 ::sigaction(SIGHUP, &
prev_signal[SIGHUP],
nullptr);
202 ::sigaction(SIGCONT, &
prev_signal[SIGCONT],
nullptr);
203 ::sigaction(SIGWINCH, &
prev_signal[SIGWINCH],
nullptr);
247#if _POSIX_C_SOURCE >= 200112L
249 clock_gettime(CLOCK_REALTIME, &timeout);
338 LogWidget(
int display_height,
int display_width,
int display_y,
int display_x,
short bar_color,
short ind_color)
340 m_scroll(newpad(display_height, 1)),
343 scrollok(
m_pad, TRUE);
360 void write(
const char *data, ssize_t nchars) {
373 waddch(
m_pad, *data);
384 void resize(
int display_height,
int display_width) {
390 if (display_width > getmaxx(
m_pad)) {
391 wresize(
m_pad, getmaxy(
m_pad), display_width);
393 wresize(
m_scroll, display_height, 1);
450 boost::algorithm::trim(term_lines.
back());
453 while (!term_lines.
empty() && term_lines.
back().empty()) {
468 int displayed_line_offset =
m_active_line - min_selectable_line;
469 float p =
std::max(0.f,
std::min(1.f,
static_cast<float>(displayed_line_offset) /
470 static_cast<float>(max_selectable_line - min_selectable_line)));
472 auto scroll_marker_pos =
static_cast<int>(p *
static_cast<float>(
m_display_height - 1));
474 if (i == scroll_marker_pos)
519 ProgressWidget(
int height,
int width,
int y,
int x,
short done_color,
short progress_color)
565 size_t value_position =
sizeof(
"Elapsed");
567 for (
auto& entry: info) {
568 if (entry.m_label.size() > value_position) {
569 value_position = entry.m_label.size();
575 int bar_width = getmaxx(
m_window) - 2 -
static_cast<int>(value_position);
586 for (
auto& entry : info) {
587 drawProgressLine(
static_cast<int>(value_position), bar_width, line, entry.m_label, entry.m_total, entry.m_done);
592 drawElapsed(
static_cast<int>(value_position), elapsed, line);
602 void drawElapsed(
size_t value_position,
const std::chrono::steady_clock::duration& elapsed,
int line)
const {
603 auto h = std::chrono::duration_cast<std::chrono::hours>(elapsed);
604 auto m = std::chrono::duration_cast<std::chrono::minutes>(elapsed - h);
605 auto s = std::chrono::duration_cast<std::chrono::seconds>(elapsed - h -
m);
607 elapsed_str.
fill(
'0');
611 mvwaddstr(
m_window, line, 0,
"Elapsed");
615 line, value_position + 1,
616 elapsed_str.
str().c_str()
624 int total,
int done)
const {
632 mvwprintw(
m_window, line, value_position + 1,
"%d", done);
637 float ratio =
static_cast<float>(done) /
static_cast<float>(total);
653 mvwaddch(
m_window, line, value_position,
'[');
656 auto bar_content =
bar.str();
657 auto completed =
static_cast<int>(
static_cast<float>(bar_content.size()) *
ratio);
660 waddstr(
m_window, bar_content.substr(0, completed).c_str());
665 waddstr(
m_window, bar_content.substr(completed).c_str());
718 sigaddset(&
set, SIGTERM);
719 sigaddset(&
set, SIGINT);
720 sigaddset(&
set, SIGHUP);
721 pthread_sigmask(SIG_BLOCK, &
set,
nullptr);
735 if (poll_fd.revents & POLLIN) {
737 if (read(
signal_fds[0], &signal_no,
sizeof(signal_no)) ==
sizeof(signal_no) && signal_no == SIGWINCH) {
745 logWidget.
write(buf,
snprintf(buf,
sizeof(buf),
"Caught signal %s\n", strsignal(signal_no)));
752 if (poll_fd.revents & POLLIN) {
755 while ((nbytes = read(pipe, &buf,
sizeof(buf))) > 0) {
756 out.
write(buf, nbytes);
762 if (poll_fd.revents & POLLIN) {
763 int key = wgetch(stdscr);
764 if (key != KEY_RESIZE) {
778 LINES - 1, COLS, 0, 0,
779 screen.
initColor(COLOR_WHITE, COLOR_BLACK), screen.
initColor(COLOR_WHITE, COLOR_WHITE)
784 1, COLS, LINES - 1, 0,
785 screen.
initColor(COLOR_WHITE, COLOR_GREEN), screen.
initColor(COLOR_WHITE, COLOR_BLACK)
789 struct pollfd poll_fds[] = {
792 {STDIN_FILENO, POLLIN, 0},
828 if (poll(poll_fds, 4, 1000) < 0) {
832 }
while (!
m_exit_loop && !boost::this_thread::interruption_requested());
846 if (new_stderr_fd < 0) {
849 m_stderr = fdopen(new_stderr_fd,
"w");
894 return isatty(STDERR_FILENO);
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > y
T emplace_back(T... args)
T generic_category(T... args)
std::unique_ptr< T > make_unique(Args &&... args)
T setprecision(T... args)