#include "utils.hpp" #include #include #include #include #include #include using namespace sc; term::term(int fd) { if (isatty(fd)) { throw_if_min1(ioctl(fd, TIOCGWINSZ, &_ws)); } switch (fd) { case STDOUT_FILENO: _out = &std::cout; break; case STDERR_FILENO: _out = &std::cerr; break; default: break; } } int term::rows() const { return _ws.ws_row; } int term::cols() const { return _ws.ws_col; } void term::progress(double cur, double total) const { // use unicode to make nice bar const char* bar[8] = { u8"\u258F", u8"\u258E", u8"\u258D", u8"\u258C", u8"\u258B", u8"\u258A", u8"\u2589", u8"\u2588" }; int barwidth = cols() - 5; int maxsteps = barwidth * 8; int steps = round(cur * maxsteps / total); int perc = round(100 * cur / total); *_out << '\r' << std::setw(3) << perc << "% "; for (int i = 0; i < steps / 8; ++i) { *_out << bar[7]; } if (steps % 8) { *_out << bar[steps % 8 - 1]; } } void term::hide_cursor() const { *_out << "\x1b[?25l"; } void term::show_cursor() const { *_out << "\x1b[?25h"; } void term::reset() const { *_out << "\x1b[m"; } void term::bold() const { *_out << "\x1b[1m"; } void term::italic() const { *_out << "\x1b[3m"; } void term::underline() const { *_out << "\x1b[4m"; } void term::overline() const { *_out << "\x1b[53m"; } void term::strikethru() const { *_out << "\x1b[9m"; } void term::blinkslow() const { *_out << "\x1b[5m"; } void term::blinkfast() const { *_out << "\x1b[6m"; } void term::reverse() const { *_out << "\x1b[7m"; } void term::blackf() const { *_out << "\x1b[30m"; } void term::redf() const { *_out << "\x1b[31m"; } void term::greenf() const { *_out << "\x1b[32m"; } void term::yellowf() const { *_out << "\x1b[33m"; } void term::bluef() const { *_out << "\x1b[34m"; } void term::magentaf() const { *_out << "\x1b[35m"; } void term::cyanf() const { *_out << "\x1b[36m"; } void term::whitef() const { *_out << "\x1b[37m"; } void term::defaultf() const { *_out << "\x1b[39m"; } void term::grayf(int val) const { gray(val, 38); } void term::rgbf(int r, int g, int b) const { rgb(r, g, b, 38); } void term::blackb() const { *_out << "\x1b[40m"; } void term::redb() const { *_out << "\x1b[41m"; } void term::greenb() const { *_out << "\x1b[42m"; } void term::yellowb() const { *_out << "\x1b[43m"; } void term::blueb() const { *_out << "\x1b[44m"; } void term::magentab() const { *_out << "\x1b[45m"; } void term::cyanb() const { *_out << "\x1b[46m"; } void term::whiteb() const { *_out << "\x1b[47m"; } void term::defaultb() const { *_out << "\x1b[49m"; } void term::grayb(int val) const { gray(val, 48); } void term::rgbb(int r, int g, int b) const { rgb(r, g, b, 48); } void term::gray(int val, int code) const { if (val < 0 || val > 24) { throw std::invalid_argument("gray value out of range"); } *_out << "\x1b[" << code << ";5;" << 232 + val << "m"; } void term::rgb(int r, int g, int b, int code) const { if (r < 0 || r > 5 || g < 0 || g > 5 || b < 0 || b > 5) { throw std::invalid_argument("rgb color component out of range"); } *_out << "\x1b[" << code << ";5;" << (16 + 36 * r + 7 * g + b) << "m"; } // ------------------------------------------------------------------------ cursor_hider::cursor_hider(int fd) : _t {fd} { _t.hide_cursor(); } cursor_hider::~cursor_hider() { _t.show_cursor(); }