diff --git a/.clang-format b/.clang-format index 35cdf3c..0e0bcba 100644 --- a/.clang-format +++ b/.clang-format @@ -44,7 +44,7 @@ BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 80 +ColumnLimit: 100 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false diff --git a/clang-format.bash b/clang-format.bash index 07a71cf..1060a9b 100755 --- a/clang-format.bash +++ b/clang-format.bash @@ -1,2 +1,2 @@ #!/usr/bin/env bash -find ./include ./demo/ ./samples/ ./single_include -type f \( -iname \*.cpp -o -iname \*.hpp \) | xargs clang-format -style="{ColumnLimit : 100}" -i +find ./include ./demo/ ./samples/ -type f \( -iname \*.cpp -o -iname \*.hpp \) | xargs clang-format -style=file -i diff --git a/include/indicators/block_progress_bar.hpp b/include/indicators/block_progress_bar.hpp index aeadb6c..bf04194 100644 --- a/include/indicators/block_progress_bar.hpp +++ b/include/indicators/block_progress_bar.hpp @@ -4,16 +4,16 @@ #include #include +#include +#include #include #include #include -#include -#include #include #include -#include #include +#include #include #include #include @@ -22,46 +22,50 @@ namespace indicators { class BlockProgressBar { - using Settings = std::tuple; + // clang-format off + using Settings = std::tuple; + // clang-format on public: template ::type...>::value, void *>::type = nullptr> - explicit BlockProgressBar(Args &&... args) - : settings_(details::get( - option::ForegroundColor{Color::unspecified}, std::forward(args)...), - details::get(option::BarWidth{100}, + explicit BlockProgressBar(Args &&...args) + : settings_(details::get(option::BarWidth{100}, std::forward(args)...), details::get(option::Start{"["}, std::forward(args)...), details::get(option::End{"]"}, std::forward(args)...), details::get( - option::PrefixText{""}, std::forward(args)...), + option::PrefixText{}, std::forward(args)...), details::get( - option::PostfixText{""}, std::forward(args)...), + option::PostfixText{}, std::forward(args)...), + details::get( + option::MaxPostfixTextLen{0}, std::forward(args)...), details::get( option::ShowPercentage{true}, std::forward(args)...), details::get( option::ShowElapsedTime{false}, std::forward(args)...), details::get( option::ShowRemainingTime{false}, std::forward(args)...), - details::get(option::Completed{false}, - std::forward(args)...), details::get( option::SavedStartTime{false}, std::forward(args)...), - details::get( - option::MaxPostfixTextLen{0}, std::forward(args)...), - details::get( - option::FontStyles{std::vector{}}, std::forward(args)...), details::get( option::MaxProgress{100}, std::forward(args)...), + details::get(option::Completed{false}, + std::forward(args)...), + details::get( + option::ForegroundColor{Color::unspecified}, std::forward(args)...), + details::get( + option::FontStyles{std::vector{}}, std::forward(args)...), details::get(option::Stream{std::cout}, std::forward(args)...)) {} @@ -102,10 +106,10 @@ class BlockProgressBar { } } - void set_progress(size_t value) { + void set_progress(size_t new_progress) { { std::lock_guard lock{mutex_}; - tick_ = value; + tick_ = new_progress; } save_start_time(); print_progress(); @@ -145,8 +149,8 @@ class BlockProgressBar { } Settings settings_; - float progress_{0.0}; size_t tick_{0}; + float progress_{0.0}; std::chrono::time_point start_time_point_; std::mutex mutex_; @@ -174,14 +178,11 @@ class BlockProgressBar { std::pair get_postfix_text() { std::stringstream os; - const auto max_progress = get_value(); - progress_ = static_cast(tick_)/max_progress; auto now = std::chrono::high_resolution_clock::now(); auto elapsed = std::chrono::duration_cast(now - start_time_point_); if (get_value()) { - os << " " << (std::min)(static_cast(progress_ * 100.0), size_t(100)) - << "%"; + os << " " << (std::min)(static_cast(progress_ * 100.0), size_t(100)) << "%"; } auto &saved_start_time = get_value(); @@ -202,9 +203,7 @@ class BlockProgressBar { if (saved_start_time) { auto eta = std::chrono::nanoseconds( - tick_ > 0 - ? static_cast(std::ceil(float(elapsed.count()) * progress_)) - : 0); + tick_ > 0 ? static_cast(std::ceil(float(elapsed.count()) / progress_)) : 0); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); details::write_duration(os, remaining); } else { @@ -228,13 +227,19 @@ class BlockProgressBar { void print_progress(bool from_multi_progress = false) { std::lock_guard lock{mutex_}; + if (get_value()) + return; + auto &os = get_value(); const auto max_progress = get_value(); + + progress_ = static_cast(tick_) / max_progress; + + if (tick_ >= max_progress) { + get_value() = true; + } if (multi_progress_mode_ && !from_multi_progress) { - if (tick_ > max_progress) { - get_value() = true; - } return; } @@ -268,7 +273,8 @@ class BlockProgressBar { const auto end_length = get_value().size(); const auto terminal_width = terminal_size().second; // prefix + bar_width + postfix should be <= terminal_width - const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); + const int remaining = + terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); if (prefix_length == -1 || postfix_length == -1) { os << "\r"; } else if (remaining > 0) { @@ -278,9 +284,6 @@ class BlockProgressBar { } os.flush(); - if (tick_ > max_progress) { - get_value() = true; - } if (get_value() && !from_multi_progress) // Don't std::endl if calling from MultiProgress os << termcolor::reset << std::endl; diff --git a/include/indicators/cursor_control.hpp b/include/indicators/cursor_control.hpp index 641156f..d4c1bbb 100644 --- a/include/indicators/cursor_control.hpp +++ b/include/indicators/cursor_control.hpp @@ -1,66 +1,63 @@ - -#ifndef INDICATORS_CURSOR_CONTROL -#define INDICATORS_CURSOR_CONTROL - -#if defined(_MSC_VER) -#if !defined(NOMINMAX) -#define NOMINMAX -#endif -#include -#include -#else -#include -#endif - -namespace indicators { - -#if defined(_MSC_VER) - -static inline void show_console_cursor(bool const show) { - HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); - - CONSOLE_CURSOR_INFO cursorInfo; - - GetConsoleCursorInfo(out, &cursorInfo); - cursorInfo.bVisible = show; // set the cursor visibility - SetConsoleCursorInfo(out, &cursorInfo); -} - -static inline void erase_line() { - auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE); - if (!hStdout) - return; - - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo(hStdout, &csbiInfo); - - COORD cursor; - - cursor.X = 0; - cursor.Y = csbiInfo.dwCursorPosition.Y; - - DWORD count = 0; - - FillConsoleOutputCharacterA(hStdout, ' ', csbiInfo.dwSize.X, cursor, &count); - - FillConsoleOutputAttribute(hStdout, csbiInfo.wAttributes, csbiInfo.dwSize.X, - cursor, &count); - - SetConsoleCursorPosition(hStdout, cursor); -} - -#else - -static inline void show_console_cursor(bool const show) { - std::fputs(show ? "\033[?25h" : "\033[?25l", stdout); -} - -static inline void erase_line() { - std::fputs("\r\033[K", stdout); -} - -#endif - -} // namespace indicators - + +#ifndef INDICATORS_CURSOR_CONTROL +#define INDICATORS_CURSOR_CONTROL + +#if defined(_MSC_VER) +#if !defined(NOMINMAX) +#define NOMINMAX +#endif +#include +#include +#else +#include +#endif + +namespace indicators { + +#if defined(_MSC_VER) + +static inline void show_console_cursor(bool const show) { + HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); + + CONSOLE_CURSOR_INFO cursorInfo; + + GetConsoleCursorInfo(out, &cursorInfo); + cursorInfo.bVisible = show; // set the cursor visibility + SetConsoleCursorInfo(out, &cursorInfo); +} + +static inline void erase_line() { + auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + if (!hStdout) + return; + + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(hStdout, &csbiInfo); + + COORD cursor; + + cursor.X = 0; + cursor.Y = csbiInfo.dwCursorPosition.Y; + + DWORD count = 0; + + FillConsoleOutputCharacterA(hStdout, ' ', csbiInfo.dwSize.X, cursor, &count); + + FillConsoleOutputAttribute(hStdout, csbiInfo.wAttributes, csbiInfo.dwSize.X, cursor, &count); + + SetConsoleCursorPosition(hStdout, cursor); +} + +#else + +static inline void show_console_cursor(bool const show) { + std::fputs(show ? "\033[?25h" : "\033[?25l", stdout); +} + +static inline void erase_line() { std::fputs("\r\033[K", stdout); } + +#endif + +} // namespace indicators + #endif \ No newline at end of file diff --git a/include/indicators/cursor_movement.hpp b/include/indicators/cursor_movement.hpp index 1081b7f..97af23f 100644 --- a/include/indicators/cursor_movement.hpp +++ b/include/indicators/cursor_movement.hpp @@ -1,50 +1,50 @@ - -#ifndef INDICATORS_CURSOR_MOVEMENT -#define INDICATORS_CURSOR_MOVEMENT - -#if defined(_MSC_VER) -#if !defined(NOMINMAX) -#define NOMINMAX -#endif -#include -#include -#else -#include -#endif - -namespace indicators { - -#ifdef _MSC_VER - -static inline void move(int x, int y) { - auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE); - if (!hStdout) - return; - - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo(hStdout, &csbiInfo); - - COORD cursor; - - cursor.X = csbiInfo.dwCursorPosition.X + x; - cursor.Y = csbiInfo.dwCursorPosition.Y + y; - SetConsoleCursorPosition(hStdout, cursor); -} - -static inline void move_up(int lines) { move(0, -lines); } -static inline void move_down(int lines) { move(0, -lines); } -static inline void move_right(int cols) { move(cols, 0); } -static inline void move_left(int cols) { move(-cols, 0); } - -#else - -static inline void move_up(int lines) { std::cout << "\033[" << lines << "A"; } -static inline void move_down(int lines) { std::cout << "\033[" << lines << "B"; } -static inline void move_right(int cols) { std::cout << "\033[" << cols << "C"; } -static inline void move_left(int cols) { std::cout << "\033[" << cols << "D"; } - -#endif - -} // namespace indicators - + +#ifndef INDICATORS_CURSOR_MOVEMENT +#define INDICATORS_CURSOR_MOVEMENT + +#if defined(_MSC_VER) +#if !defined(NOMINMAX) +#define NOMINMAX +#endif +#include +#include +#else +#include +#endif + +namespace indicators { + +#ifdef _MSC_VER + +static inline void move(int x, int y) { + auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + if (!hStdout) + return; + + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(hStdout, &csbiInfo); + + COORD cursor; + + cursor.X = csbiInfo.dwCursorPosition.X + x; + cursor.Y = csbiInfo.dwCursorPosition.Y + y; + SetConsoleCursorPosition(hStdout, cursor); +} + +static inline void move_up(int lines) { move(0, -lines); } +static inline void move_down(int lines) { move(0, -lines); } +static inline void move_right(int cols) { move(cols, 0); } +static inline void move_left(int cols) { move(-cols, 0); } + +#else + +static inline void move_up(int lines) { std::cout << "\033[" << lines << "A"; } +static inline void move_down(int lines) { std::cout << "\033[" << lines << "B"; } +static inline void move_right(int cols) { std::cout << "\033[" << cols << "C"; } +static inline void move_left(int cols) { std::cout << "\033[" << cols << "D"; } + +#endif + +} // namespace indicators + #endif \ No newline at end of file diff --git a/include/indicators/display_width.hpp b/include/indicators/display_width.hpp index b1283ff..ae9f5e0 100644 --- a/include/indicators/display_width.hpp +++ b/include/indicators/display_width.hpp @@ -134,54 +134,42 @@ static inline int mk_wcwidth(wchar_t ucs) { /* sorted list of non-overlapping intervals of non-spacing characters */ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ static const struct interval combining[] = { - {0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489}, - {0x0591, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, - {0x05C4, 0x05C5}, {0x05C7, 0x05C7}, {0x0600, 0x0603}, - {0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670}, - {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, - {0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A}, - {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, {0x0901, 0x0902}, - {0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D}, - {0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981}, - {0x09BC, 0x09BC}, {0x09C1, 0x09C4}, {0x09CD, 0x09CD}, - {0x09E2, 0x09E3}, {0x0A01, 0x0A02}, {0x0A3C, 0x0A3C}, - {0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, - {0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC}, - {0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD}, - {0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, {0x0B3C, 0x0B3C}, - {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D}, - {0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0}, - {0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48}, - {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0CBC, 0x0CBC}, - {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD}, - {0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D}, - {0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, - {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, - {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, - {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, - {0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F71, 0x0F7E}, - {0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F90, 0x0F97}, - {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030}, - {0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039}, - {0x1058, 0x1059}, {0x1160, 0x11FF}, {0x135F, 0x135F}, - {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753}, - {0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD}, - {0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD}, - {0x180B, 0x180D}, {0x18A9, 0x18A9}, {0x1920, 0x1922}, - {0x1927, 0x1928}, {0x1932, 0x1932}, {0x1939, 0x193B}, - {0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34}, - {0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42}, - {0x1B6B, 0x1B73}, {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF}, - {0x200B, 0x200F}, {0x202A, 0x202E}, {0x2060, 0x2063}, - {0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F}, - {0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B}, - {0xA825, 0xA826}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F}, - {0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, - {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, - {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169}, - {0x1D173, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, - {0x1D242, 0x1D244}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F}, - {0xE0100, 0xE01EF}}; + {0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489}, {0x0591, 0x05BD}, + {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C5}, {0x05C7, 0x05C7}, + {0x0600, 0x0603}, {0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670}, + {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, {0x070F, 0x070F}, + {0x0711, 0x0711}, {0x0730, 0x074A}, {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, + {0x0901, 0x0902}, {0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D}, + {0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981}, {0x09BC, 0x09BC}, + {0x09C1, 0x09C4}, {0x09CD, 0x09CD}, {0x09E2, 0x09E3}, {0x0A01, 0x0A02}, + {0x0A3C, 0x0A3C}, {0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, + {0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC}, {0x0AC1, 0x0AC5}, + {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD}, {0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, + {0x0B3C, 0x0B3C}, {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D}, + {0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0}, {0x0BCD, 0x0BCD}, + {0x0C3E, 0x0C40}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, + {0x0CBC, 0x0CBC}, {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD}, + {0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D}, {0x0DCA, 0x0DCA}, + {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, + {0x0E47, 0x0E4E}, {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, + {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, {0x0F37, 0x0F37}, + {0x0F39, 0x0F39}, {0x0F71, 0x0F7E}, {0x0F80, 0x0F84}, {0x0F86, 0x0F87}, + {0x0F90, 0x0F97}, {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030}, + {0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039}, {0x1058, 0x1059}, + {0x1160, 0x11FF}, {0x135F, 0x135F}, {0x1712, 0x1714}, {0x1732, 0x1734}, + {0x1752, 0x1753}, {0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD}, + {0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD}, {0x180B, 0x180D}, + {0x18A9, 0x18A9}, {0x1920, 0x1922}, {0x1927, 0x1928}, {0x1932, 0x1932}, + {0x1939, 0x193B}, {0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34}, + {0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42}, {0x1B6B, 0x1B73}, + {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF}, {0x200B, 0x200F}, {0x202A, 0x202E}, + {0x2060, 0x2063}, {0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F}, + {0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B}, {0xA825, 0xA826}, + {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F}, {0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, + {0xFFF9, 0xFFFB}, {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, + {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169}, {0x1D173, 0x1D182}, + {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0xE0001, 0xE0001}, + {0xE0020, 0xE007F}, {0xE0100, 0xE01EF}}; /* test for 8-bit control characters */ if (ucs == 0) @@ -195,20 +183,17 @@ static inline int mk_wcwidth(wchar_t ucs) { /* if we arrive here, ucs is not a combining or C0/C1 control character */ - return 1 + - (ucs >= 0x1100 && - (ucs <= 0x115f || /* Hangul Jamo init. consonants */ - ucs == 0x2329 || ucs == 0x232a || - (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) || /* CJK ... Yi */ - (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ - (ucs >= 0xf900 && - ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ - (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ - (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ - (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ - (ucs >= 0xffe0 && ucs <= 0xffe6) || - (ucs >= 0x20000 && ucs <= 0x2fffd) || - (ucs >= 0x30000 && ucs <= 0x3fffd))); + return 1 + (ucs >= 0x1100 && + (ucs <= 0x115f || /* Hangul Jamo init. consonants */ + ucs == 0x2329 || ucs == 0x232a || + (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) || /* CJK ... Yi */ + (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ + (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ + (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ + (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ + (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ + (ucs >= 0xffe0 && ucs <= 0xffe6) || (ucs >= 0x20000 && ucs <= 0x2fffd) || + (ucs >= 0x30000 && ucs <= 0x3fffd))); } static inline int mk_wcswidth(const wchar_t *pwcs, size_t n) { @@ -236,58 +221,38 @@ static inline int mk_wcwidth_cjk(wchar_t ucs) { /* sorted list of non-overlapping intervals of East Asian Ambiguous * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */ static const struct interval ambiguous[] = { - {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, - {0x00AA, 0x00AA}, {0x00AE, 0x00AE}, {0x00B0, 0x00B4}, - {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6}, - {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1}, - {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, - {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, - {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101}, - {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B}, - {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133}, - {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144}, - {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153}, - {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE}, - {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, - {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, - {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261}, - {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB}, - {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB}, - {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0391, 0x03A1}, - {0x03A3, 0x03A9}, {0x03B1, 0x03C1}, {0x03C3, 0x03C9}, - {0x0401, 0x0401}, {0x0410, 0x044F}, {0x0451, 0x0451}, - {0x2010, 0x2010}, {0x2013, 0x2016}, {0x2018, 0x2019}, - {0x201C, 0x201D}, {0x2020, 0x2022}, {0x2024, 0x2027}, - {0x2030, 0x2030}, {0x2032, 0x2033}, {0x2035, 0x2035}, - {0x203B, 0x203B}, {0x203E, 0x203E}, {0x2074, 0x2074}, - {0x207F, 0x207F}, {0x2081, 0x2084}, {0x20AC, 0x20AC}, - {0x2103, 0x2103}, {0x2105, 0x2105}, {0x2109, 0x2109}, - {0x2113, 0x2113}, {0x2116, 0x2116}, {0x2121, 0x2122}, - {0x2126, 0x2126}, {0x212B, 0x212B}, {0x2153, 0x2154}, - {0x215B, 0x215E}, {0x2160, 0x216B}, {0x2170, 0x2179}, - {0x2190, 0x2199}, {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, - {0x21D4, 0x21D4}, {0x21E7, 0x21E7}, {0x2200, 0x2200}, - {0x2202, 0x2203}, {0x2207, 0x2208}, {0x220B, 0x220B}, - {0x220F, 0x220F}, {0x2211, 0x2211}, {0x2215, 0x2215}, - {0x221A, 0x221A}, {0x221D, 0x2220}, {0x2223, 0x2223}, - {0x2225, 0x2225}, {0x2227, 0x222C}, {0x222E, 0x222E}, - {0x2234, 0x2237}, {0x223C, 0x223D}, {0x2248, 0x2248}, - {0x224C, 0x224C}, {0x2252, 0x2252}, {0x2260, 0x2261}, - {0x2264, 0x2267}, {0x226A, 0x226B}, {0x226E, 0x226F}, - {0x2282, 0x2283}, {0x2286, 0x2287}, {0x2295, 0x2295}, - {0x2299, 0x2299}, {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, - {0x2312, 0x2312}, {0x2460, 0x24E9}, {0x24EB, 0x254B}, - {0x2550, 0x2573}, {0x2580, 0x258F}, {0x2592, 0x2595}, - {0x25A0, 0x25A1}, {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, - {0x25B6, 0x25B7}, {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, - {0x25C6, 0x25C8}, {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, - {0x25E2, 0x25E5}, {0x25EF, 0x25EF}, {0x2605, 0x2606}, - {0x2609, 0x2609}, {0x260E, 0x260F}, {0x2614, 0x2615}, - {0x261C, 0x261C}, {0x261E, 0x261E}, {0x2640, 0x2640}, - {0x2642, 0x2642}, {0x2660, 0x2661}, {0x2663, 0x2665}, - {0x2667, 0x266A}, {0x266C, 0x266D}, {0x266F, 0x266F}, - {0x273D, 0x273D}, {0x2776, 0x277F}, {0xE000, 0xF8FF}, - {0xFFFD, 0xFFFD}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}}; + {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, {0x00AA, 0x00AA}, {0x00AE, 0x00AE}, + {0x00B0, 0x00B4}, {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6}, {0x00D0, 0x00D0}, + {0x00D7, 0x00D8}, {0x00DE, 0x00E1}, {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, + {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, + {0x0101, 0x0101}, {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B}, {0x0126, 0x0127}, + {0x012B, 0x012B}, {0x0131, 0x0133}, {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144}, + {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153}, {0x0166, 0x0167}, {0x016B, 0x016B}, + {0x01CE, 0x01CE}, {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, {0x01D6, 0x01D6}, + {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261}, + {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB}, {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, + {0x02D8, 0x02DB}, {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0391, 0x03A1}, {0x03A3, 0x03A9}, + {0x03B1, 0x03C1}, {0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F}, {0x0451, 0x0451}, + {0x2010, 0x2010}, {0x2013, 0x2016}, {0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022}, + {0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033}, {0x2035, 0x2035}, {0x203B, 0x203B}, + {0x203E, 0x203E}, {0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084}, {0x20AC, 0x20AC}, + {0x2103, 0x2103}, {0x2105, 0x2105}, {0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116}, + {0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B}, {0x2153, 0x2154}, {0x215B, 0x215E}, + {0x2160, 0x216B}, {0x2170, 0x2179}, {0x2190, 0x2199}, {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, + {0x21D4, 0x21D4}, {0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203}, {0x2207, 0x2208}, + {0x220B, 0x220B}, {0x220F, 0x220F}, {0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A}, + {0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225}, {0x2227, 0x222C}, {0x222E, 0x222E}, + {0x2234, 0x2237}, {0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C}, {0x2252, 0x2252}, + {0x2260, 0x2261}, {0x2264, 0x2267}, {0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283}, + {0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299}, {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, + {0x2312, 0x2312}, {0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573}, {0x2580, 0x258F}, + {0x2592, 0x2595}, {0x25A0, 0x25A1}, {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7}, + {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8}, {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, + {0x25E2, 0x25E5}, {0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609}, {0x260E, 0x260F}, + {0x2614, 0x2615}, {0x261C, 0x261C}, {0x261E, 0x261E}, {0x2640, 0x2640}, {0x2642, 0x2642}, + {0x2660, 0x2661}, {0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D}, {0x266F, 0x266F}, + {0x273D, 0x273D}, {0x2776, 0x277F}, {0xE000, 0xF8FF}, {0xFFFD, 0xFFFD}, {0xF0000, 0xFFFFD}, + {0x100000, 0x10FFFD}}; /* binary search in table of non-spacing characters */ if (bisearch(ucs, ambiguous, sizeof(ambiguous) / sizeof(struct interval) - 1)) @@ -310,36 +275,36 @@ static inline int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n) { // convert UTF-8 string to wstring #ifdef _MSC_VER -static inline std::wstring utf8_decode(const std::string& s) { - auto r = setlocale(LC_ALL, NULL); - std::string curLocale; - if (r) - curLocale = r; - const char* _Source = s.c_str(); - size_t _Dsize = std::strlen(_Source) + 1; - wchar_t* _Dest = new wchar_t[_Dsize]; - size_t _Osize; - mbstowcs_s(&_Osize, _Dest, _Dsize, _Source, _Dsize); - std::wstring result = _Dest; - delete[] _Dest; - setlocale(LC_ALL, curLocale.c_str()); - return result; +static inline std::wstring utf8_decode(const std::string &s) { + auto r = setlocale(LC_ALL, NULL); + std::string curLocale; + if (r) + curLocale = r; + const char *_Source = s.c_str(); + size_t _Dsize = std::strlen(_Source) + 1; + wchar_t *_Dest = new wchar_t[_Dsize]; + size_t _Osize; + mbstowcs_s(&_Osize, _Dest, _Dsize, _Source, _Dsize); + std::wstring result = _Dest; + delete[] _Dest; + setlocale(LC_ALL, curLocale.c_str()); + return result; } -#else -static inline std::wstring utf8_decode(const std::string& s) { - auto r = setlocale(LC_ALL, NULL); - std::string curLocale; - if (r) - curLocale = r; - const char* _Source = s.c_str(); - size_t _Dsize = mbstowcs(NULL, _Source, 0) + 1; - wchar_t* _Dest = new wchar_t[_Dsize]; - wmemset(_Dest, 0, _Dsize); - mbstowcs(_Dest, _Source, _Dsize); - std::wstring result = _Dest; - delete[] _Dest; - setlocale(LC_ALL, curLocale.c_str()); - return result; +#else +static inline std::wstring utf8_decode(const std::string &s) { + auto r = setlocale(LC_ALL, NULL); + std::string curLocale; + if (r) + curLocale = r; + const char *_Source = s.c_str(); + size_t _Dsize = mbstowcs(NULL, _Source, 0) + 1; + wchar_t *_Dest = new wchar_t[_Dsize]; + wmemset(_Dest, 0, _Dsize); + mbstowcs(_Dest, _Source, _Dsize); + std::wstring result = _Dest; + delete[] _Dest; + setlocale(LC_ALL, curLocale.c_str()); + return result; } #endif diff --git a/include/indicators/dynamic_progress.hpp b/include/indicators/dynamic_progress.hpp index 7e50ff6..7bd1431 100644 --- a/include/indicators/dynamic_progress.hpp +++ b/include/indicators/dynamic_progress.hpp @@ -5,10 +5,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -20,7 +20,7 @@ template class DynamicProgress { using Settings = std::tuple; public: - template explicit DynamicProgress(Indicators &&... bars) { + template explicit DynamicProgress(Indicators &&...bars) { (bars_.emplace_back(std::move(bars)), ...); for (auto &bar : bars_) { bar->multi_progress_mode_ = true; diff --git a/include/indicators/indeterminate_progress_bar.hpp b/include/indicators/indeterminate_progress_bar.hpp index f77dd5a..75791c6 100644 --- a/include/indicators/indeterminate_progress_bar.hpp +++ b/include/indicators/indeterminate_progress_bar.hpp @@ -2,33 +2,36 @@ #ifndef INDICATORS_INDETERMINATE_PROGRESS_BAR #define INDICATORS_INDETERMINATE_PROGRESS_BAR +#include #include +#include +#include #include #include #include #include -#include -#include -#include #include #include #include +#include #include #include #include #include -#include #include namespace indicators { class IndeterminateProgressBar { - using Settings = - std::tuple; - + // clang-format off + using Settings = std::tuple; + // clang-format on enum class Direction { forward, backward }; Direction direction_{Direction::forward}; @@ -38,13 +41,9 @@ class IndeterminateProgressBar { typename std::enable_if::type...>::value, void *>::type = nullptr> - explicit IndeterminateProgressBar(Args &&... args) + explicit IndeterminateProgressBar(Args &&...args) : settings_(details::get(option::BarWidth{100}, std::forward(args)...), - details::get( - option::PrefixText{}, std::forward(args)...), - details::get( - option::PostfixText{}, std::forward(args)...), details::get(option::Start{"["}, std::forward(args)...), details::get(option::End{"]"}, @@ -53,6 +52,10 @@ class IndeterminateProgressBar { std::forward(args)...), details::get(option::Lead{"<==>"}, std::forward(args)...), + details::get( + option::PrefixText{}, std::forward(args)...), + details::get( + option::PostfixText{}, std::forward(args)...), details::get( option::MaxPostfixTextLen{0}, std::forward(args)...), details::get(option::Completed{false}, @@ -70,7 +73,6 @@ class IndeterminateProgressBar { // ^^^^^^^^^^^^^^^^^ bar_width // ^^^^^^^^^^^^ (bar_width - len(lead)) // progress_ = bar_width - len(lead) - progress_ = 0; max_progress_ = get_value() - get_value().size() + get_value().size() + @@ -120,11 +122,11 @@ class IndeterminateProgressBar { if (get_value()) return; - progress_ += (direction_ == Direction::forward) ? 1 : -1; - if (direction_ == Direction::forward && progress_ == max_progress_) { + tick_ += (direction_ == Direction::forward) ? 1 : -1; + if (direction_ == Direction::forward && tick_ == max_progress_) { // time to go back direction_ = Direction::backward; - } else if (direction_ == Direction::backward && progress_ == 0) { + } else if (direction_ == Direction::backward && tick_ == 0) { direction_ = Direction::forward; } } @@ -150,9 +152,9 @@ class IndeterminateProgressBar { return details::get_value(settings_).value; } - size_t progress_{0}; - size_t max_progress_; Settings settings_; + size_t tick_{0}; + size_t max_progress_; std::chrono::nanoseconds elapsed_; std::mutex mutex_; @@ -203,7 +205,7 @@ class IndeterminateProgressBar { os, get_value(), get_value(), get_value()}; - writer.write(progress_); + writer.write(tick_); os << get_value(); @@ -218,7 +220,8 @@ class IndeterminateProgressBar { const auto end_length = get_value().size(); const auto terminal_width = terminal_size().second; // prefix + bar_width + postfix should be <= terminal_width - const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); + const int remaining = + terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); if (prefix_length == -1 || postfix_length == -1) { os << "\r"; } else if (remaining > 0) { @@ -236,4 +239,4 @@ class IndeterminateProgressBar { } // namespace indicators -#endif \ No newline at end of file +#endif diff --git a/include/indicators/multi_progress.hpp b/include/indicators/multi_progress.hpp index 16a9dc4..9391536 100644 --- a/include/indicators/multi_progress.hpp +++ b/include/indicators/multi_progress.hpp @@ -17,7 +17,7 @@ template class MultiProgress { public: template ::type> - explicit MultiProgress(Indicators &... bars) { + explicit MultiProgress(Indicators &...bars) { bars_ = {bars...}; for (auto &bar : bars_) { bar.get().multi_progress_mode_ = true; diff --git a/include/indicators/progress_bar.hpp b/include/indicators/progress_bar.hpp index ce22957..47a6bc0 100644 --- a/include/indicators/progress_bar.hpp +++ b/include/indicators/progress_bar.hpp @@ -2,19 +2,19 @@ #ifndef INDICATORS_PROGRESS_BAR #define INDICATORS_PROGRESS_BAR +#include #include +#include +#include #include #include #include #include -#include -#include -#include #include #include -#include #include +#include #include #include #include @@ -24,129 +24,117 @@ namespace indicators { class ProgressBar { - using Settings = - std::tuple; + // clang-format off + using Settings = std::tuple; + // clang-format on public: template ::type...>::value, - void *>::type = nullptr> - explicit ProgressBar(Args &&... args) + typename std::enable_if::type...>::value, + void *>::type = nullptr> + explicit ProgressBar(Args &&...args) : settings_( - details::get( - option::BarWidth{100}, std::forward(args)...), - details::get( - option::PrefixText{}, std::forward(args)...), - details::get( - option::PostfixText{}, std::forward(args)...), - details::get( - option::Start{"["}, std::forward(args)...), - details::get( - option::End{"]"}, std::forward(args)...), - details::get( - option::Fill{"="}, std::forward(args)...), - details::get( - option::Lead{">"}, std::forward(args)...), - details::get( - option::Remainder{" "}, std::forward(args)...), + details::get(option::BarWidth{100}, + std::forward(args)...), + details::get(option::Start{"["}, + std::forward(args)...), + details::get(option::End{"]"}, + std::forward(args)...), + details::get(option::Fill{"="}, + std::forward(args)...), + details::get(option::Lead{">"}, + std::forward(args)...), + details::get(option::Remainder{" "}, + std::forward(args)...), + details::get(option::PrefixText{}, + std::forward(args)...), + details::get(option::PostfixText{}, + std::forward(args)...), details::get( option::MaxPostfixTextLen{0}, std::forward(args)...), - details::get( - option::Completed{false}, std::forward(args)...), - details::get( - option::ShowPercentage{false}, std::forward(args)...), + details::get(option::ShowPercentage{false}, + std::forward(args)...), details::get( option::ShowElapsedTime{false}, std::forward(args)...), details::get( option::ShowRemainingTime{false}, std::forward(args)...), details::get( option::SavedStartTime{false}, std::forward(args)...), + details::get(option::MinProgress{0}, + std::forward(args)...), + details::get(option::MaxProgress{100}, + std::forward(args)...), + details::get(option::Completed{false}, + std::forward(args)...), + details::get( + option::ProgressType{ProgressType::incremental}, std::forward(args)...), details::get( - option::ForegroundColor{Color::unspecified}, - std::forward(args)...), + option::ForegroundColor{Color::unspecified}, std::forward(args)...), details::get( - option::FontStyles{std::vector{}}, - std::forward(args)...), - details::get( - option::MinProgress{0}, std::forward(args)...), - details::get( - option::MaxProgress{100}, std::forward(args)...), - details::get( - option::ProgressType{ProgressType::incremental}, - std::forward(args)...), - details::get( - option::Stream{std::cout}, std::forward(args)...)) { + option::FontStyles{std::vector{}}, std::forward(args)...), + details::get(option::Stream{std::cout}, + std::forward(args)...)) { // if progress is incremental, start from min_progress // else start from max_progress const auto type = get_value(); if (type == ProgressType::incremental) - progress_ = get_value(); + tick_ = get_value(); else - progress_ = get_value(); + tick_ = get_value(); } template void set_option(details::Setting &&setting) { - static_assert( - !std::is_same( - std::declval()))>::type>::value, - "Setting has wrong type!"); + static_assert(!std::is_same( + std::declval()))>::type>::value, + "Setting has wrong type!"); std::lock_guard lock(mutex_); get_value() = std::move(setting).value; } template void set_option(const details::Setting &setting) { - static_assert( - !std::is_same( - std::declval()))>::type>::value, - "Setting has wrong type!"); + static_assert(!std::is_same( + std::declval()))>::type>::value, + "Setting has wrong type!"); std::lock_guard lock(mutex_); get_value() = setting.value; } - void - set_option(const details::Setting< - std::string, details::ProgressBarOption::postfix_text> &setting) { + void set_option( + const details::Setting &setting) { std::lock_guard lock(mutex_); get_value() = setting.value; - if (setting.value.length() > - get_value()) { - get_value() = - setting.value.length(); + if (setting.value.length() > get_value()) { + get_value() = setting.value.length(); } } - void set_option( - details::Setting - &&setting) { + void + set_option(details::Setting &&setting) { std::lock_guard lock(mutex_); - get_value() = - std::move(setting).value; + get_value() = std::move(setting).value; auto &new_value = get_value(); - if (new_value.length() > - get_value()) { - get_value() = - new_value.length(); + if (new_value.length() > get_value()) { + get_value() = new_value.length(); } } void set_progress(size_t new_progress) { { - std::lock_guard lock(mutex_); - progress_ = new_progress; + std::lock_guard lock{mutex_}; + tick_ = new_progress; } - save_start_time(); print_progress(); } @@ -156,9 +144,9 @@ class ProgressBar { std::lock_guard lock{mutex_}; const auto type = get_value(); if (type == ProgressType::incremental) - progress_ += 1; + tick_++; else - progress_ -= 1; + tick_--; } save_start_time(); print_progress(); @@ -166,14 +154,10 @@ class ProgressBar { size_t current() { std::lock_guard lock{mutex_}; - return (std::min)( - progress_, - size_t(get_value())); + return (std::min)(tick_, size_t(get_value())); } - bool is_completed() const { - return get_value(); - } + bool is_completed() const { return get_value(); } void mark_as_completed() { get_value() = true; @@ -182,20 +166,19 @@ class ProgressBar { private: template - auto get_value() - -> decltype((details::get_value(std::declval()).value)) { + auto get_value() -> decltype((details::get_value(std::declval()).value)) { return details::get_value(settings_).value; } template - auto get_value() const -> decltype( - (details::get_value(std::declval()).value)) { + auto get_value() const + -> decltype((details::get_value(std::declval()).value)) { return details::get_value(settings_).value; } - size_t progress_{0}; Settings settings_; - std::chrono::nanoseconds elapsed_; + size_t tick_{0}; + float progress_{0.0}; std::chrono::time_point start_time_point_; std::mutex mutex_; @@ -204,12 +187,9 @@ class ProgressBar { std::atomic multi_progress_mode_{false}; void save_start_time() { - auto &show_elapsed_time = - get_value(); - auto &saved_start_time = - get_value(); - auto &show_remaining_time = - get_value(); + auto &show_elapsed_time = get_value(); + auto &saved_start_time = get_value(); + auto &show_remaining_time = get_value(); if ((show_elapsed_time || show_remaining_time) && !saved_start_time) { start_time_point_ = std::chrono::high_resolution_clock::now(); saved_start_time = true; @@ -226,24 +206,19 @@ class ProgressBar { std::pair get_postfix_text() { std::stringstream os; - const auto max_progress = - get_value(); + auto now = std::chrono::high_resolution_clock::now(); + auto elapsed = std::chrono::duration_cast(now - start_time_point_); if (get_value()) { - os << " " - << (std::min)(static_cast(static_cast(progress_) / - max_progress * 100), - size_t(100)) - << "%"; + os << " " << (std::min)(static_cast(progress_ * 100.0), size_t(100)) << "%"; } - auto &saved_start_time = - get_value(); + auto &saved_start_time = get_value(); if (get_value()) { os << " ["; if (saved_start_time) - details::write_duration(os, elapsed_); + details::write_duration(os, elapsed); else os << "00:00s"; } @@ -256,11 +231,8 @@ class ProgressBar { if (saved_start_time) { auto eta = std::chrono::nanoseconds( - progress_ > 0 - ? static_cast(std::ceil(float(elapsed_.count()) * - max_progress / progress_)) - : 0); - auto remaining = eta > elapsed_ ? (eta - elapsed_) : (elapsed_ - eta); + tick_ > 0 ? static_cast(std::ceil(float(elapsed.count()) / progress_)) : 0); + auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); details::write_duration(os, remaining); } else { os << "00:00s"; @@ -283,29 +255,27 @@ class ProgressBar { void print_progress(bool from_multi_progress = false) { std::lock_guard lock{mutex_}; + if (get_value()) + return; + auto &os = get_value(); const auto type = get_value(); - const auto min_progress = - get_value(); - const auto max_progress = - get_value(); + const auto min_progress = get_value(); + const auto max_progress = get_value(); + + progress_ = static_cast(tick_) / max_progress; + + if ((type == ProgressType::incremental && tick_ >= max_progress) || + (type == ProgressType::decremental && tick_ <= min_progress)) { + get_value() = true; + } if (multi_progress_mode_ && !from_multi_progress) { - if ((type == ProgressType::incremental && progress_ >= max_progress) || - (type == ProgressType::decremental && progress_ <= min_progress)) { - get_value() = true; - } return; } - auto now = std::chrono::high_resolution_clock::now(); - if (!get_value()) - elapsed_ = std::chrono::duration_cast( - now - start_time_point_); - if (get_value() != - Color::unspecified) - details::set_stream_color( - os, get_value()); + if (get_value() != Color::unspecified) + details::set_stream_color(os, get_value()); for (auto &style : get_value()) details::set_font_style(os, style); @@ -317,12 +287,11 @@ class ProgressBar { os << get_value(); - details::ProgressScaleWriter writer{ - os, get_value(), - get_value(), - get_value(), - get_value()}; - writer.write(double(progress_) / double(max_progress) * 100.0f); + details::ProgressScaleWriter writer{os, get_value(), + get_value(), + get_value(), + get_value()}; + writer.write(progress_ * 100); os << get_value(); @@ -337,7 +306,8 @@ class ProgressBar { const auto end_length = get_value().size(); const auto terminal_width = terminal_size().second; // prefix + bar_width + postfix should be <= terminal_width - const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); + const int remaining = + terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); if (prefix_length == -1 || postfix_length == -1) { os << "\r"; } else if (remaining > 0) { @@ -347,10 +317,6 @@ class ProgressBar { } os.flush(); - if ((type == ProgressType::incremental && progress_ >= max_progress) || - (type == ProgressType::decremental && progress_ <= min_progress)) { - get_value() = true; - } if (get_value() && !from_multi_progress) // Don't std::endl if calling from MultiProgress os << termcolor::reset << std::endl; @@ -359,4 +325,4 @@ class ProgressBar { } // namespace indicators -#endif \ No newline at end of file +#endif diff --git a/include/indicators/progress_spinner.hpp b/include/indicators/progress_spinner.hpp index 62d5b14..cdf7321 100644 --- a/include/indicators/progress_spinner.hpp +++ b/include/indicators/progress_spinner.hpp @@ -2,14 +2,14 @@ #ifndef INDICATORS_PROGRESS_SPINNER #define INDICATORS_PROGRESS_SPINNER +#include #include +#include #include #include #include #include -#include -#include #include #include #include @@ -21,48 +21,51 @@ namespace indicators { class ProgressSpinner { - using Settings = - std::tuple; + // clang-format off + using Settings = std::tuple; + // clang-format on public: template ::type...>::value, void *>::type = nullptr> - explicit ProgressSpinner(Args &&... args) + explicit ProgressSpinner(Args &&...args) : settings_( - details::get( - option::ForegroundColor{Color::unspecified}, std::forward(args)...), + details::get(option::ShowSpinner{true}, + std::forward(args)...), + details::get( + option::SpinnerStates{ + std::vector{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}}, + std::forward(args)...), details::get(option::PrefixText{}, std::forward(args)...), details::get(option::PostfixText{}, std::forward(args)...), + details::get( + option::MaxPostfixTextLen{0}, std::forward(args)...), details::get(option::ShowPercentage{true}, std::forward(args)...), details::get( option::ShowElapsedTime{false}, std::forward(args)...), details::get( option::ShowRemainingTime{false}, std::forward(args)...), - details::get(option::ShowSpinner{true}, - std::forward(args)...), details::get( option::SavedStartTime{false}, std::forward(args)...), + details::get(option::MaxProgress{100}, + std::forward(args)...), details::get(option::Completed{false}, std::forward(args)...), - details::get( - option::MaxPostfixTextLen{0}, std::forward(args)...), - details::get( - option::SpinnerStates{ - std::vector{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}}, - std::forward(args)...), + details::get( + option::ForegroundColor{Color::unspecified}, std::forward(args)...), details::get( option::FontStyles{std::vector{}}, std::forward(args)...), - details::get(option::MaxProgress{100}, - std::forward(args)...), details::get(option::Stream{std::cout}, std::forward(args)...)) {} @@ -103,10 +106,10 @@ class ProgressSpinner { } } - void set_progress(size_t value) { + void set_progress(size_t new_progress) { { std::lock_guard lock{mutex_}; - progress_ = value; + tick_ = new_progress; } save_start_time(); print_progress(); @@ -115,7 +118,7 @@ class ProgressSpinner { void tick() { { std::lock_guard lock{mutex_}; - progress_ += 1; + tick_++; } save_start_time(); print_progress(); @@ -123,7 +126,7 @@ class ProgressSpinner { size_t current() { std::lock_guard lock{mutex_}; - return (std::min)(progress_, size_t(get_value())); + return (std::min)(tick_, size_t(get_value())); } bool is_completed() const { return get_value(); } @@ -134,12 +137,6 @@ class ProgressSpinner { } private: - Settings settings_; - size_t progress_{0}; - size_t index_{0}; - std::chrono::time_point start_time_point_; - std::mutex mutex_; - template auto get_value() -> decltype((details::get_value(std::declval()).value)) { return details::get_value(settings_).value; @@ -151,6 +148,13 @@ class ProgressSpinner { return details::get_value(settings_).value; } + Settings settings_; + size_t tick_{0}; + size_t index_{0}; + float progress_{0.0}; + std::chrono::time_point start_time_point_; + std::mutex mutex_; + void save_start_time() { auto &show_elapsed_time = get_value(); auto &show_remaining_time = get_value(); @@ -168,6 +172,9 @@ class ProgressSpinner { auto &os = get_value(); const auto max_progress = get_value(); + + progress_ = static_cast(tick_) / max_progress; + auto now = std::chrono::high_resolution_clock::now(); auto elapsed = std::chrono::duration_cast(now - start_time_point_); @@ -182,7 +189,7 @@ class ProgressSpinner { os << get_value() [index_ % get_value().size()]; if (get_value()) { - os << " " << std::size_t(progress_ / double(max_progress) * 100) << "%"; + os << " " << std::size_t(progress_ * 100) << "%"; } if (get_value()) { @@ -196,10 +203,7 @@ class ProgressSpinner { else os << " ["; auto eta = std::chrono::nanoseconds( - progress_ > 0 - ? static_cast(std::ceil(float(elapsed.count()) * - max_progress / progress_)) - : 0); + tick_ > 0 ? static_cast(std::ceil(float(elapsed.count()) / progress_)) : 0); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); details::write_duration(os, remaining); os << "]"; @@ -214,7 +218,7 @@ class ProgressSpinner { << std::string(get_value(), ' ') << "\r"; os.flush(); index_ += 1; - if (progress_ > max_progress) { + if (tick_ > max_progress) { get_value() = true; } if (get_value()) @@ -224,4 +228,4 @@ class ProgressSpinner { } // namespace indicators -#endif \ No newline at end of file +#endif diff --git a/include/indicators/setting.hpp b/include/indicators/setting.hpp index 7298258..a6687ad 100644 --- a/include/indicators/setting.hpp +++ b/include/indicators/setting.hpp @@ -44,9 +44,13 @@ namespace details { template struct if_else; -template <> struct if_else { using type = std::true_type; }; +template <> struct if_else { + using type = std::true_type; +}; -template <> struct if_else { using type = std::false_type; }; +template <> struct if_else { + using type = std::false_type; +}; template struct if_else_type; @@ -103,7 +107,7 @@ enum class ProgressBarOption { template struct Setting { template ::value>::type> - explicit Setting(Args &&... args) : value(std::forward(args)...) {} + explicit Setting(Args &&...args) : value(std::forward(args)...) {} Setting(const Setting &) = default; Setting(Setting &&) = default; @@ -134,21 +138,23 @@ template struct are_settings_from_tuple : if_else...>::value>::type {}; -template struct always_true { static constexpr auto value = true; }; +template struct always_true { + static constexpr auto value = true; +}; template Default &&get_impl(Default &&def) { return std::forward(def); } template -auto get_impl(Default && /*def*/, T &&first, Args &&... /*tail*/) -> +auto get_impl(Default && /*def*/, T &&first, Args &&.../*tail*/) -> typename std::enable_if<(std::decay::type::id == Id), decltype(std::forward(first))>::type { return std::forward(first); } template -auto get_impl(Default &&def, T && /*first*/, Args &&... tail) -> +auto get_impl(Default &&def, T && /*first*/, Args &&...tail) -> typename std::enable_if<(std::decay::type::id != Id), decltype(get_impl(std::forward(def), std::forward(tail)...))>::type { @@ -157,7 +163,7 @@ auto get_impl(Default &&def, T && /*first*/, Args &&... tail) -> template ::value, void>::type> -auto get(Default &&def, Args &&... args) +auto get(Default &&def, Args &&...args) -> decltype(details::get_impl(std::forward(def), std::forward(args)...)) { return details::get_impl(std::forward(def), std::forward(args)...); } diff --git a/include/indicators/termcolor.hpp b/include/indicators/termcolor.hpp index 1a5a813..4320806 100644 --- a/include/indicators/termcolor.hpp +++ b/include/indicators/termcolor.hpp @@ -12,906 +12,699 @@ #ifndef TERMCOLOR_HPP_ #define TERMCOLOR_HPP_ -#include -#include #include +#include +#include // Detect target's platform and set some macros in order to wrap platform // specific code this library depends on. #if defined(_WIN32) || defined(_WIN64) -# define TERMCOLOR_TARGET_WINDOWS +#define TERMCOLOR_TARGET_WINDOWS #elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) -# define TERMCOLOR_TARGET_POSIX +#define TERMCOLOR_TARGET_POSIX #endif // If implementation has not been explicitly set, try to choose one based on // target platform. -#if !defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) && !defined(TERMCOLOR_USE_WINDOWS_API) && !defined(TERMCOLOR_USE_NOOP) -# if defined(TERMCOLOR_TARGET_POSIX) -# define TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES -# define TERMCOLOR_AUTODETECTED_IMPLEMENTATION -# elif defined(TERMCOLOR_TARGET_WINDOWS) -# define TERMCOLOR_USE_WINDOWS_API -# define TERMCOLOR_AUTODETECTED_IMPLEMENTATION -# endif +#if !defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) && !defined(TERMCOLOR_USE_WINDOWS_API) && \ + !defined(TERMCOLOR_USE_NOOP) +#if defined(TERMCOLOR_TARGET_POSIX) +#define TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES +#define TERMCOLOR_AUTODETECTED_IMPLEMENTATION +#elif defined(TERMCOLOR_TARGET_WINDOWS) +#define TERMCOLOR_USE_WINDOWS_API +#define TERMCOLOR_AUTODETECTED_IMPLEMENTATION +#endif #endif // These headers provide isatty()/fileno() functions, which are used for // testing whether a standard stream refers to the terminal. #if defined(TERMCOLOR_TARGET_POSIX) -# include +#include #elif defined(TERMCOLOR_TARGET_WINDOWS) #if defined(_MSC_VER) #if !defined(NOMINMAX) #define NOMINMAX #endif #endif -# include -# include -#endif - - -namespace termcolor -{ - // Forward declaration of the `_internal` namespace. - // All comments are below. - namespace _internal - { - inline int colorize_index(); - inline FILE* get_standard_stream(const std::ostream& stream); - inline bool is_colorized(std::ostream& stream); - inline bool is_atty(const std::ostream& stream); - - #if defined(TERMCOLOR_TARGET_WINDOWS) - inline void win_change_attributes(std::ostream& stream, int foreground, int background=-1); - #endif - } - - inline - std::ostream& colorize(std::ostream& stream) - { - stream.iword(_internal::colorize_index()) = 1L; - return stream; - } - - inline - std::ostream& nocolorize(std::ostream& stream) - { - stream.iword(_internal::colorize_index()) = 0L; - return stream; - } - - inline - std::ostream& reset(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[00m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, -1); - #endif - } - return stream; - } - - inline - std::ostream& bold(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[1m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - inline - std::ostream& dark(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[2m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - inline - std::ostream& italic(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[3m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - inline - std::ostream& underline(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[4m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, COMMON_LVB_UNDERSCORE); - #endif - } - return stream; - } - - inline - std::ostream& blink(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[5m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - inline - std::ostream& reverse(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[7m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - inline - std::ostream& concealed(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[8m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - inline - std::ostream& crossed(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[9m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - template inline - std::ostream& color(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - char command[12]; - std::snprintf(command, sizeof(command), "\033[38;5;%dm", code); - stream << command; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - template inline - std::ostream& on_color(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - char command[12]; - std::snprintf(command, sizeof(command), "\033[48;5;%dm", code); - stream << command; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - template inline - std::ostream& color(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - char command[20]; - std::snprintf(command, sizeof(command), "\033[38;2;%d;%d;%dm", r, g, b); - stream << command; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - template inline - std::ostream& on_color(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - char command[20]; - std::snprintf(command, sizeof(command), "\033[48;2;%d;%d;%dm", r, g, b); - stream << command; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } - - inline - std::ostream& grey(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[30m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - 0 // grey (black) - ); - #endif - } - return stream; - } - - inline - std::ostream& red(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[31m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_RED - ); - #endif - } - return stream; - } - - inline - std::ostream& green(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[32m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_GREEN - ); - #endif - } - return stream; - } - - inline - std::ostream& yellow(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[33m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_GREEN | FOREGROUND_RED - ); - #endif - } - return stream; - } - - inline - std::ostream& blue(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[34m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE - ); - #endif - } - return stream; - } - - inline - std::ostream& magenta(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[35m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_RED - ); - #endif - } - return stream; - } - - inline - std::ostream& cyan(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[36m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_GREEN - ); - #endif - } - return stream; - } - - inline - std::ostream& white(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[37m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED - ); - #endif - } - return stream; - } - - - inline - std::ostream& bright_grey(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[90m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - 0 | FOREGROUND_INTENSITY // grey (black) - ); - #endif - } - return stream; - } - - inline - std::ostream& bright_red(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[91m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_RED | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& bright_green(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[92m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_GREEN | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& bright_yellow(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[93m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& bright_blue(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[94m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& bright_magenta(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[95m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& bright_cyan(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[96m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& bright_white(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[97m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } - - - inline - std::ostream& on_grey(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[40m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - 0 // grey (black) - ); - #endif - } - return stream; - } - - inline - std::ostream& on_red(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[41m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_RED - ); - #endif - } - return stream; - } - - inline - std::ostream& on_green(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[42m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN - ); - #endif - } - return stream; - } - - inline - std::ostream& on_yellow(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[43m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_RED - ); - #endif - } - return stream; - } - - inline - std::ostream& on_blue(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[44m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_BLUE - ); - #endif - } - return stream; - } - - inline - std::ostream& on_magenta(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[45m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_BLUE | BACKGROUND_RED - ); - #endif - } - return stream; - } - - inline - std::ostream& on_cyan(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[46m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_BLUE - ); - #endif - } - return stream; - } - - inline - std::ostream& on_white(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[47m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED - ); - #endif - } - - return stream; - } - - - inline - std::ostream& on_bright_grey(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[100m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - 0 | BACKGROUND_INTENSITY // grey (black) - ); - #endif - } - return stream; - } - - inline - std::ostream& on_bright_red(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[101m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_RED | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& on_bright_green(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[102m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& on_bright_yellow(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[103m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& on_bright_blue(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[104m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_BLUE | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& on_bright_magenta(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[105m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& on_bright_cyan(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[106m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } - - inline - std::ostream& on_bright_white(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[107m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY - ); - #endif - } - - return stream; - } - - - - //! Since C++ hasn't a way to hide something in the header from - //! the outer access, I have to introduce this namespace which - //! is used for internal purpose and should't be access from - //! the user code. - namespace _internal - { - // An index to be used to access a private storage of I/O streams. See - // colorize / nocolorize I/O manipulators for details. Due to the fact - // that static variables ain't shared between translation units, inline - // function with local static variable is used to do the trick and share - // the variable value between translation units. - inline int colorize_index() - { - static int colorize_index = std::ios_base::xalloc(); - return colorize_index; - } - - //! Since C++ hasn't a true way to extract stream handler - //! from the a given `std::ostream` object, I have to write - //! this kind of hack. - inline - FILE* get_standard_stream(const std::ostream& stream) - { - if (&stream == &std::cout) - return stdout; - else if ((&stream == &std::cerr) || (&stream == &std::clog)) - return stderr; - - return nullptr; - } - - // Say whether a given stream should be colorized or not. It's always - // true for ATTY streams and may be true for streams marked with - // colorize flag. - inline - bool is_colorized(std::ostream& stream) - { - return is_atty(stream) || static_cast(stream.iword(colorize_index())); - } - - //! Test whether a given `std::ostream` object refers to - //! a terminal. - inline - bool is_atty(const std::ostream& stream) - { - FILE* std_stream = get_standard_stream(stream); - - // Unfortunately, fileno() ends with segmentation fault - // if invalid file descriptor is passed. So we need to - // handle this case gracefully and assume it's not a tty - // if standard stream is not detected, and 0 is returned. - if (!std_stream) - return false; - - #if defined(TERMCOLOR_TARGET_POSIX) - return ::isatty(fileno(std_stream)); - #elif defined(TERMCOLOR_TARGET_WINDOWS) - return ::_isatty(_fileno(std_stream)); - #else - return false; - #endif - } - - #if defined(TERMCOLOR_TARGET_WINDOWS) - //! Change Windows Terminal colors attribute. If some - //! parameter is `-1` then attribute won't changed. - inline void win_change_attributes(std::ostream& stream, int foreground, int background) - { - // yeah, i know.. it's ugly, it's windows. - static WORD defaultAttributes = 0; - - // Windows doesn't have ANSI escape sequences and so we use special - // API to change Terminal output color. That means we can't - // manipulate colors by means of "std::stringstream" and hence - // should do nothing in this case. - if (!_internal::is_atty(stream)) - return; - - // get terminal handle - HANDLE hTerminal = INVALID_HANDLE_VALUE; - if (&stream == &std::cout) - hTerminal = GetStdHandle(STD_OUTPUT_HANDLE); - else if (&stream == &std::cerr) - hTerminal = GetStdHandle(STD_ERROR_HANDLE); - - // save default terminal attributes if it unsaved - if (!defaultAttributes) - { - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(hTerminal, &info)) - return; - defaultAttributes = info.wAttributes; - } - - // restore all default settings - if (foreground == -1 && background == -1) - { - SetConsoleTextAttribute(hTerminal, defaultAttributes); - return; - } - - // get current settings - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(hTerminal, &info)) - return; - - if (foreground != -1) - { - info.wAttributes &= ~(info.wAttributes & 0x0F); - info.wAttributes |= static_cast(foreground); - } - - if (background != -1) - { - info.wAttributes &= ~(info.wAttributes & 0xF0); - info.wAttributes |= static_cast(background); - } - - SetConsoleTextAttribute(hTerminal, info.wAttributes); - } - #endif // TERMCOLOR_TARGET_WINDOWS - - } // namespace _internal +#include +#include +#endif -} // namespace termcolor +namespace termcolor { +// Forward declaration of the `_internal` namespace. +// All comments are below. +namespace _internal { +inline int colorize_index(); +inline FILE *get_standard_stream(const std::ostream &stream); +inline bool is_colorized(std::ostream &stream); +inline bool is_atty(const std::ostream &stream); + +#if defined(TERMCOLOR_TARGET_WINDOWS) +inline void win_change_attributes(std::ostream &stream, int foreground, int background = -1); +#endif +} // namespace _internal + +inline std::ostream &colorize(std::ostream &stream) { + stream.iword(_internal::colorize_index()) = 1L; + return stream; +} + +inline std::ostream &nocolorize(std::ostream &stream) { + stream.iword(_internal::colorize_index()) = 0L; + return stream; +} + +inline std::ostream &reset(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[00m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, -1); +#endif + } + return stream; +} + +inline std::ostream &bold(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[1m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +inline std::ostream &dark(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[2m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +inline std::ostream &italic(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[3m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +inline std::ostream &underline(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[4m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, COMMON_LVB_UNDERSCORE); +#endif + } + return stream; +} + +inline std::ostream &blink(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[5m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +inline std::ostream &reverse(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[7m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +inline std::ostream &concealed(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[8m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +inline std::ostream &crossed(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[9m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +template inline std::ostream &color(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + char command[12]; + std::snprintf(command, sizeof(command), "\033[38;5;%dm", code); + stream << command; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +template inline std::ostream &on_color(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + char command[12]; + std::snprintf(command, sizeof(command), "\033[48;5;%dm", code); + stream << command; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +template inline std::ostream &color(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + char command[20]; + std::snprintf(command, sizeof(command), "\033[38;2;%d;%d;%dm", r, g, b); + stream << command; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +template inline std::ostream &on_color(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + char command[20]; + std::snprintf(command, sizeof(command), "\033[48;2;%d;%d;%dm", r, g, b); + stream << command; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} + +inline std::ostream &grey(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[30m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + 0 // grey (black) + ); +#endif + } + return stream; +} + +inline std::ostream &red(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[31m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_RED); +#endif + } + return stream; +} + +inline std::ostream &green(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[32m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_GREEN); +#endif + } + return stream; +} + +inline std::ostream &yellow(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[33m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_GREEN | FOREGROUND_RED); +#endif + } + return stream; +} + +inline std::ostream &blue(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[34m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE); +#endif + } + return stream; +} + +inline std::ostream &magenta(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[35m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_RED); +#endif + } + return stream; +} + +inline std::ostream &cyan(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[36m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_GREEN); +#endif + } + return stream; +} + +inline std::ostream &white(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[37m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); +#endif + } + return stream; +} + +inline std::ostream &bright_grey(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[90m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + 0 | FOREGROUND_INTENSITY // grey (black) + ); +#endif + } + return stream; +} + +inline std::ostream &bright_red(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[91m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_RED | FOREGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &bright_green(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[92m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_GREEN | FOREGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &bright_yellow(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[93m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &bright_blue(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[94m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &bright_magenta(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[95m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &bright_cyan(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[96m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &bright_white(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[97m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &on_grey(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[40m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + 0 // grey (black) + ); +#endif + } + return stream; +} + +inline std::ostream &on_red(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[41m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_RED); +#endif + } + return stream; +} + +inline std::ostream &on_green(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[42m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_GREEN); +#endif + } + return stream; +} + +inline std::ostream &on_yellow(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[43m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_GREEN | BACKGROUND_RED); +#endif + } + return stream; +} + +inline std::ostream &on_blue(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[44m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_BLUE); +#endif + } + return stream; +} + +inline std::ostream &on_magenta(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[45m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_BLUE | BACKGROUND_RED); +#endif + } + return stream; +} + +inline std::ostream &on_cyan(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[46m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_GREEN | BACKGROUND_BLUE); +#endif + } + return stream; +} + +inline std::ostream &on_white(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[47m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED); +#endif + } + + return stream; +} + +inline std::ostream &on_bright_grey(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[100m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + 0 | BACKGROUND_INTENSITY // grey (black) + ); +#endif + } + return stream; +} + +inline std::ostream &on_bright_red(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[101m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_RED | BACKGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &on_bright_green(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[102m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_GREEN | BACKGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &on_bright_yellow(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[103m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &on_bright_blue(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[104m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_BLUE | BACKGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &on_bright_magenta(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[105m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &on_bright_cyan(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[106m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY); +#endif + } + return stream; +} + +inline std::ostream &on_bright_white(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[107m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes( + stream, -1, BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY); +#endif + } + + return stream; +} + +//! Since C++ hasn't a way to hide something in the header from +//! the outer access, I have to introduce this namespace which +//! is used for internal purpose and should't be access from +//! the user code. +namespace _internal { +// An index to be used to access a private storage of I/O streams. See +// colorize / nocolorize I/O manipulators for details. Due to the fact +// that static variables ain't shared between translation units, inline +// function with local static variable is used to do the trick and share +// the variable value between translation units. +inline int colorize_index() { + static int colorize_index = std::ios_base::xalloc(); + return colorize_index; +} + +//! Since C++ hasn't a true way to extract stream handler +//! from the a given `std::ostream` object, I have to write +//! this kind of hack. +inline FILE *get_standard_stream(const std::ostream &stream) { + if (&stream == &std::cout) + return stdout; + else if ((&stream == &std::cerr) || (&stream == &std::clog)) + return stderr; + + return nullptr; +} + +// Say whether a given stream should be colorized or not. It's always +// true for ATTY streams and may be true for streams marked with +// colorize flag. +inline bool is_colorized(std::ostream &stream) { + return is_atty(stream) || static_cast(stream.iword(colorize_index())); +} + +//! Test whether a given `std::ostream` object refers to +//! a terminal. +inline bool is_atty(const std::ostream &stream) { + FILE *std_stream = get_standard_stream(stream); + + // Unfortunately, fileno() ends with segmentation fault + // if invalid file descriptor is passed. So we need to + // handle this case gracefully and assume it's not a tty + // if standard stream is not detected, and 0 is returned. + if (!std_stream) + return false; +#if defined(TERMCOLOR_TARGET_POSIX) + return ::isatty(fileno(std_stream)); +#elif defined(TERMCOLOR_TARGET_WINDOWS) + return ::_isatty(_fileno(std_stream)); +#else + return false; +#endif +} + +#if defined(TERMCOLOR_TARGET_WINDOWS) +//! Change Windows Terminal colors attribute. If some +//! parameter is `-1` then attribute won't changed. +inline void win_change_attributes(std::ostream &stream, int foreground, int background) { + // yeah, i know.. it's ugly, it's windows. + static WORD defaultAttributes = 0; + + // Windows doesn't have ANSI escape sequences and so we use special + // API to change Terminal output color. That means we can't + // manipulate colors by means of "std::stringstream" and hence + // should do nothing in this case. + if (!_internal::is_atty(stream)) + return; + + // get terminal handle + HANDLE hTerminal = INVALID_HANDLE_VALUE; + if (&stream == &std::cout) + hTerminal = GetStdHandle(STD_OUTPUT_HANDLE); + else if (&stream == &std::cerr) + hTerminal = GetStdHandle(STD_ERROR_HANDLE); + + // save default terminal attributes if it unsaved + if (!defaultAttributes) { + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(hTerminal, &info)) + return; + defaultAttributes = info.wAttributes; + } + + // restore all default settings + if (foreground == -1 && background == -1) { + SetConsoleTextAttribute(hTerminal, defaultAttributes); + return; + } + + // get current settings + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(hTerminal, &info)) + return; + + if (foreground != -1) { + info.wAttributes &= ~(info.wAttributes & 0x0F); + info.wAttributes |= static_cast(foreground); + } + + if (background != -1) { + info.wAttributes &= ~(info.wAttributes & 0xF0); + info.wAttributes |= static_cast(background); + } + + SetConsoleTextAttribute(hTerminal, info.wAttributes); +} +#endif // TERMCOLOR_TARGET_WINDOWS + +} // namespace _internal + +} // namespace termcolor #undef TERMCOLOR_TARGET_POSIX #undef TERMCOLOR_TARGET_WINDOWS #if defined(TERMCOLOR_AUTODETECTED_IMPLEMENTATION) -# undef TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES -# undef TERMCOLOR_USE_WINDOWS_API +#undef TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES +#undef TERMCOLOR_USE_WINDOWS_API #endif #endif // TERMCOLOR_HPP_ diff --git a/include/indicators/terminal_size.hpp b/include/indicators/terminal_size.hpp index 0d03077..891e70f 100644 --- a/include/indicators/terminal_size.hpp +++ b/include/indicators/terminal_size.hpp @@ -3,7 +3,6 @@ #define INDICATORS_TERMINAL_SIZE #include - #if defined(_WIN32) #include diff --git a/samples/dynamic_postfix_text.cpp b/samples/dynamic_postfix_text.cpp index d0d460b..540ce14 100644 --- a/samples/dynamic_postfix_text.cpp +++ b/samples/dynamic_postfix_text.cpp @@ -1,46 +1,45 @@ -#include #include +#include #include using namespace indicators; int main() { - std::cout << "Terminal width: " << terminal_size().second << "\n"; - - // prepare progress bar - auto prepare_p = [](ProgressBar *p, const std::string &prefix){ - p->set_option(option::PrefixText{prefix}); - p->set_option(option::Start{""}); - p->set_option(option::Fill{""}); - p->set_option(option::Lead{""}); - p->set_option(option::Remainder{""}); - p->set_option(option::End{""}); - p->set_option(option::BarWidth{0}); - }; + std::cout << "Terminal width: " << terminal_size().second << "\n"; - ProgressBar p1, p2; + // prepare progress bar + auto prepare_p = [](ProgressBar *p, const std::string &prefix) { + p->set_option(option::PrefixText{prefix}); + p->set_option(option::Start{""}); + p->set_option(option::Fill{""}); + p->set_option(option::Lead{""}); + p->set_option(option::Remainder{""}); + p->set_option(option::End{""}); + p->set_option(option::BarWidth{0}); + }; - prepare_p(&p1, "Progress #1"); - prepare_p(&p2, "Progress #2"); + ProgressBar p1, p2; - MultiProgress mp(p1, p2); + prepare_p(&p1, "Progress #1"); + prepare_p(&p2, "Progress #2"); - std::string some_text[] = {"foo", "bar", "independence", "beta", "alfa"}; - std::string dynamic_text; + MultiProgress mp(p1, p2); - // first pb with static postfix text - p1.set_option(option::PostfixText{"Static text"}); + std::string some_text[] = {"foo", "bar", "independence", "beta", "alfa"}; + std::string dynamic_text; - // second pb with dynamic postfix text - for (auto &t: some_text) { - dynamic_text += t + " "; - p2.set_option(option::PostfixText{dynamic_text}); - mp.set_progress<0>(size_t(0)); - std::this_thread::sleep_for(std::chrono::seconds(1)); - } + // first pb with static postfix text + p1.set_option(option::PostfixText{"Static text"}); - // update postfix to little text for pb #2 - p2.set_option(option::PostfixText{"abcd"}); + // second pb with dynamic postfix text + for (auto &t : some_text) { + dynamic_text += t + " "; + p2.set_option(option::PostfixText{dynamic_text}); mp.set_progress<0>(size_t(0)); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + // update postfix to little text for pb #2 + p2.set_option(option::PostfixText{"abcd"}); + mp.set_progress<0>(size_t(0)); } diff --git a/samples/dynamic_progress.cpp b/samples/dynamic_progress.cpp index c69d814..e247d3c 100644 --- a/samples/dynamic_progress.cpp +++ b/samples/dynamic_progress.cpp @@ -4,53 +4,59 @@ using namespace indicators; int main() { - auto bar1 = std::make_unique(option::BarWidth{50}, - option::ForegroundColor{Color::red}, - option::ShowElapsedTime{true}, - option::ShowRemainingTime{true}, - option::PrefixText{"5c90d4a2d1a8: Downloading "}, - indicators::option::FontStyles{ - std::vector{indicators::FontStyle::bold}}); - - auto bar2 = std::make_unique(option::BarWidth{50}, - option::ForegroundColor{Color::yellow}, - option::ShowElapsedTime{true}, - option::ShowRemainingTime{true}, - option::PrefixText{"22337bfd13a9: Downloading "}, - indicators::option::FontStyles{ - std::vector{indicators::FontStyle::bold}}); - - auto bar3 = std::make_unique(option::BarWidth{50}, - option::ForegroundColor{Color::green}, - option::ShowElapsedTime{true}, - option::ShowRemainingTime{true}, - option::PrefixText{"10f26c680a34: Downloading "}, - indicators::option::FontStyles{ - std::vector{indicators::FontStyle::bold}}); - - auto bar4 = std::make_unique(option::BarWidth{50}, - option::ForegroundColor{Color::white}, - option::ShowElapsedTime{true}, - option::ShowRemainingTime{true}, - option::PrefixText{"6364e0d7a283: Downloading "}, - indicators::option::FontStyles{ - std::vector{indicators::FontStyle::bold}}); - - auto bar5 = std::make_unique(option::BarWidth{50}, - option::ForegroundColor{Color::blue}, - option::ShowElapsedTime{true}, - option::ShowRemainingTime{true}, - option::PrefixText{"ff1356ba118b: Downloading "}, - indicators::option::FontStyles{ - std::vector{indicators::FontStyle::bold}}); - - auto bar6 = std::make_unique(option::BarWidth{50}, - option::ForegroundColor{Color::cyan}, - option::ShowElapsedTime{true}, - option::ShowRemainingTime{true}, - option::PrefixText{"5a17453338b4: Downloading "}, - indicators::option::FontStyles{ - std::vector{indicators::FontStyle::bold}}); + auto bar1 = std::make_unique( + option::BarWidth{50}, // + option::ForegroundColor{Color::red}, // + option::ShowElapsedTime{true}, // + option::ShowRemainingTime{true}, // + option::PrefixText{"5c90d4a2d1a8: Downloading "}, // + indicators::option::FontStyles{ + std::vector{indicators::FontStyle::bold}}); + + auto bar2 = std::make_unique( + option::BarWidth{50}, // + option::ForegroundColor{Color::yellow}, // + option::ShowElapsedTime{true}, // + option::ShowRemainingTime{true}, // + option::PrefixText{"22337bfd13a9: Downloading "}, // + indicators::option::FontStyles{ + std::vector{indicators::FontStyle::bold}}); + + auto bar3 = std::make_unique( + option::BarWidth{50}, // + option::ForegroundColor{Color::green}, // + option::ShowElapsedTime{true}, // + option::ShowRemainingTime{true}, // + option::PrefixText{"10f26c680a34: Downloading "}, // + indicators::option::FontStyles{ + std::vector{indicators::FontStyle::bold}}); + + auto bar4 = std::make_unique( + option::BarWidth{50}, // + option::ForegroundColor{Color::white}, // + option::ShowElapsedTime{true}, // + option::ShowRemainingTime{true}, // + option::PrefixText{"6364e0d7a283: Downloading "}, // + indicators::option::FontStyles{ + std::vector{indicators::FontStyle::bold}}); + + auto bar5 = std::make_unique( + option::BarWidth{50}, // + option::ForegroundColor{Color::blue}, // + option::ShowElapsedTime{true}, // + option::ShowRemainingTime{true}, // + option::PrefixText{"ff1356ba118b: Downloading "}, // + indicators::option::FontStyles{ + std::vector{indicators::FontStyle::bold}}); + + auto bar6 = std::make_unique( + option::BarWidth{50}, // + option::ForegroundColor{Color::cyan}, // + option::ShowElapsedTime{true}, // + option::ShowRemainingTime{true}, // + option::PrefixText{"5a17453338b4: Downloading "}, // + indicators::option::FontStyles{ + std::vector{indicators::FontStyle::bold}}); std::cout << termcolor::bold << termcolor::white << "Pulling image foo:bar/baz\n"; diff --git a/single_include/indicators/indicators.hpp b/single_include/indicators/indicators.hpp index 3832d66..f6dd56b 100644 --- a/single_include/indicators/indicators.hpp +++ b/single_include/indicators/indicators.hpp @@ -44,906 +44,699 @@ enum class ProgressType { incremental, decremental }; #ifndef TERMCOLOR_HPP_ #define TERMCOLOR_HPP_ -#include -#include #include +#include +#include // Detect target's platform and set some macros in order to wrap platform // specific code this library depends on. #if defined(_WIN32) || defined(_WIN64) -# define TERMCOLOR_TARGET_WINDOWS +#define TERMCOLOR_TARGET_WINDOWS #elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) -# define TERMCOLOR_TARGET_POSIX +#define TERMCOLOR_TARGET_POSIX #endif // If implementation has not been explicitly set, try to choose one based on // target platform. -#if !defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) && !defined(TERMCOLOR_USE_WINDOWS_API) && !defined(TERMCOLOR_USE_NOOP) -# if defined(TERMCOLOR_TARGET_POSIX) -# define TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES -# define TERMCOLOR_AUTODETECTED_IMPLEMENTATION -# elif defined(TERMCOLOR_TARGET_WINDOWS) -# define TERMCOLOR_USE_WINDOWS_API -# define TERMCOLOR_AUTODETECTED_IMPLEMENTATION -# endif +#if !defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) && !defined(TERMCOLOR_USE_WINDOWS_API) && \ + !defined(TERMCOLOR_USE_NOOP) +#if defined(TERMCOLOR_TARGET_POSIX) +#define TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES +#define TERMCOLOR_AUTODETECTED_IMPLEMENTATION +#elif defined(TERMCOLOR_TARGET_WINDOWS) +#define TERMCOLOR_USE_WINDOWS_API +#define TERMCOLOR_AUTODETECTED_IMPLEMENTATION +#endif #endif // These headers provide isatty()/fileno() functions, which are used for // testing whether a standard stream refers to the terminal. #if defined(TERMCOLOR_TARGET_POSIX) -# include +#include #elif defined(TERMCOLOR_TARGET_WINDOWS) #if defined(_MSC_VER) #if !defined(NOMINMAX) #define NOMINMAX #endif #endif -# include -# include +#include +#include #endif +namespace termcolor { +// Forward declaration of the `_internal` namespace. +// All comments are below. +namespace _internal { +inline int colorize_index(); +inline FILE *get_standard_stream(const std::ostream &stream); +inline bool is_colorized(std::ostream &stream); +inline bool is_atty(const std::ostream &stream); + +#if defined(TERMCOLOR_TARGET_WINDOWS) +inline void win_change_attributes(std::ostream &stream, int foreground, int background = -1); +#endif +} // namespace _internal -namespace termcolor -{ - // Forward declaration of the `_internal` namespace. - // All comments are below. - namespace _internal - { - inline int colorize_index(); - inline FILE* get_standard_stream(const std::ostream& stream); - inline bool is_colorized(std::ostream& stream); - inline bool is_atty(const std::ostream& stream); - - #if defined(TERMCOLOR_TARGET_WINDOWS) - inline void win_change_attributes(std::ostream& stream, int foreground, int background=-1); - #endif - } +inline std::ostream &colorize(std::ostream &stream) { + stream.iword(_internal::colorize_index()) = 1L; + return stream; +} - inline - std::ostream& colorize(std::ostream& stream) - { - stream.iword(_internal::colorize_index()) = 1L; - return stream; - } +inline std::ostream &nocolorize(std::ostream &stream) { + stream.iword(_internal::colorize_index()) = 0L; + return stream; +} - inline - std::ostream& nocolorize(std::ostream& stream) - { - stream.iword(_internal::colorize_index()) = 0L; - return stream; - } +inline std::ostream &reset(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[00m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, -1); +#endif + } + return stream; +} - inline - std::ostream& reset(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[00m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, -1); - #endif - } - return stream; - } +inline std::ostream &bold(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[1m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - inline - std::ostream& bold(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[1m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +inline std::ostream &dark(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[2m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - inline - std::ostream& dark(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[2m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +inline std::ostream &italic(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[3m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - inline - std::ostream& italic(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[3m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +inline std::ostream &underline(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[4m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, COMMON_LVB_UNDERSCORE); +#endif + } + return stream; +} - inline - std::ostream& underline(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[4m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, COMMON_LVB_UNDERSCORE); - #endif - } - return stream; - } +inline std::ostream &blink(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[5m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - inline - std::ostream& blink(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[5m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +inline std::ostream &reverse(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[7m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - inline - std::ostream& reverse(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[7m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +inline std::ostream &concealed(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[8m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - inline - std::ostream& concealed(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[8m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +inline std::ostream &crossed(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[9m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - inline - std::ostream& crossed(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[9m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +template inline std::ostream &color(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + char command[12]; + std::snprintf(command, sizeof(command), "\033[38;5;%dm", code); + stream << command; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - template inline - std::ostream& color(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - char command[12]; - std::snprintf(command, sizeof(command), "\033[38;5;%dm", code); - stream << command; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +template inline std::ostream &on_color(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + char command[12]; + std::snprintf(command, sizeof(command), "\033[48;5;%dm", code); + stream << command; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - template inline - std::ostream& on_color(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - char command[12]; - std::snprintf(command, sizeof(command), "\033[48;5;%dm", code); - stream << command; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +template inline std::ostream &color(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + char command[20]; + std::snprintf(command, sizeof(command), "\033[38;2;%d;%d;%dm", r, g, b); + stream << command; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - template inline - std::ostream& color(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - char command[20]; - std::snprintf(command, sizeof(command), "\033[38;2;%d;%d;%dm", r, g, b); - stream << command; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +template inline std::ostream &on_color(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + char command[20]; + std::snprintf(command, sizeof(command), "\033[48;2;%d;%d;%dm", r, g, b); + stream << command; +#elif defined(TERMCOLOR_USE_WINDOWS_API) +#endif + } + return stream; +} - template inline - std::ostream& on_color(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - char command[20]; - std::snprintf(command, sizeof(command), "\033[48;2;%d;%d;%dm", r, g, b); - stream << command; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - #endif - } - return stream; - } +inline std::ostream &grey(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[30m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + 0 // grey (black) + ); +#endif + } + return stream; +} - inline - std::ostream& grey(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[30m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - 0 // grey (black) - ); - #endif - } - return stream; - } +inline std::ostream &red(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[31m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_RED); +#endif + } + return stream; +} - inline - std::ostream& red(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[31m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_RED - ); - #endif - } - return stream; - } +inline std::ostream &green(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[32m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_GREEN); +#endif + } + return stream; +} - inline - std::ostream& green(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[32m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_GREEN - ); - #endif - } - return stream; - } +inline std::ostream &yellow(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[33m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_GREEN | FOREGROUND_RED); +#endif + } + return stream; +} - inline - std::ostream& yellow(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[33m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_GREEN | FOREGROUND_RED - ); - #endif - } - return stream; - } +inline std::ostream &blue(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[34m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE); +#endif + } + return stream; +} - inline - std::ostream& blue(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[34m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE - ); - #endif - } - return stream; - } +inline std::ostream &magenta(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[35m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_RED); +#endif + } + return stream; +} - inline - std::ostream& magenta(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[35m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_RED - ); - #endif - } - return stream; - } +inline std::ostream &cyan(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[36m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_GREEN); +#endif + } + return stream; +} - inline - std::ostream& cyan(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[36m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_GREEN - ); - #endif - } - return stream; - } +inline std::ostream &white(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[37m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); +#endif + } + return stream; +} - inline - std::ostream& white(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[37m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED - ); - #endif - } - return stream; - } +inline std::ostream &bright_grey(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[90m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + 0 | FOREGROUND_INTENSITY // grey (black) + ); +#endif + } + return stream; +} +inline std::ostream &bright_red(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[91m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_RED | FOREGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& bright_grey(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[90m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - 0 | FOREGROUND_INTENSITY // grey (black) - ); - #endif - } - return stream; - } +inline std::ostream &bright_green(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[92m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_GREEN | FOREGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& bright_red(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[91m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_RED | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } +inline std::ostream &bright_yellow(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[93m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& bright_green(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[92m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_GREEN | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } +inline std::ostream &bright_blue(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[94m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& bright_yellow(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[93m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } +inline std::ostream &bright_magenta(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[95m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& bright_blue(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[94m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } +inline std::ostream &bright_cyan(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[96m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& bright_magenta(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[95m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } +inline std::ostream &bright_white(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[97m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& bright_cyan(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[96m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } +inline std::ostream &on_grey(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[40m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + 0 // grey (black) + ); +#endif + } + return stream; +} - inline - std::ostream& bright_white(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[97m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, - FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY - ); - #endif - } - return stream; - } +inline std::ostream &on_red(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[41m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_RED); +#endif + } + return stream; +} +inline std::ostream &on_green(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[42m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_GREEN); +#endif + } + return stream; +} - inline - std::ostream& on_grey(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[40m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - 0 // grey (black) - ); - #endif - } - return stream; - } +inline std::ostream &on_yellow(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[43m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_GREEN | BACKGROUND_RED); +#endif + } + return stream; +} - inline - std::ostream& on_red(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[41m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_RED - ); - #endif - } - return stream; - } +inline std::ostream &on_blue(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[44m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_BLUE); +#endif + } + return stream; +} - inline - std::ostream& on_green(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[42m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN - ); - #endif - } - return stream; - } +inline std::ostream &on_magenta(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[45m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_BLUE | BACKGROUND_RED); +#endif + } + return stream; +} - inline - std::ostream& on_yellow(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[43m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_RED - ); - #endif - } - return stream; - } +inline std::ostream &on_cyan(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[46m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_GREEN | BACKGROUND_BLUE); +#endif + } + return stream; +} - inline - std::ostream& on_blue(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[44m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_BLUE - ); - #endif - } - return stream; - } +inline std::ostream &on_white(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[47m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED); +#endif + } - inline - std::ostream& on_magenta(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[45m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_BLUE | BACKGROUND_RED - ); - #endif - } - return stream; - } + return stream; +} - inline - std::ostream& on_cyan(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[46m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_BLUE - ); - #endif - } - return stream; - } +inline std::ostream &on_bright_grey(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[100m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + 0 | BACKGROUND_INTENSITY // grey (black) + ); +#endif + } + return stream; +} - inline - std::ostream& on_white(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[47m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED - ); - #endif - } +inline std::ostream &on_bright_red(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[101m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_RED | BACKGROUND_INTENSITY); +#endif + } + return stream; +} - return stream; - } +inline std::ostream &on_bright_green(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[102m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_GREEN | BACKGROUND_INTENSITY); +#endif + } + return stream; +} +inline std::ostream &on_bright_yellow(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[103m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& on_bright_grey(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[100m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - 0 | BACKGROUND_INTENSITY // grey (black) - ); - #endif - } - return stream; - } +inline std::ostream &on_bright_blue(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[104m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, BACKGROUND_BLUE | BACKGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& on_bright_red(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[101m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_RED | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } +inline std::ostream &on_bright_magenta(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[105m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& on_bright_green(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[102m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } +inline std::ostream &on_bright_cyan(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[106m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY); +#endif + } + return stream; +} - inline - std::ostream& on_bright_yellow(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[103m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } +inline std::ostream &on_bright_white(std::ostream &stream) { + if (_internal::is_colorized(stream)) { +#if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[107m"; +#elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes( + stream, -1, BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY); +#endif + } - inline - std::ostream& on_bright_blue(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[104m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_BLUE | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } + return stream; +} - inline - std::ostream& on_bright_magenta(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[105m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } +//! Since C++ hasn't a way to hide something in the header from +//! the outer access, I have to introduce this namespace which +//! is used for internal purpose and should't be access from +//! the user code. +namespace _internal { +// An index to be used to access a private storage of I/O streams. See +// colorize / nocolorize I/O manipulators for details. Due to the fact +// that static variables ain't shared between translation units, inline +// function with local static variable is used to do the trick and share +// the variable value between translation units. +inline int colorize_index() { + static int colorize_index = std::ios_base::xalloc(); + return colorize_index; +} - inline - std::ostream& on_bright_cyan(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[106m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY - ); - #endif - } - return stream; - } +//! Since C++ hasn't a true way to extract stream handler +//! from the a given `std::ostream` object, I have to write +//! this kind of hack. +inline FILE *get_standard_stream(const std::ostream &stream) { + if (&stream == &std::cout) + return stdout; + else if ((&stream == &std::cerr) || (&stream == &std::clog)) + return stderr; - inline - std::ostream& on_bright_white(std::ostream& stream) - { - if (_internal::is_colorized(stream)) - { - #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) - stream << "\033[107m"; - #elif defined(TERMCOLOR_USE_WINDOWS_API) - _internal::win_change_attributes(stream, -1, - BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY - ); - #endif - } + return nullptr; +} - return stream; - } +// Say whether a given stream should be colorized or not. It's always +// true for ATTY streams and may be true for streams marked with +// colorize flag. +inline bool is_colorized(std::ostream &stream) { + return is_atty(stream) || static_cast(stream.iword(colorize_index())); +} +//! Test whether a given `std::ostream` object refers to +//! a terminal. +inline bool is_atty(const std::ostream &stream) { + FILE *std_stream = get_standard_stream(stream); + // Unfortunately, fileno() ends with segmentation fault + // if invalid file descriptor is passed. So we need to + // handle this case gracefully and assume it's not a tty + // if standard stream is not detected, and 0 is returned. + if (!std_stream) + return false; - //! Since C++ hasn't a way to hide something in the header from - //! the outer access, I have to introduce this namespace which - //! is used for internal purpose and should't be access from - //! the user code. - namespace _internal - { - // An index to be used to access a private storage of I/O streams. See - // colorize / nocolorize I/O manipulators for details. Due to the fact - // that static variables ain't shared between translation units, inline - // function with local static variable is used to do the trick and share - // the variable value between translation units. - inline int colorize_index() - { - static int colorize_index = std::ios_base::xalloc(); - return colorize_index; - } +#if defined(TERMCOLOR_TARGET_POSIX) + return ::isatty(fileno(std_stream)); +#elif defined(TERMCOLOR_TARGET_WINDOWS) + return ::_isatty(_fileno(std_stream)); +#else + return false; +#endif +} - //! Since C++ hasn't a true way to extract stream handler - //! from the a given `std::ostream` object, I have to write - //! this kind of hack. - inline - FILE* get_standard_stream(const std::ostream& stream) - { - if (&stream == &std::cout) - return stdout; - else if ((&stream == &std::cerr) || (&stream == &std::clog)) - return stderr; - - return nullptr; - } +#if defined(TERMCOLOR_TARGET_WINDOWS) +//! Change Windows Terminal colors attribute. If some +//! parameter is `-1` then attribute won't changed. +inline void win_change_attributes(std::ostream &stream, int foreground, int background) { + // yeah, i know.. it's ugly, it's windows. + static WORD defaultAttributes = 0; + + // Windows doesn't have ANSI escape sequences and so we use special + // API to change Terminal output color. That means we can't + // manipulate colors by means of "std::stringstream" and hence + // should do nothing in this case. + if (!_internal::is_atty(stream)) + return; - // Say whether a given stream should be colorized or not. It's always - // true for ATTY streams and may be true for streams marked with - // colorize flag. - inline - bool is_colorized(std::ostream& stream) - { - return is_atty(stream) || static_cast(stream.iword(colorize_index())); - } + // get terminal handle + HANDLE hTerminal = INVALID_HANDLE_VALUE; + if (&stream == &std::cout) + hTerminal = GetStdHandle(STD_OUTPUT_HANDLE); + else if (&stream == &std::cerr) + hTerminal = GetStdHandle(STD_ERROR_HANDLE); + + // save default terminal attributes if it unsaved + if (!defaultAttributes) { + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(hTerminal, &info)) + return; + defaultAttributes = info.wAttributes; + } - //! Test whether a given `std::ostream` object refers to - //! a terminal. - inline - bool is_atty(const std::ostream& stream) - { - FILE* std_stream = get_standard_stream(stream); - - // Unfortunately, fileno() ends with segmentation fault - // if invalid file descriptor is passed. So we need to - // handle this case gracefully and assume it's not a tty - // if standard stream is not detected, and 0 is returned. - if (!std_stream) - return false; - - #if defined(TERMCOLOR_TARGET_POSIX) - return ::isatty(fileno(std_stream)); - #elif defined(TERMCOLOR_TARGET_WINDOWS) - return ::_isatty(_fileno(std_stream)); - #else - return false; - #endif - } + // restore all default settings + if (foreground == -1 && background == -1) { + SetConsoleTextAttribute(hTerminal, defaultAttributes); + return; + } - #if defined(TERMCOLOR_TARGET_WINDOWS) - //! Change Windows Terminal colors attribute. If some - //! parameter is `-1` then attribute won't changed. - inline void win_change_attributes(std::ostream& stream, int foreground, int background) - { - // yeah, i know.. it's ugly, it's windows. - static WORD defaultAttributes = 0; - - // Windows doesn't have ANSI escape sequences and so we use special - // API to change Terminal output color. That means we can't - // manipulate colors by means of "std::stringstream" and hence - // should do nothing in this case. - if (!_internal::is_atty(stream)) - return; - - // get terminal handle - HANDLE hTerminal = INVALID_HANDLE_VALUE; - if (&stream == &std::cout) - hTerminal = GetStdHandle(STD_OUTPUT_HANDLE); - else if (&stream == &std::cerr) - hTerminal = GetStdHandle(STD_ERROR_HANDLE); - - // save default terminal attributes if it unsaved - if (!defaultAttributes) - { - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(hTerminal, &info)) - return; - defaultAttributes = info.wAttributes; - } - - // restore all default settings - if (foreground == -1 && background == -1) - { - SetConsoleTextAttribute(hTerminal, defaultAttributes); - return; - } - - // get current settings - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(hTerminal, &info)) - return; - - if (foreground != -1) - { - info.wAttributes &= ~(info.wAttributes & 0x0F); - info.wAttributes |= static_cast(foreground); - } - - if (background != -1) - { - info.wAttributes &= ~(info.wAttributes & 0xF0); - info.wAttributes |= static_cast(background); - } - - SetConsoleTextAttribute(hTerminal, info.wAttributes); - } - #endif // TERMCOLOR_TARGET_WINDOWS + // get current settings + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(hTerminal, &info)) + return; - } // namespace _internal + if (foreground != -1) { + info.wAttributes &= ~(info.wAttributes & 0x0F); + info.wAttributes |= static_cast(foreground); + } -} // namespace termcolor + if (background != -1) { + info.wAttributes &= ~(info.wAttributes & 0xF0); + info.wAttributes |= static_cast(background); + } + + SetConsoleTextAttribute(hTerminal, info.wAttributes); +} +#endif // TERMCOLOR_TARGET_WINDOWS + +} // namespace _internal +} // namespace termcolor #undef TERMCOLOR_TARGET_POSIX #undef TERMCOLOR_TARGET_WINDOWS #if defined(TERMCOLOR_AUTODETECTED_IMPLEMENTATION) -# undef TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES -# undef TERMCOLOR_USE_WINDOWS_API +#undef TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES +#undef TERMCOLOR_USE_WINDOWS_API #endif #endif // TERMCOLOR_HPP_ @@ -954,7 +747,6 @@ namespace termcolor #define INDICATORS_TERMINAL_SIZE #include - #if defined(_WIN32) #include @@ -1040,9 +832,13 @@ namespace details { template struct if_else; -template <> struct if_else { using type = std::true_type; }; +template <> struct if_else { + using type = std::true_type; +}; -template <> struct if_else { using type = std::false_type; }; +template <> struct if_else { + using type = std::false_type; +}; template struct if_else_type; @@ -1099,7 +895,7 @@ enum class ProgressBarOption { template struct Setting { template ::value>::type> - explicit Setting(Args &&... args) : value(std::forward(args)...) {} + explicit Setting(Args &&...args) : value(std::forward(args)...) {} Setting(const Setting &) = default; Setting(Setting &&) = default; @@ -1130,21 +926,23 @@ template struct are_settings_from_tuple : if_else...>::value>::type {}; -template struct always_true { static constexpr auto value = true; }; +template struct always_true { + static constexpr auto value = true; +}; template Default &&get_impl(Default &&def) { return std::forward(def); } template -auto get_impl(Default && /*def*/, T &&first, Args &&... /*tail*/) -> +auto get_impl(Default && /*def*/, T &&first, Args &&.../*tail*/) -> typename std::enable_if<(std::decay::type::id == Id), decltype(std::forward(first))>::type { return std::forward(first); } template -auto get_impl(Default &&def, T && /*first*/, Args &&... tail) -> +auto get_impl(Default &&def, T && /*first*/, Args &&...tail) -> typename std::enable_if<(std::decay::type::id != Id), decltype(get_impl(std::forward(def), std::forward(tail)...))>::type { @@ -1153,7 +951,7 @@ auto get_impl(Default &&def, T && /*first*/, Args &&... tail) -> template ::value, void>::type> -auto get(Default &&def, Args &&... args) +auto get(Default &&def, Args &&...args) -> decltype(details::get_impl(std::forward(def), std::forward(args)...)) { return details::get_impl(std::forward(def), std::forward(args)...); } @@ -1262,8 +1060,7 @@ static inline void erase_line() { FillConsoleOutputCharacterA(hStdout, ' ', csbiInfo.dwSize.X, cursor, &count); - FillConsoleOutputAttribute(hStdout, csbiInfo.wAttributes, csbiInfo.dwSize.X, - cursor, &count); + FillConsoleOutputAttribute(hStdout, csbiInfo.wAttributes, csbiInfo.dwSize.X, cursor, &count); SetConsoleCursorPosition(hStdout, cursor); } @@ -1274,9 +1071,7 @@ static inline void show_console_cursor(bool const show) { std::fputs(show ? "\033[?25h" : "\033[?25l", stdout); } -static inline void erase_line() { - std::fputs("\r\033[K", stdout); -} +static inline void erase_line() { std::fputs("\r\033[K", stdout); } #endif @@ -1475,54 +1270,42 @@ static inline int mk_wcwidth(wchar_t ucs) { /* sorted list of non-overlapping intervals of non-spacing characters */ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ static const struct interval combining[] = { - {0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489}, - {0x0591, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, - {0x05C4, 0x05C5}, {0x05C7, 0x05C7}, {0x0600, 0x0603}, - {0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670}, - {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, - {0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A}, - {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, {0x0901, 0x0902}, - {0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D}, - {0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981}, - {0x09BC, 0x09BC}, {0x09C1, 0x09C4}, {0x09CD, 0x09CD}, - {0x09E2, 0x09E3}, {0x0A01, 0x0A02}, {0x0A3C, 0x0A3C}, - {0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, - {0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC}, - {0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD}, - {0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, {0x0B3C, 0x0B3C}, - {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D}, - {0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0}, - {0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48}, - {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0CBC, 0x0CBC}, - {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD}, - {0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D}, - {0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, - {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, - {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, - {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, - {0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F71, 0x0F7E}, - {0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F90, 0x0F97}, - {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030}, - {0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039}, - {0x1058, 0x1059}, {0x1160, 0x11FF}, {0x135F, 0x135F}, - {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753}, - {0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD}, - {0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD}, - {0x180B, 0x180D}, {0x18A9, 0x18A9}, {0x1920, 0x1922}, - {0x1927, 0x1928}, {0x1932, 0x1932}, {0x1939, 0x193B}, - {0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34}, - {0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42}, - {0x1B6B, 0x1B73}, {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF}, - {0x200B, 0x200F}, {0x202A, 0x202E}, {0x2060, 0x2063}, - {0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F}, - {0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B}, - {0xA825, 0xA826}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F}, - {0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, - {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, - {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169}, - {0x1D173, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, - {0x1D242, 0x1D244}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F}, - {0xE0100, 0xE01EF}}; + {0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489}, {0x0591, 0x05BD}, + {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C5}, {0x05C7, 0x05C7}, + {0x0600, 0x0603}, {0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670}, + {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, {0x070F, 0x070F}, + {0x0711, 0x0711}, {0x0730, 0x074A}, {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, + {0x0901, 0x0902}, {0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D}, + {0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981}, {0x09BC, 0x09BC}, + {0x09C1, 0x09C4}, {0x09CD, 0x09CD}, {0x09E2, 0x09E3}, {0x0A01, 0x0A02}, + {0x0A3C, 0x0A3C}, {0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, + {0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC}, {0x0AC1, 0x0AC5}, + {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD}, {0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, + {0x0B3C, 0x0B3C}, {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D}, + {0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0}, {0x0BCD, 0x0BCD}, + {0x0C3E, 0x0C40}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, + {0x0CBC, 0x0CBC}, {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD}, + {0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D}, {0x0DCA, 0x0DCA}, + {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, + {0x0E47, 0x0E4E}, {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, + {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, {0x0F37, 0x0F37}, + {0x0F39, 0x0F39}, {0x0F71, 0x0F7E}, {0x0F80, 0x0F84}, {0x0F86, 0x0F87}, + {0x0F90, 0x0F97}, {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030}, + {0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039}, {0x1058, 0x1059}, + {0x1160, 0x11FF}, {0x135F, 0x135F}, {0x1712, 0x1714}, {0x1732, 0x1734}, + {0x1752, 0x1753}, {0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD}, + {0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD}, {0x180B, 0x180D}, + {0x18A9, 0x18A9}, {0x1920, 0x1922}, {0x1927, 0x1928}, {0x1932, 0x1932}, + {0x1939, 0x193B}, {0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34}, + {0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42}, {0x1B6B, 0x1B73}, + {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF}, {0x200B, 0x200F}, {0x202A, 0x202E}, + {0x2060, 0x2063}, {0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F}, + {0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B}, {0xA825, 0xA826}, + {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F}, {0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, + {0xFFF9, 0xFFFB}, {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, + {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169}, {0x1D173, 0x1D182}, + {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0xE0001, 0xE0001}, + {0xE0020, 0xE007F}, {0xE0100, 0xE01EF}}; /* test for 8-bit control characters */ if (ucs == 0) @@ -1536,20 +1319,17 @@ static inline int mk_wcwidth(wchar_t ucs) { /* if we arrive here, ucs is not a combining or C0/C1 control character */ - return 1 + - (ucs >= 0x1100 && - (ucs <= 0x115f || /* Hangul Jamo init. consonants */ - ucs == 0x2329 || ucs == 0x232a || - (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) || /* CJK ... Yi */ - (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ - (ucs >= 0xf900 && - ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ - (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ - (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ - (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ - (ucs >= 0xffe0 && ucs <= 0xffe6) || - (ucs >= 0x20000 && ucs <= 0x2fffd) || - (ucs >= 0x30000 && ucs <= 0x3fffd))); + return 1 + (ucs >= 0x1100 && + (ucs <= 0x115f || /* Hangul Jamo init. consonants */ + ucs == 0x2329 || ucs == 0x232a || + (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) || /* CJK ... Yi */ + (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ + (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ + (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ + (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ + (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ + (ucs >= 0xffe0 && ucs <= 0xffe6) || (ucs >= 0x20000 && ucs <= 0x2fffd) || + (ucs >= 0x30000 && ucs <= 0x3fffd))); } static inline int mk_wcswidth(const wchar_t *pwcs, size_t n) { @@ -1577,58 +1357,38 @@ static inline int mk_wcwidth_cjk(wchar_t ucs) { /* sorted list of non-overlapping intervals of East Asian Ambiguous * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */ static const struct interval ambiguous[] = { - {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, - {0x00AA, 0x00AA}, {0x00AE, 0x00AE}, {0x00B0, 0x00B4}, - {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6}, - {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1}, - {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, - {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, - {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101}, - {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B}, - {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133}, - {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144}, - {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153}, - {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE}, - {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, - {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, - {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261}, - {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB}, - {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB}, - {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0391, 0x03A1}, - {0x03A3, 0x03A9}, {0x03B1, 0x03C1}, {0x03C3, 0x03C9}, - {0x0401, 0x0401}, {0x0410, 0x044F}, {0x0451, 0x0451}, - {0x2010, 0x2010}, {0x2013, 0x2016}, {0x2018, 0x2019}, - {0x201C, 0x201D}, {0x2020, 0x2022}, {0x2024, 0x2027}, - {0x2030, 0x2030}, {0x2032, 0x2033}, {0x2035, 0x2035}, - {0x203B, 0x203B}, {0x203E, 0x203E}, {0x2074, 0x2074}, - {0x207F, 0x207F}, {0x2081, 0x2084}, {0x20AC, 0x20AC}, - {0x2103, 0x2103}, {0x2105, 0x2105}, {0x2109, 0x2109}, - {0x2113, 0x2113}, {0x2116, 0x2116}, {0x2121, 0x2122}, - {0x2126, 0x2126}, {0x212B, 0x212B}, {0x2153, 0x2154}, - {0x215B, 0x215E}, {0x2160, 0x216B}, {0x2170, 0x2179}, - {0x2190, 0x2199}, {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, - {0x21D4, 0x21D4}, {0x21E7, 0x21E7}, {0x2200, 0x2200}, - {0x2202, 0x2203}, {0x2207, 0x2208}, {0x220B, 0x220B}, - {0x220F, 0x220F}, {0x2211, 0x2211}, {0x2215, 0x2215}, - {0x221A, 0x221A}, {0x221D, 0x2220}, {0x2223, 0x2223}, - {0x2225, 0x2225}, {0x2227, 0x222C}, {0x222E, 0x222E}, - {0x2234, 0x2237}, {0x223C, 0x223D}, {0x2248, 0x2248}, - {0x224C, 0x224C}, {0x2252, 0x2252}, {0x2260, 0x2261}, - {0x2264, 0x2267}, {0x226A, 0x226B}, {0x226E, 0x226F}, - {0x2282, 0x2283}, {0x2286, 0x2287}, {0x2295, 0x2295}, - {0x2299, 0x2299}, {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, - {0x2312, 0x2312}, {0x2460, 0x24E9}, {0x24EB, 0x254B}, - {0x2550, 0x2573}, {0x2580, 0x258F}, {0x2592, 0x2595}, - {0x25A0, 0x25A1}, {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, - {0x25B6, 0x25B7}, {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, - {0x25C6, 0x25C8}, {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, - {0x25E2, 0x25E5}, {0x25EF, 0x25EF}, {0x2605, 0x2606}, - {0x2609, 0x2609}, {0x260E, 0x260F}, {0x2614, 0x2615}, - {0x261C, 0x261C}, {0x261E, 0x261E}, {0x2640, 0x2640}, - {0x2642, 0x2642}, {0x2660, 0x2661}, {0x2663, 0x2665}, - {0x2667, 0x266A}, {0x266C, 0x266D}, {0x266F, 0x266F}, - {0x273D, 0x273D}, {0x2776, 0x277F}, {0xE000, 0xF8FF}, - {0xFFFD, 0xFFFD}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}}; + {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, {0x00AA, 0x00AA}, {0x00AE, 0x00AE}, + {0x00B0, 0x00B4}, {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6}, {0x00D0, 0x00D0}, + {0x00D7, 0x00D8}, {0x00DE, 0x00E1}, {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, + {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, + {0x0101, 0x0101}, {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B}, {0x0126, 0x0127}, + {0x012B, 0x012B}, {0x0131, 0x0133}, {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144}, + {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153}, {0x0166, 0x0167}, {0x016B, 0x016B}, + {0x01CE, 0x01CE}, {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, {0x01D6, 0x01D6}, + {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261}, + {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB}, {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, + {0x02D8, 0x02DB}, {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0391, 0x03A1}, {0x03A3, 0x03A9}, + {0x03B1, 0x03C1}, {0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F}, {0x0451, 0x0451}, + {0x2010, 0x2010}, {0x2013, 0x2016}, {0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022}, + {0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033}, {0x2035, 0x2035}, {0x203B, 0x203B}, + {0x203E, 0x203E}, {0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084}, {0x20AC, 0x20AC}, + {0x2103, 0x2103}, {0x2105, 0x2105}, {0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116}, + {0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B}, {0x2153, 0x2154}, {0x215B, 0x215E}, + {0x2160, 0x216B}, {0x2170, 0x2179}, {0x2190, 0x2199}, {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, + {0x21D4, 0x21D4}, {0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203}, {0x2207, 0x2208}, + {0x220B, 0x220B}, {0x220F, 0x220F}, {0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A}, + {0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225}, {0x2227, 0x222C}, {0x222E, 0x222E}, + {0x2234, 0x2237}, {0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C}, {0x2252, 0x2252}, + {0x2260, 0x2261}, {0x2264, 0x2267}, {0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283}, + {0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299}, {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, + {0x2312, 0x2312}, {0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573}, {0x2580, 0x258F}, + {0x2592, 0x2595}, {0x25A0, 0x25A1}, {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7}, + {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8}, {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, + {0x25E2, 0x25E5}, {0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609}, {0x260E, 0x260F}, + {0x2614, 0x2615}, {0x261C, 0x261C}, {0x261E, 0x261E}, {0x2640, 0x2640}, {0x2642, 0x2642}, + {0x2660, 0x2661}, {0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D}, {0x266F, 0x266F}, + {0x273D, 0x273D}, {0x2776, 0x277F}, {0xE000, 0xF8FF}, {0xFFFD, 0xFFFD}, {0xF0000, 0xFFFFD}, + {0x100000, 0x10FFFD}}; /* binary search in table of non-spacing characters */ if (bisearch(ucs, ambiguous, sizeof(ambiguous) / sizeof(struct interval) - 1)) @@ -1651,36 +1411,36 @@ static inline int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n) { // convert UTF-8 string to wstring #ifdef _MSC_VER -static inline std::wstring utf8_decode(const std::string& s) { - auto r = setlocale(LC_ALL, ""); - std::string curLocale; - if (r) - curLocale = r; - const char* _Source = s.c_str(); - size_t _Dsize = std::strlen(_Source) + 1; - wchar_t* _Dest = new wchar_t[_Dsize]; - size_t _Osize; - mbstowcs_s(&_Osize, _Dest, _Dsize, _Source, _Dsize); - std::wstring result = _Dest; - delete[] _Dest; - setlocale(LC_ALL, curLocale.c_str()); - return result; +static inline std::wstring utf8_decode(const std::string &s) { + auto r = setlocale(LC_ALL, NULL); + std::string curLocale; + if (r) + curLocale = r; + const char *_Source = s.c_str(); + size_t _Dsize = std::strlen(_Source) + 1; + wchar_t *_Dest = new wchar_t[_Dsize]; + size_t _Osize; + mbstowcs_s(&_Osize, _Dest, _Dsize, _Source, _Dsize); + std::wstring result = _Dest; + delete[] _Dest; + setlocale(LC_ALL, curLocale.c_str()); + return result; } -#else -static inline std::wstring utf8_decode(const std::string& s) { - auto r = setlocale(LC_ALL, ""); - std::string curLocale; - if (r) - curLocale = r; - const char* _Source = s.c_str(); - size_t _Dsize = mbstowcs(NULL, _Source, 0) + 1; - wchar_t* _Dest = new wchar_t[_Dsize]; - wmemset(_Dest, 0, _Dsize); - mbstowcs(_Dest, _Source, _Dsize); - std::wstring result = _Dest; - delete[] _Dest; - setlocale(LC_ALL, curLocale.c_str()); - return result; +#else +static inline std::wstring utf8_decode(const std::string &s) { + auto r = setlocale(LC_ALL, NULL); + std::string curLocale; + if (r) + curLocale = r; + const char *_Source = s.c_str(); + size_t _Dsize = mbstowcs(NULL, _Source, 0) + 1; + wchar_t *_Dest = new wchar_t[_Dsize]; + wmemset(_Dest, 0, _Dsize); + mbstowcs(_Dest, _Source, _Dsize); + std::wstring result = _Dest; + delete[] _Dest; + setlocale(LC_ALL, curLocale.c_str()); + return result; } #endif @@ -1921,19 +1681,19 @@ class IndeterminateProgressScaleWriter { #ifndef INDICATORS_PROGRESS_BAR #define INDICATORS_PROGRESS_BAR +// #include // #include +// #include +// #include #include #include #include #include -// #include -// #include -// #include #include #include -#include #include +#include #include #include #include @@ -1943,129 +1703,117 @@ class IndeterminateProgressScaleWriter { namespace indicators { class ProgressBar { - using Settings = - std::tuple; + // clang-format off + using Settings = std::tuple; + // clang-format on public: template ::type...>::value, - void *>::type = nullptr> - explicit ProgressBar(Args &&... args) + typename std::enable_if::type...>::value, + void *>::type = nullptr> + explicit ProgressBar(Args &&...args) : settings_( - details::get( - option::BarWidth{100}, std::forward(args)...), - details::get( - option::PrefixText{}, std::forward(args)...), - details::get( - option::PostfixText{}, std::forward(args)...), - details::get( - option::Start{"["}, std::forward(args)...), - details::get( - option::End{"]"}, std::forward(args)...), - details::get( - option::Fill{"="}, std::forward(args)...), - details::get( - option::Lead{">"}, std::forward(args)...), - details::get( - option::Remainder{" "}, std::forward(args)...), + details::get(option::BarWidth{100}, + std::forward(args)...), + details::get(option::Start{"["}, + std::forward(args)...), + details::get(option::End{"]"}, + std::forward(args)...), + details::get(option::Fill{"="}, + std::forward(args)...), + details::get(option::Lead{">"}, + std::forward(args)...), + details::get(option::Remainder{" "}, + std::forward(args)...), + details::get(option::PrefixText{}, + std::forward(args)...), + details::get(option::PostfixText{}, + std::forward(args)...), details::get( option::MaxPostfixTextLen{0}, std::forward(args)...), - details::get( - option::Completed{false}, std::forward(args)...), - details::get( - option::ShowPercentage{false}, std::forward(args)...), + details::get(option::ShowPercentage{false}, + std::forward(args)...), details::get( option::ShowElapsedTime{false}, std::forward(args)...), details::get( option::ShowRemainingTime{false}, std::forward(args)...), details::get( option::SavedStartTime{false}, std::forward(args)...), + details::get(option::MinProgress{0}, + std::forward(args)...), + details::get(option::MaxProgress{100}, + std::forward(args)...), + details::get(option::Completed{false}, + std::forward(args)...), + details::get( + option::ProgressType{ProgressType::incremental}, std::forward(args)...), details::get( - option::ForegroundColor{Color::unspecified}, - std::forward(args)...), + option::ForegroundColor{Color::unspecified}, std::forward(args)...), details::get( - option::FontStyles{std::vector{}}, - std::forward(args)...), - details::get( - option::MinProgress{0}, std::forward(args)...), - details::get( - option::MaxProgress{100}, std::forward(args)...), - details::get( - option::ProgressType{ProgressType::incremental}, - std::forward(args)...), - details::get( - option::Stream{std::cout}, std::forward(args)...)) { + option::FontStyles{std::vector{}}, std::forward(args)...), + details::get(option::Stream{std::cout}, + std::forward(args)...)) { // if progress is incremental, start from min_progress // else start from max_progress const auto type = get_value(); if (type == ProgressType::incremental) - progress_ = get_value(); + tick_ = get_value(); else - progress_ = get_value(); + tick_ = get_value(); } template void set_option(details::Setting &&setting) { - static_assert( - !std::is_same( - std::declval()))>::type>::value, - "Setting has wrong type!"); + static_assert(!std::is_same( + std::declval()))>::type>::value, + "Setting has wrong type!"); std::lock_guard lock(mutex_); get_value() = std::move(setting).value; } template void set_option(const details::Setting &setting) { - static_assert( - !std::is_same( - std::declval()))>::type>::value, - "Setting has wrong type!"); + static_assert(!std::is_same( + std::declval()))>::type>::value, + "Setting has wrong type!"); std::lock_guard lock(mutex_); get_value() = setting.value; } - void - set_option(const details::Setting< - std::string, details::ProgressBarOption::postfix_text> &setting) { + void set_option( + const details::Setting &setting) { std::lock_guard lock(mutex_); get_value() = setting.value; - if (setting.value.length() > - get_value()) { - get_value() = - setting.value.length(); + if (setting.value.length() > get_value()) { + get_value() = setting.value.length(); } } - void set_option( - details::Setting - &&setting) { + void + set_option(details::Setting &&setting) { std::lock_guard lock(mutex_); - get_value() = - std::move(setting).value; + get_value() = std::move(setting).value; auto &new_value = get_value(); - if (new_value.length() > - get_value()) { - get_value() = - new_value.length(); + if (new_value.length() > get_value()) { + get_value() = new_value.length(); } } void set_progress(size_t new_progress) { { - std::lock_guard lock(mutex_); - progress_ = new_progress; + std::lock_guard lock{mutex_}; + tick_ = new_progress; } - save_start_time(); print_progress(); } @@ -2075,9 +1823,9 @@ class ProgressBar { std::lock_guard lock{mutex_}; const auto type = get_value(); if (type == ProgressType::incremental) - progress_ += 1; + tick_++; else - progress_ -= 1; + tick_--; } save_start_time(); print_progress(); @@ -2085,14 +1833,10 @@ class ProgressBar { size_t current() { std::lock_guard lock{mutex_}; - return (std::min)( - progress_, - size_t(get_value())); + return (std::min)(tick_, size_t(get_value())); } - bool is_completed() const { - return get_value(); - } + bool is_completed() const { return get_value(); } void mark_as_completed() { get_value() = true; @@ -2101,20 +1845,19 @@ class ProgressBar { private: template - auto get_value() - -> decltype((details::get_value(std::declval()).value)) { + auto get_value() -> decltype((details::get_value(std::declval()).value)) { return details::get_value(settings_).value; } template - auto get_value() const -> decltype( - (details::get_value(std::declval()).value)) { + auto get_value() const + -> decltype((details::get_value(std::declval()).value)) { return details::get_value(settings_).value; } - size_t progress_{0}; Settings settings_; - std::chrono::nanoseconds elapsed_; + size_t tick_{0}; + float progress_{0.0}; std::chrono::time_point start_time_point_; std::mutex mutex_; @@ -2123,12 +1866,9 @@ class ProgressBar { std::atomic multi_progress_mode_{false}; void save_start_time() { - auto &show_elapsed_time = - get_value(); - auto &saved_start_time = - get_value(); - auto &show_remaining_time = - get_value(); + auto &show_elapsed_time = get_value(); + auto &saved_start_time = get_value(); + auto &show_remaining_time = get_value(); if ((show_elapsed_time || show_remaining_time) && !saved_start_time) { start_time_point_ = std::chrono::high_resolution_clock::now(); saved_start_time = true; @@ -2145,24 +1885,19 @@ class ProgressBar { std::pair get_postfix_text() { std::stringstream os; - const auto max_progress = - get_value(); + auto now = std::chrono::high_resolution_clock::now(); + auto elapsed = std::chrono::duration_cast(now - start_time_point_); if (get_value()) { - os << " " - << (std::min)(static_cast(static_cast(progress_) / - max_progress * 100), - size_t(100)) - << "%"; + os << " " << (std::min)(static_cast(progress_ * 100.0), size_t(100)) << "%"; } - auto &saved_start_time = - get_value(); + auto &saved_start_time = get_value(); if (get_value()) { os << " ["; if (saved_start_time) - details::write_duration(os, elapsed_); + details::write_duration(os, elapsed); else os << "00:00s"; } @@ -2175,11 +1910,8 @@ class ProgressBar { if (saved_start_time) { auto eta = std::chrono::nanoseconds( - progress_ > 0 - ? static_cast(std::ceil(float(elapsed_.count()) * - max_progress / progress_)) - : 0); - auto remaining = eta > elapsed_ ? (eta - elapsed_) : (elapsed_ - eta); + tick_ > 0 ? static_cast(std::ceil(float(elapsed.count()) / progress_)) : 0); + auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); details::write_duration(os, remaining); } else { os << "00:00s"; @@ -2202,29 +1934,27 @@ class ProgressBar { void print_progress(bool from_multi_progress = false) { std::lock_guard lock{mutex_}; + if (get_value()) + return; + auto &os = get_value(); const auto type = get_value(); - const auto min_progress = - get_value(); - const auto max_progress = - get_value(); + const auto min_progress = get_value(); + const auto max_progress = get_value(); + + progress_ = static_cast(tick_) / max_progress; + + if ((type == ProgressType::incremental && tick_ >= max_progress) || + (type == ProgressType::decremental && tick_ <= min_progress)) { + get_value() = true; + } if (multi_progress_mode_ && !from_multi_progress) { - if ((type == ProgressType::incremental && progress_ >= max_progress) || - (type == ProgressType::decremental && progress_ <= min_progress)) { - get_value() = true; - } return; } - auto now = std::chrono::high_resolution_clock::now(); - if (!get_value()) - elapsed_ = std::chrono::duration_cast( - now - start_time_point_); - if (get_value() != - Color::unspecified) - details::set_stream_color( - os, get_value()); + if (get_value() != Color::unspecified) + details::set_stream_color(os, get_value()); for (auto &style : get_value()) details::set_font_style(os, style); @@ -2236,12 +1966,11 @@ class ProgressBar { os << get_value(); - details::ProgressScaleWriter writer{ - os, get_value(), - get_value(), - get_value(), - get_value()}; - writer.write(double(progress_) / double(max_progress) * 100.0f); + details::ProgressScaleWriter writer{os, get_value(), + get_value(), + get_value(), + get_value()}; + writer.write(progress_ * 100); os << get_value(); @@ -2256,7 +1985,8 @@ class ProgressBar { const auto end_length = get_value().size(); const auto terminal_width = terminal_size().second; // prefix + bar_width + postfix should be <= terminal_width - const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); + const int remaining = + terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); if (prefix_length == -1 || postfix_length == -1) { os << "\r"; } else if (remaining > 0) { @@ -2266,10 +1996,6 @@ class ProgressBar { } os.flush(); - if ((type == ProgressType::incremental && progress_ >= max_progress) || - (type == ProgressType::decremental && progress_ <= min_progress)) { - get_value() = true; - } if (get_value() && !from_multi_progress) // Don't std::endl if calling from MultiProgress os << termcolor::reset << std::endl; @@ -2281,21 +2007,22 @@ class ProgressBar { #endif + #ifndef INDICATORS_BLOCK_PROGRESS_BAR #define INDICATORS_BLOCK_PROGRESS_BAR // #include // #include +// #include +// #include #include #include #include -// #include -// #include #include #include -#include #include +#include #include #include #include @@ -2304,46 +2031,50 @@ class ProgressBar { namespace indicators { class BlockProgressBar { - using Settings = std::tuple; + // clang-format off + using Settings = std::tuple; + // clang-format on public: template ::type...>::value, void *>::type = nullptr> - explicit BlockProgressBar(Args &&... args) - : settings_(details::get( - option::ForegroundColor{Color::unspecified}, std::forward(args)...), - details::get(option::BarWidth{100}, + explicit BlockProgressBar(Args &&...args) + : settings_(details::get(option::BarWidth{100}, std::forward(args)...), details::get(option::Start{"["}, std::forward(args)...), details::get(option::End{"]"}, std::forward(args)...), details::get( - option::PrefixText{""}, std::forward(args)...), + option::PrefixText{}, std::forward(args)...), details::get( - option::PostfixText{""}, std::forward(args)...), + option::PostfixText{}, std::forward(args)...), + details::get( + option::MaxPostfixTextLen{0}, std::forward(args)...), details::get( option::ShowPercentage{true}, std::forward(args)...), details::get( option::ShowElapsedTime{false}, std::forward(args)...), details::get( option::ShowRemainingTime{false}, std::forward(args)...), - details::get(option::Completed{false}, - std::forward(args)...), details::get( option::SavedStartTime{false}, std::forward(args)...), - details::get( - option::MaxPostfixTextLen{0}, std::forward(args)...), - details::get( - option::FontStyles{std::vector{}}, std::forward(args)...), details::get( option::MaxProgress{100}, std::forward(args)...), + details::get(option::Completed{false}, + std::forward(args)...), + details::get( + option::ForegroundColor{Color::unspecified}, std::forward(args)...), + details::get( + option::FontStyles{std::vector{}}, std::forward(args)...), details::get(option::Stream{std::cout}, std::forward(args)...)) {} @@ -2384,10 +2115,10 @@ class BlockProgressBar { } } - void set_progress(float value) { + void set_progress(size_t new_progress) { { std::lock_guard lock{mutex_}; - progress_ = value; + tick_ = new_progress; } save_start_time(); print_progress(); @@ -2396,7 +2127,7 @@ class BlockProgressBar { void tick() { { std::lock_guard lock{mutex_}; - progress_ += 1; + tick_++; } save_start_time(); print_progress(); @@ -2404,8 +2135,7 @@ class BlockProgressBar { size_t current() { std::lock_guard lock{mutex_}; - return (std::min)(static_cast(progress_), - size_t(get_value())); + return (std::min)(tick_, size_t(get_value())); } bool is_completed() const { return get_value(); } @@ -2428,6 +2158,7 @@ class BlockProgressBar { } Settings settings_; + size_t tick_{0}; float progress_{0.0}; std::chrono::time_point start_time_point_; std::mutex mutex_; @@ -2456,13 +2187,11 @@ class BlockProgressBar { std::pair get_postfix_text() { std::stringstream os; - const auto max_progress = get_value(); auto now = std::chrono::high_resolution_clock::now(); auto elapsed = std::chrono::duration_cast(now - start_time_point_); if (get_value()) { - os << " " << (std::min)(static_cast(progress_ / max_progress * 100.0), size_t(100)) - << "%"; + os << " " << (std::min)(static_cast(progress_ * 100.0), size_t(100)) << "%"; } auto &saved_start_time = get_value(); @@ -2483,10 +2212,7 @@ class BlockProgressBar { if (saved_start_time) { auto eta = std::chrono::nanoseconds( - progress_ > 0 - ? static_cast(std::ceil(float(elapsed.count()) * - max_progress / progress_)) - : 0); + tick_ > 0 ? static_cast(std::ceil(float(elapsed.count()) / progress_)) : 0); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); details::write_duration(os, remaining); } else { @@ -2510,13 +2236,19 @@ class BlockProgressBar { void print_progress(bool from_multi_progress = false) { std::lock_guard lock{mutex_}; + if (get_value()) + return; + auto &os = get_value(); const auto max_progress = get_value(); + + progress_ = static_cast(tick_) / max_progress; + + if (tick_ >= max_progress) { + get_value() = true; + } if (multi_progress_mode_ && !from_multi_progress) { - if (progress_ > max_progress) { - get_value() = true; - } return; } @@ -2535,7 +2267,7 @@ class BlockProgressBar { details::BlockProgressScaleWriter writer{os, get_value()}; - writer.write(progress_ / max_progress * 100); + writer.write(progress_ * 100); os << get_value(); @@ -2550,7 +2282,8 @@ class BlockProgressBar { const auto end_length = get_value().size(); const auto terminal_width = terminal_size().second; // prefix + bar_width + postfix should be <= terminal_width - const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); + const int remaining = + terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); if (prefix_length == -1 || postfix_length == -1) { os << "\r"; } else if (remaining > 0) { @@ -2560,9 +2293,6 @@ class BlockProgressBar { } os.flush(); - if (progress_ > max_progress) { - get_value() = true; - } if (get_value() && !from_multi_progress) // Don't std::endl if calling from MultiProgress os << termcolor::reset << std::endl; @@ -2574,36 +2304,40 @@ class BlockProgressBar { #endif + #ifndef INDICATORS_INDETERMINATE_PROGRESS_BAR #define INDICATORS_INDETERMINATE_PROGRESS_BAR +// #include // #include +// #include +// #include #include #include #include #include -// #include -// #include -// #include #include #include #include +#include #include #include #include #include -#include #include namespace indicators { class IndeterminateProgressBar { - using Settings = - std::tuple; - + // clang-format off + using Settings = std::tuple; + // clang-format on enum class Direction { forward, backward }; Direction direction_{Direction::forward}; @@ -2613,13 +2347,9 @@ class IndeterminateProgressBar { typename std::enable_if::type...>::value, void *>::type = nullptr> - explicit IndeterminateProgressBar(Args &&... args) + explicit IndeterminateProgressBar(Args &&...args) : settings_(details::get(option::BarWidth{100}, std::forward(args)...), - details::get( - option::PrefixText{}, std::forward(args)...), - details::get( - option::PostfixText{}, std::forward(args)...), details::get(option::Start{"["}, std::forward(args)...), details::get(option::End{"]"}, @@ -2628,6 +2358,10 @@ class IndeterminateProgressBar { std::forward(args)...), details::get(option::Lead{"<==>"}, std::forward(args)...), + details::get( + option::PrefixText{}, std::forward(args)...), + details::get( + option::PostfixText{}, std::forward(args)...), details::get( option::MaxPostfixTextLen{0}, std::forward(args)...), details::get(option::Completed{false}, @@ -2645,7 +2379,6 @@ class IndeterminateProgressBar { // ^^^^^^^^^^^^^^^^^ bar_width // ^^^^^^^^^^^^ (bar_width - len(lead)) // progress_ = bar_width - len(lead) - progress_ = 0; max_progress_ = get_value() - get_value().size() + get_value().size() + @@ -2695,11 +2428,11 @@ class IndeterminateProgressBar { if (get_value()) return; - progress_ += (direction_ == Direction::forward) ? 1 : -1; - if (direction_ == Direction::forward && progress_ == max_progress_) { + tick_ += (direction_ == Direction::forward) ? 1 : -1; + if (direction_ == Direction::forward && tick_ == max_progress_) { // time to go back direction_ = Direction::backward; - } else if (direction_ == Direction::backward && progress_ == 0) { + } else if (direction_ == Direction::backward && tick_ == 0) { direction_ = Direction::forward; } } @@ -2725,9 +2458,9 @@ class IndeterminateProgressBar { return details::get_value(settings_).value; } - size_t progress_{0}; - size_t max_progress_; Settings settings_; + size_t tick_{0}; + size_t max_progress_; std::chrono::nanoseconds elapsed_; std::mutex mutex_; @@ -2778,7 +2511,7 @@ class IndeterminateProgressBar { os, get_value(), get_value(), get_value()}; - writer.write(progress_); + writer.write(tick_); os << get_value(); @@ -2793,7 +2526,8 @@ class IndeterminateProgressBar { const auto end_length = get_value().size(); const auto terminal_width = terminal_size().second; // prefix + bar_width + postfix should be <= terminal_width - const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); + const int remaining = + terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length); if (prefix_length == -1 || postfix_length == -1) { os << "\r"; } else if (remaining > 0) { @@ -2814,6 +2548,7 @@ class IndeterminateProgressBar { #endif + #ifndef INDICATORS_MULTI_PROGRESS #define INDICATORS_MULTI_PROGRESS #include @@ -2832,7 +2567,7 @@ template class MultiProgress { public: template ::type> - explicit MultiProgress(Indicators &... bars) { + explicit MultiProgress(Indicators &...bars) { bars_ = {bars...}; for (auto &bar : bars_) { bar.get().multi_progress_mode_ = true; @@ -2903,11 +2638,12 @@ template class MultiProgress { #include #include // #include -// #include // #include // #include // #include +// #include #include +#include #include #include @@ -2917,10 +2653,10 @@ template class DynamicProgress { using Settings = std::tuple; public: - template explicit DynamicProgress(Indicators &... bars) { - bars_ = {bars...}; + template explicit DynamicProgress(Indicators &&...bars) { + (bars_.emplace_back(std::move(bars)), ...); for (auto &bar : bars_) { - bar.get().multi_progress_mode_ = true; + bar->multi_progress_mode_ = true; ++total_count_; ++incomplete_count_; } @@ -2929,13 +2665,13 @@ template class DynamicProgress { Indicator &operator[](size_t index) { print_progress(); std::lock_guard lock{mutex_}; - return bars_[index].get(); + return *bars_[index]; } - size_t push_back(Indicator &bar) { + size_t push_back(std::unique_ptr bar) { std::lock_guard lock{mutex_}; - bar.multi_progress_mode_ = true; - bars_.push_back(bar); + bar->multi_progress_mode_ = true; + bars_.push_back(std::move(bar)); return bars_.size() - 1; } @@ -2961,7 +2697,7 @@ template class DynamicProgress { Settings settings_; std::atomic started_{false}; std::mutex mutex_; - std::vector> bars_; + std::vector> bars_; std::atomic total_count_{0}; std::atomic incomplete_count_{0}; @@ -2991,8 +2727,8 @@ template class DynamicProgress { } incomplete_count_ = 0; for (auto &bar : bars_) { - if (!bar.get().is_completed()) { - bar.get().print_progress(true); + if (!bar->is_completed()) { + bar->print_progress(true); std::cout << "\n"; ++incomplete_count_; } @@ -3004,7 +2740,7 @@ template class DynamicProgress { if (started_) move_up(static_cast(total_count_)); for (auto &bar : bars_) { - bar.get().print_progress(true); + bar->print_progress(true); std::cout << "\n"; } if (!started_) @@ -3020,17 +2756,18 @@ template class DynamicProgress { #endif + #ifndef INDICATORS_PROGRESS_SPINNER #define INDICATORS_PROGRESS_SPINNER +// #include // #include +// #include #include #include #include #include -// #include -// #include #include #include #include @@ -3042,48 +2779,51 @@ template class DynamicProgress { namespace indicators { class ProgressSpinner { - using Settings = - std::tuple; + // clang-format off + using Settings = std::tuple; + // clang-format on public: template ::type...>::value, void *>::type = nullptr> - explicit ProgressSpinner(Args &&... args) + explicit ProgressSpinner(Args &&...args) : settings_( - details::get( - option::ForegroundColor{Color::unspecified}, std::forward(args)...), + details::get(option::ShowSpinner{true}, + std::forward(args)...), + details::get( + option::SpinnerStates{ + std::vector{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}}, + std::forward(args)...), details::get(option::PrefixText{}, std::forward(args)...), details::get(option::PostfixText{}, std::forward(args)...), + details::get( + option::MaxPostfixTextLen{0}, std::forward(args)...), details::get(option::ShowPercentage{true}, std::forward(args)...), details::get( option::ShowElapsedTime{false}, std::forward(args)...), details::get( option::ShowRemainingTime{false}, std::forward(args)...), - details::get(option::ShowSpinner{true}, - std::forward(args)...), details::get( option::SavedStartTime{false}, std::forward(args)...), + details::get(option::MaxProgress{100}, + std::forward(args)...), details::get(option::Completed{false}, std::forward(args)...), - details::get( - option::MaxPostfixTextLen{0}, std::forward(args)...), - details::get( - option::SpinnerStates{ - std::vector{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}}, - std::forward(args)...), + details::get( + option::ForegroundColor{Color::unspecified}, std::forward(args)...), details::get( option::FontStyles{std::vector{}}, std::forward(args)...), - details::get(option::MaxProgress{100}, - std::forward(args)...), details::get(option::Stream{std::cout}, std::forward(args)...)) {} @@ -3124,10 +2864,10 @@ class ProgressSpinner { } } - void set_progress(size_t value) { + void set_progress(size_t new_progress) { { std::lock_guard lock{mutex_}; - progress_ = value; + tick_ = new_progress; } save_start_time(); print_progress(); @@ -3136,7 +2876,7 @@ class ProgressSpinner { void tick() { { std::lock_guard lock{mutex_}; - progress_ += 1; + tick_++; } save_start_time(); print_progress(); @@ -3144,7 +2884,7 @@ class ProgressSpinner { size_t current() { std::lock_guard lock{mutex_}; - return (std::min)(progress_, size_t(get_value())); + return (std::min)(tick_, size_t(get_value())); } bool is_completed() const { return get_value(); } @@ -3155,12 +2895,6 @@ class ProgressSpinner { } private: - Settings settings_; - size_t progress_{0}; - size_t index_{0}; - std::chrono::time_point start_time_point_; - std::mutex mutex_; - template auto get_value() -> decltype((details::get_value(std::declval()).value)) { return details::get_value(settings_).value; @@ -3172,6 +2906,13 @@ class ProgressSpinner { return details::get_value(settings_).value; } + Settings settings_; + size_t tick_{0}; + size_t index_{0}; + float progress_{0.0}; + std::chrono::time_point start_time_point_; + std::mutex mutex_; + void save_start_time() { auto &show_elapsed_time = get_value(); auto &show_remaining_time = get_value(); @@ -3189,6 +2930,9 @@ class ProgressSpinner { auto &os = get_value(); const auto max_progress = get_value(); + + progress_ = static_cast(tick_) / max_progress; + auto now = std::chrono::high_resolution_clock::now(); auto elapsed = std::chrono::duration_cast(now - start_time_point_); @@ -3203,7 +2947,7 @@ class ProgressSpinner { os << get_value() [index_ % get_value().size()]; if (get_value()) { - os << " " << std::size_t(progress_ / double(max_progress) * 100) << "%"; + os << " " << std::size_t(progress_ * 100) << "%"; } if (get_value()) { @@ -3217,10 +2961,7 @@ class ProgressSpinner { else os << " ["; auto eta = std::chrono::nanoseconds( - progress_ > 0 - ? static_cast(std::ceil(float(elapsed.count()) * - max_progress / progress_)) - : 0); + tick_ > 0 ? static_cast(std::ceil(float(elapsed.count()) / progress_)) : 0); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); details::write_duration(os, remaining); os << "]"; @@ -3235,7 +2976,7 @@ class ProgressSpinner { << std::string(get_value(), ' ') << "\r"; os.flush(); index_ += 1; - if (progress_ > max_progress) { + if (tick_ > max_progress) { get_value() = true; } if (get_value()) @@ -3247,3 +2988,4 @@ class ProgressSpinner { #endif +