26 #ifndef INDICATORS_COLOR
27 #define INDICATORS_COLOR
37 #ifndef INDICATORS_FONT_STYLE
38 #define INDICATORS_FONT_STYLE
48 #ifndef INDICATORS_PROGRESS_TYPE
49 #define INDICATORS_PROGRESS_TYPE
68 #ifndef TERMCOLOR_HPP_
69 #define TERMCOLOR_HPP_
77 #if defined(_WIN32) || defined(_WIN64)
78 # define TERMCOLOR_TARGET_WINDOWS
79 #elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
80 # define TERMCOLOR_TARGET_POSIX
85 #if !defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) && !defined(TERMCOLOR_USE_WINDOWS_API) && !defined(TERMCOLOR_USE_NOOP)
86 # if defined(TERMCOLOR_TARGET_POSIX)
87 # define TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES
88 # define TERMCOLOR_AUTODETECTED_IMPLEMENTATION
89 # elif defined(TERMCOLOR_TARGET_WINDOWS)
90 # define TERMCOLOR_USE_WINDOWS_API
91 # define TERMCOLOR_AUTODETECTED_IMPLEMENTATION
97 #if defined(TERMCOLOR_TARGET_POSIX)
99 #elif defined(TERMCOLOR_TARGET_WINDOWS)
100 #if defined(_MSC_VER)
101 #if !defined(NOMINMAX)
106 # include <windows.h>
116 inline int colorize_index();
117 inline FILE* get_standard_stream(
const std::ostream& stream);
118 inline bool is_colorized(std::ostream& stream);
119 inline bool is_atty(
const std::ostream& stream);
121 #if defined(TERMCOLOR_TARGET_WINDOWS)
122 inline void win_change_attributes(std::ostream& stream,
int foreground,
int background=-1);
127 std::ostream& colorize(std::ostream& stream)
129 stream.iword(_internal::colorize_index()) = 1L;
134 std::ostream& nocolorize(std::ostream& stream)
136 stream.iword(_internal::colorize_index()) = 0L;
141 std::ostream& reset(std::ostream& stream)
143 if (_internal::is_colorized(stream))
145 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
146 stream <<
"\033[00m";
147 #elif defined(TERMCOLOR_USE_WINDOWS_API)
148 _internal::win_change_attributes(stream, -1, -1);
155 std::ostream&
bold(std::ostream& stream)
157 if (_internal::is_colorized(stream))
159 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
161 #elif defined(TERMCOLOR_USE_WINDOWS_API)
168 std::ostream&
dark(std::ostream& stream)
170 if (_internal::is_colorized(stream))
172 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
174 #elif defined(TERMCOLOR_USE_WINDOWS_API)
181 std::ostream&
italic(std::ostream& stream)
183 if (_internal::is_colorized(stream))
185 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
187 #elif defined(TERMCOLOR_USE_WINDOWS_API)
194 std::ostream&
underline(std::ostream& stream)
196 if (_internal::is_colorized(stream))
198 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
200 #elif defined(TERMCOLOR_USE_WINDOWS_API)
201 _internal::win_change_attributes(stream, -1, COMMON_LVB_UNDERSCORE);
208 std::ostream&
blink(std::ostream& stream)
210 if (_internal::is_colorized(stream))
212 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
214 #elif defined(TERMCOLOR_USE_WINDOWS_API)
221 std::ostream&
reverse(std::ostream& stream)
223 if (_internal::is_colorized(stream))
225 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
227 #elif defined(TERMCOLOR_USE_WINDOWS_API)
234 std::ostream&
concealed(std::ostream& stream)
236 if (_internal::is_colorized(stream))
238 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
240 #elif defined(TERMCOLOR_USE_WINDOWS_API)
247 std::ostream&
crossed(std::ostream& stream)
249 if (_internal::is_colorized(stream))
251 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
253 #elif defined(TERMCOLOR_USE_WINDOWS_API)
259 template <u
int8_t code>
inline
260 std::ostream& color(std::ostream& stream)
262 if (_internal::is_colorized(stream))
264 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
266 std::snprintf(command,
sizeof(command),
"\033[38;5;%dm", code);
268 #elif defined(TERMCOLOR_USE_WINDOWS_API)
274 template <u
int8_t code>
inline
275 std::ostream& on_color(std::ostream& stream)
277 if (_internal::is_colorized(stream))
279 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
281 std::snprintf(command,
sizeof(command),
"\033[48;5;%dm", code);
283 #elif defined(TERMCOLOR_USE_WINDOWS_API)
289 template <u
int8_t r, u
int8_t g, u
int8_t b>
inline
290 std::ostream& color(std::ostream& stream)
292 if (_internal::is_colorized(stream))
294 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
296 std::snprintf(command,
sizeof(command),
"\033[38;2;%d;%d;%dm", r, g, b);
298 #elif defined(TERMCOLOR_USE_WINDOWS_API)
304 template <u
int8_t r, u
int8_t g, u
int8_t b>
inline
305 std::ostream& on_color(std::ostream& stream)
307 if (_internal::is_colorized(stream))
309 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
311 std::snprintf(command,
sizeof(command),
"\033[48;2;%d;%d;%dm", r, g, b);
313 #elif defined(TERMCOLOR_USE_WINDOWS_API)
320 std::ostream&
grey(std::ostream& stream)
322 if (_internal::is_colorized(stream))
324 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
325 stream <<
"\033[30m";
326 #elif defined(TERMCOLOR_USE_WINDOWS_API)
327 _internal::win_change_attributes(stream,
336 std::ostream&
red(std::ostream& stream)
338 if (_internal::is_colorized(stream))
340 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
341 stream <<
"\033[31m";
342 #elif defined(TERMCOLOR_USE_WINDOWS_API)
343 _internal::win_change_attributes(stream,
352 std::ostream&
green(std::ostream& stream)
354 if (_internal::is_colorized(stream))
356 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
357 stream <<
"\033[32m";
358 #elif defined(TERMCOLOR_USE_WINDOWS_API)
359 _internal::win_change_attributes(stream,
368 std::ostream&
yellow(std::ostream& stream)
370 if (_internal::is_colorized(stream))
372 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
373 stream <<
"\033[33m";
374 #elif defined(TERMCOLOR_USE_WINDOWS_API)
375 _internal::win_change_attributes(stream,
376 FOREGROUND_GREEN | FOREGROUND_RED
384 std::ostream&
blue(std::ostream& stream)
386 if (_internal::is_colorized(stream))
388 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
389 stream <<
"\033[34m";
390 #elif defined(TERMCOLOR_USE_WINDOWS_API)
391 _internal::win_change_attributes(stream,
400 std::ostream&
magenta(std::ostream& stream)
402 if (_internal::is_colorized(stream))
404 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
405 stream <<
"\033[35m";
406 #elif defined(TERMCOLOR_USE_WINDOWS_API)
407 _internal::win_change_attributes(stream,
408 FOREGROUND_BLUE | FOREGROUND_RED
416 std::ostream&
cyan(std::ostream& stream)
418 if (_internal::is_colorized(stream))
420 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
421 stream <<
"\033[36m";
422 #elif defined(TERMCOLOR_USE_WINDOWS_API)
423 _internal::win_change_attributes(stream,
424 FOREGROUND_BLUE | FOREGROUND_GREEN
432 std::ostream&
white(std::ostream& stream)
434 if (_internal::is_colorized(stream))
436 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
437 stream <<
"\033[37m";
438 #elif defined(TERMCOLOR_USE_WINDOWS_API)
439 _internal::win_change_attributes(stream,
440 FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
449 std::ostream& bright_grey(std::ostream& stream)
451 if (_internal::is_colorized(stream))
453 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
454 stream <<
"\033[90m";
455 #elif defined(TERMCOLOR_USE_WINDOWS_API)
456 _internal::win_change_attributes(stream,
457 0 | FOREGROUND_INTENSITY
465 std::ostream& bright_red(std::ostream& stream)
467 if (_internal::is_colorized(stream))
469 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
470 stream <<
"\033[91m";
471 #elif defined(TERMCOLOR_USE_WINDOWS_API)
472 _internal::win_change_attributes(stream,
473 FOREGROUND_RED | FOREGROUND_INTENSITY
481 std::ostream& bright_green(std::ostream& stream)
483 if (_internal::is_colorized(stream))
485 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
486 stream <<
"\033[92m";
487 #elif defined(TERMCOLOR_USE_WINDOWS_API)
488 _internal::win_change_attributes(stream,
489 FOREGROUND_GREEN | FOREGROUND_INTENSITY
497 std::ostream& bright_yellow(std::ostream& stream)
499 if (_internal::is_colorized(stream))
501 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
502 stream <<
"\033[93m";
503 #elif defined(TERMCOLOR_USE_WINDOWS_API)
504 _internal::win_change_attributes(stream,
505 FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
513 std::ostream& bright_blue(std::ostream& stream)
515 if (_internal::is_colorized(stream))
517 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
518 stream <<
"\033[94m";
519 #elif defined(TERMCOLOR_USE_WINDOWS_API)
520 _internal::win_change_attributes(stream,
521 FOREGROUND_BLUE | FOREGROUND_INTENSITY
529 std::ostream& bright_magenta(std::ostream& stream)
531 if (_internal::is_colorized(stream))
533 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
534 stream <<
"\033[95m";
535 #elif defined(TERMCOLOR_USE_WINDOWS_API)
536 _internal::win_change_attributes(stream,
537 FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY
545 std::ostream& bright_cyan(std::ostream& stream)
547 if (_internal::is_colorized(stream))
549 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
550 stream <<
"\033[96m";
551 #elif defined(TERMCOLOR_USE_WINDOWS_API)
552 _internal::win_change_attributes(stream,
553 FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY
561 std::ostream& bright_white(std::ostream& stream)
563 if (_internal::is_colorized(stream))
565 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
566 stream <<
"\033[97m";
567 #elif defined(TERMCOLOR_USE_WINDOWS_API)
568 _internal::win_change_attributes(stream,
569 FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
578 std::ostream& on_grey(std::ostream& stream)
580 if (_internal::is_colorized(stream))
582 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
583 stream <<
"\033[40m";
584 #elif defined(TERMCOLOR_USE_WINDOWS_API)
585 _internal::win_change_attributes(stream, -1,
594 std::ostream& on_red(std::ostream& stream)
596 if (_internal::is_colorized(stream))
598 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
599 stream <<
"\033[41m";
600 #elif defined(TERMCOLOR_USE_WINDOWS_API)
601 _internal::win_change_attributes(stream, -1,
610 std::ostream& on_green(std::ostream& stream)
612 if (_internal::is_colorized(stream))
614 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
615 stream <<
"\033[42m";
616 #elif defined(TERMCOLOR_USE_WINDOWS_API)
617 _internal::win_change_attributes(stream, -1,
626 std::ostream& on_yellow(std::ostream& stream)
628 if (_internal::is_colorized(stream))
630 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
631 stream <<
"\033[43m";
632 #elif defined(TERMCOLOR_USE_WINDOWS_API)
633 _internal::win_change_attributes(stream, -1,
634 BACKGROUND_GREEN | BACKGROUND_RED
642 std::ostream& on_blue(std::ostream& stream)
644 if (_internal::is_colorized(stream))
646 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
647 stream <<
"\033[44m";
648 #elif defined(TERMCOLOR_USE_WINDOWS_API)
649 _internal::win_change_attributes(stream, -1,
658 std::ostream& on_magenta(std::ostream& stream)
660 if (_internal::is_colorized(stream))
662 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
663 stream <<
"\033[45m";
664 #elif defined(TERMCOLOR_USE_WINDOWS_API)
665 _internal::win_change_attributes(stream, -1,
666 BACKGROUND_BLUE | BACKGROUND_RED
674 std::ostream& on_cyan(std::ostream& stream)
676 if (_internal::is_colorized(stream))
678 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
679 stream <<
"\033[46m";
680 #elif defined(TERMCOLOR_USE_WINDOWS_API)
681 _internal::win_change_attributes(stream, -1,
682 BACKGROUND_GREEN | BACKGROUND_BLUE
690 std::ostream& on_white(std::ostream& stream)
692 if (_internal::is_colorized(stream))
694 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
695 stream <<
"\033[47m";
696 #elif defined(TERMCOLOR_USE_WINDOWS_API)
697 _internal::win_change_attributes(stream, -1,
698 BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
708 std::ostream& on_bright_grey(std::ostream& stream)
710 if (_internal::is_colorized(stream))
712 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
713 stream <<
"\033[100m";
714 #elif defined(TERMCOLOR_USE_WINDOWS_API)
715 _internal::win_change_attributes(stream, -1,
716 0 | BACKGROUND_INTENSITY
724 std::ostream& on_bright_red(std::ostream& stream)
726 if (_internal::is_colorized(stream))
728 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
729 stream <<
"\033[101m";
730 #elif defined(TERMCOLOR_USE_WINDOWS_API)
731 _internal::win_change_attributes(stream, -1,
732 BACKGROUND_RED | BACKGROUND_INTENSITY
740 std::ostream& on_bright_green(std::ostream& stream)
742 if (_internal::is_colorized(stream))
744 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
745 stream <<
"\033[102m";
746 #elif defined(TERMCOLOR_USE_WINDOWS_API)
747 _internal::win_change_attributes(stream, -1,
748 BACKGROUND_GREEN | BACKGROUND_INTENSITY
756 std::ostream& on_bright_yellow(std::ostream& stream)
758 if (_internal::is_colorized(stream))
760 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
761 stream <<
"\033[103m";
762 #elif defined(TERMCOLOR_USE_WINDOWS_API)
763 _internal::win_change_attributes(stream, -1,
764 BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY
772 std::ostream& on_bright_blue(std::ostream& stream)
774 if (_internal::is_colorized(stream))
776 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
777 stream <<
"\033[104m";
778 #elif defined(TERMCOLOR_USE_WINDOWS_API)
779 _internal::win_change_attributes(stream, -1,
780 BACKGROUND_BLUE | BACKGROUND_INTENSITY
788 std::ostream& on_bright_magenta(std::ostream& stream)
790 if (_internal::is_colorized(stream))
792 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
793 stream <<
"\033[105m";
794 #elif defined(TERMCOLOR_USE_WINDOWS_API)
795 _internal::win_change_attributes(stream, -1,
796 BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY
804 std::ostream& on_bright_cyan(std::ostream& stream)
806 if (_internal::is_colorized(stream))
808 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
809 stream <<
"\033[106m";
810 #elif defined(TERMCOLOR_USE_WINDOWS_API)
811 _internal::win_change_attributes(stream, -1,
812 BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY
820 std::ostream& on_bright_white(std::ostream& stream)
822 if (_internal::is_colorized(stream))
824 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
825 stream <<
"\033[107m";
826 #elif defined(TERMCOLOR_USE_WINDOWS_API)
827 _internal::win_change_attributes(stream, -1,
828 BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY
849 inline int colorize_index()
851 static int colorize_index = std::ios_base::xalloc();
852 return colorize_index;
859 FILE* get_standard_stream(
const std::ostream& stream)
861 if (&stream == &std::cout)
863 else if ((&stream == &std::cerr) || (&stream == &std::clog))
873 bool is_colorized(std::ostream& stream)
875 return is_atty(stream) ||
static_cast<bool>(stream.iword(colorize_index()));
881 bool is_atty(
const std::ostream& stream)
883 FILE* std_stream = get_standard_stream(stream);
892 #if defined(TERMCOLOR_TARGET_POSIX)
893 return ::isatty(fileno(std_stream));
894 #elif defined(TERMCOLOR_TARGET_WINDOWS)
895 return ::_isatty(_fileno(std_stream));
901 #if defined(TERMCOLOR_TARGET_WINDOWS)
904 inline void win_change_attributes(std::ostream& stream,
int foreground,
int background)
907 static WORD defaultAttributes = 0;
913 if (!_internal::is_atty(stream))
917 HANDLE hTerminal = INVALID_HANDLE_VALUE;
918 if (&stream == &std::cout)
919 hTerminal = GetStdHandle(STD_OUTPUT_HANDLE);
920 else if (&stream == &std::cerr)
921 hTerminal = GetStdHandle(STD_ERROR_HANDLE);
924 if (!defaultAttributes)
926 CONSOLE_SCREEN_BUFFER_INFO info;
927 if (!GetConsoleScreenBufferInfo(hTerminal, &info))
929 defaultAttributes = info.wAttributes;
933 if (foreground == -1 && background == -1)
935 SetConsoleTextAttribute(hTerminal, defaultAttributes);
940 CONSOLE_SCREEN_BUFFER_INFO info;
941 if (!GetConsoleScreenBufferInfo(hTerminal, &info))
944 if (foreground != -1)
946 info.wAttributes &= ~(info.wAttributes & 0x0F);
947 info.wAttributes |=
static_cast<WORD
>(foreground);
950 if (background != -1)
952 info.wAttributes &= ~(info.wAttributes & 0xF0);
953 info.wAttributes |=
static_cast<WORD
>(background);
956 SetConsoleTextAttribute(hTerminal, info.wAttributes);
965 #undef TERMCOLOR_TARGET_POSIX
966 #undef TERMCOLOR_TARGET_WINDOWS
968 #if defined(TERMCOLOR_AUTODETECTED_IMPLEMENTATION)
969 # undef TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES
970 # undef TERMCOLOR_USE_WINDOWS_API
977 #ifndef INDICATORS_TERMINAL_SIZE
978 #define INDICATORS_TERMINAL_SIZE
987 static inline std::pair<size_t, size_t> terminal_size() {
988 CONSOLE_SCREEN_BUFFER_INFO csbi;
990 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
991 cols = csbi.srWindow.Right - csbi.srWindow.Left + 1;
992 rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
993 return {
static_cast<size_t>(rows),
static_cast<size_t>(cols)};
996 static inline size_t terminal_width() {
return terminal_size().second; }
1002 #include <sys/ioctl.h>
1007 static inline std::pair<size_t, size_t> terminal_size() {
1008 struct winsize size{};
1009 ioctl(STDOUT_FILENO, TIOCGWINSZ, &size);
1010 return {
static_cast<size_t>(size.ws_row),
static_cast<size_t>(size.ws_col)};
1013 static inline size_t terminal_width() {
return terminal_size().second; }
1048 #ifndef INDICATORS_SETTING
1049 #define INDICATORS_SETTING
1057 #include <type_traits>
1065 template <
bool condition>
struct if_else;
1067 template <>
struct if_else<true> {
using type = std::true_type; };
1069 template <>
struct if_else<false> {
using type = std::false_type; };
1071 template <
bool condition,
typename True,
typename False>
struct if_else_type;
1073 template <
typename True,
typename False>
struct if_else_type<true, True, False> {
1077 template <
typename True,
typename False>
struct if_else_type<false, True, False> {
1081 template <
typename... Ops>
struct conjuction;
1083 template <>
struct conjuction<> : std::true_type {};
1085 template <
typename Op,
typename... TailOps>
1086 struct conjuction<Op, TailOps...>
1087 : if_else_type<!Op::value, std::false_type, conjuction<TailOps...>>::type {};
1089 template <
typename... Ops>
struct disjunction;
1091 template <>
struct disjunction<> : std::false_type {};
1093 template <
typename Op,
typename... TailOps>
1094 struct disjunction<Op, TailOps...>
1095 : if_else_type<Op::value, std::true_type, disjunction<TailOps...>>::type {};
1097 enum class ProgressBarOption {
1106 max_postfix_text_len,
1110 show_remaining_time,
1116 hide_bar_when_complete,
1123 template <
typename T, ProgressBarOption Id>
struct Setting {
1124 template <
typename... Args,
1125 typename =
typename std::enable_if<std::is_constructible<T, Args...>::value>::type>
1126 explicit Setting(Args &&... args) : value(std::forward<Args>(args)...) {}
1127 Setting(
const Setting &) =
default;
1128 Setting(Setting &&) =
default;
1130 static constexpr
auto id = Id;
1136 template <
typename T>
struct is_setting : std::false_type {};
1138 template <ProgressBarOption Id,
typename T>
struct is_setting<Setting<T, Id>> : std::true_type {};
1140 template <
typename... Args>
1141 struct are_settings : if_else<conjuction<is_setting<Args>...>::value>::type {};
1143 template <>
struct are_settings<> : std::true_type {};
1145 template <
typename Setting,
typename Tuple>
struct is_setting_from_tuple;
1147 template <
typename Setting>
struct is_setting_from_tuple<Setting, std::tuple<>> : std::true_type {};
1149 template <
typename Setting,
typename... TupleTypes>
1150 struct is_setting_from_tuple<Setting, std::tuple<TupleTypes...>>
1151 : if_else<disjunction<std::is_same<Setting, TupleTypes>...>::value>::type {};
1153 template <
typename Tuple,
typename... Settings>
1154 struct are_settings_from_tuple
1155 : if_else<conjuction<is_setting_from_tuple<Settings, Tuple>...>::value>::type {};
1157 template <ProgressBarOption Id>
struct always_true {
static constexpr
auto value =
true; };
1159 template <ProgressBarOption Id,
typename Default> Default &&get_impl(Default &&def) {
1160 return std::forward<Default>(def);
1163 template <ProgressBarOption Id,
typename Default,
typename T,
typename... Args>
1164 auto get_impl(Default && , T &&first, Args &&... ) ->
1165 typename std::enable_if<(std::decay<T>::type::id == Id),
1166 decltype(std::forward<T>(first))>::type {
1167 return std::forward<T>(first);
1170 template <ProgressBarOption Id,
typename Default,
typename T,
typename... Args>
1171 auto get_impl(Default &&def, T && , Args &&... tail) ->
1172 typename std::enable_if<(std::decay<T>::type::id != Id),
1173 decltype(get_impl<Id>(std::forward<Default>(def),
1174 std::forward<Args>(tail)...))>::type {
1175 return get_impl<Id>(std::forward<Default>(def), std::forward<Args>(tail)...);
1178 template <ProgressBarOption Id,
typename Default,
typename... Args,
1179 typename =
typename std::enable_if<are_settings<Args...>::value,
void>::type>
1180 auto get(Default &&def, Args &&... args)
1181 -> decltype(details::get_impl<Id>(std::forward<Default>(def), std::forward<Args>(args)...)) {
1182 return details::get_impl<Id>(std::forward<Default>(def), std::forward<Args>(args)...);
1185 template <ProgressBarOption Id>
using StringSetting = Setting<std::string, Id>;
1187 template <ProgressBarOption Id>
using IntegerSetting = Setting<std::size_t, Id>;
1189 template <ProgressBarOption Id>
using BooleanSetting = Setting<bool, Id>;
1191 template <ProgressBarOption Id,
typename Tuple, std::
size_t counter = 0>
struct option_idx;
1193 template <ProgressBarOption Id,
typename T,
typename... Settings, std::size_t counter>
1194 struct option_idx<Id, std::tuple<T, Settings...>, counter>
1195 : if_else_type<(Id == T::id), std::integral_constant<std::size_t, counter>,
1196 option_idx<Id, std::tuple<Settings...>, counter + 1>>::type {};
1198 template <ProgressBarOption Id, std::
size_t counter>
struct option_idx<Id, std::tuple<>, counter> {
1199 static_assert(always_true<(ProgressBarOption)Id>::value,
"No such option was found");
1202 template <ProgressBarOption Id,
typename Settings>
1203 auto get_value(Settings &&settings)
1204 -> decltype((std::get<option_idx<Id,
typename std::decay<Settings>::type>::value>(
1205 std::declval<Settings &&>()))) {
1206 return std::get<option_idx<Id, typename std::decay<Settings>::type>::value>(
1207 std::forward<Settings>(settings));
1213 using BarWidth = details::IntegerSetting<details::ProgressBarOption::bar_width>;
1214 using PrefixText = details::StringSetting<details::ProgressBarOption::prefix_text>;
1215 using PostfixText = details::StringSetting<details::ProgressBarOption::postfix_text>;
1216 using Start = details::StringSetting<details::ProgressBarOption::start>;
1217 using End = details::StringSetting<details::ProgressBarOption::end>;
1218 using Fill = details::StringSetting<details::ProgressBarOption::fill>;
1219 using Lead = details::StringSetting<details::ProgressBarOption::lead>;
1220 using Remainder = details::StringSetting<details::ProgressBarOption::remainder>;
1221 using MaxPostfixTextLen = details::IntegerSetting<details::ProgressBarOption::max_postfix_text_len>;
1222 using Completed = details::BooleanSetting<details::ProgressBarOption::completed>;
1223 using ShowPercentage = details::BooleanSetting<details::ProgressBarOption::show_percentage>;
1224 using ShowElapsedTime = details::BooleanSetting<details::ProgressBarOption::show_elapsed_time>;
1225 using ShowRemainingTime = details::BooleanSetting<details::ProgressBarOption::show_remaining_time>;
1226 using SavedStartTime = details::BooleanSetting<details::ProgressBarOption::saved_start_time>;
1227 using ForegroundColor = details::Setting<Color, details::ProgressBarOption::foreground_color>;
1228 using ShowSpinner = details::BooleanSetting<details::ProgressBarOption::spinner_show>;
1229 using SpinnerStates =
1230 details::Setting<std::vector<std::string>, details::ProgressBarOption::spinner_states>;
1231 using HideBarWhenComplete =
1232 details::BooleanSetting<details::ProgressBarOption::hide_bar_when_complete>;
1234 details::Setting<std::vector<FontStyle>, details::ProgressBarOption::font_styles>;
1235 using MinProgress = details::IntegerSetting<details::ProgressBarOption::min_progress>;
1236 using MaxProgress = details::IntegerSetting<details::ProgressBarOption::max_progress>;
1237 using ProgressType = details::Setting<ProgressType, details::ProgressBarOption::progress_type>;
1238 using Stream = details::Setting<std::ostream &, details::ProgressBarOption::stream>;
1245 #ifndef INDICATORS_CURSOR_CONTROL
1246 #define INDICATORS_CURSOR_CONTROL
1248 #if defined(_MSC_VER)
1249 #if !defined(NOMINMAX)
1253 #include <windows.h>
1260 #if defined(_MSC_VER)
1262 static inline void show_console_cursor(
bool const show) {
1263 HANDLE
out = GetStdHandle(STD_OUTPUT_HANDLE);
1265 CONSOLE_CURSOR_INFO cursorInfo;
1267 GetConsoleCursorInfo(out, &cursorInfo);
1268 cursorInfo.bVisible = show;
1269 SetConsoleCursorInfo(out, &cursorInfo);
1272 static inline void erase_line() {
1273 auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
1277 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
1278 GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
1283 cursor.Y = csbiInfo.dwCursorPosition.Y;
1287 FillConsoleOutputCharacterA(hStdout,
' ', csbiInfo.dwSize.X, cursor, &count);
1289 FillConsoleOutputAttribute(hStdout, csbiInfo.wAttributes, csbiInfo.dwSize.X,
1292 SetConsoleCursorPosition(hStdout, cursor);
1297 static inline void show_console_cursor(
bool const show) {
1298 std::fputs(show ?
"\033[?25h" :
"\033[?25l", stdout);
1301 static inline void erase_line() {
1302 std::fputs(
"\r\033[K", stdout);
1312 #ifndef INDICATORS_CURSOR_MOVEMENT
1313 #define INDICATORS_CURSOR_MOVEMENT
1315 #if defined(_MSC_VER)
1316 #if !defined(NOMINMAX)
1320 #include <windows.h>
1329 static inline void move(
int x,
int y) {
1330 auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
1334 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
1335 GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
1339 cursor.X = csbiInfo.dwCursorPosition.X + x;
1340 cursor.Y = csbiInfo.dwCursorPosition.Y + y;
1341 SetConsoleCursorPosition(hStdout, cursor);
1344 static inline void move_up(
int lines) { move(0, -lines); }
1345 static inline void move_down(
int lines) { move(0, -lines); }
1346 static inline void move_right(
int cols) { move(cols, 0); }
1347 static inline void move_left(
int cols) { move(-cols, 0); }
1351 static inline void move_up(
int lines) { std::cout <<
"\033[" << lines <<
"A"; }
1352 static inline void move_down(
int lines) { std::cout <<
"\033[" << lines <<
"B"; }
1353 static inline void move_right(
int cols) { std::cout <<
"\033[" << cols <<
"C"; }
1354 static inline void move_left(
int cols) { std::cout <<
"\033[" << cols <<
"D"; }
1363 #ifndef INDICATORS_STREAM_HELPER
1364 #define INDICATORS_STREAM_HELPER
1367 #ifndef INDICATORS_DISPLAY_WIDTH
1368 #define INDICATORS_DISPLAY_WIDTH
1447 static inline int bisearch(
wchar_t ucs,
const struct interval *table,
int max) {
1451 if (ucs < table[0].first || ucs > table[max].last)
1453 while (max >= min) {
1454 mid = (min + max) / 2;
1455 if (ucs > table[mid].last)
1457 else if (ucs < table[mid].first)
1498 static inline int mk_wcwidth(
wchar_t ucs) {
1501 static const struct interval combining[] = {
1502 {0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489},
1503 {0x0591, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2},
1504 {0x05C4, 0x05C5}, {0x05C7, 0x05C7}, {0x0600, 0x0603},
1505 {0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670},
1506 {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED},
1507 {0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A},
1508 {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, {0x0901, 0x0902},
1509 {0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D},
1510 {0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981},
1511 {0x09BC, 0x09BC}, {0x09C1, 0x09C4}, {0x09CD, 0x09CD},
1512 {0x09E2, 0x09E3}, {0x0A01, 0x0A02}, {0x0A3C, 0x0A3C},
1513 {0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D},
1514 {0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC},
1515 {0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD},
1516 {0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, {0x0B3C, 0x0B3C},
1517 {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D},
1518 {0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0},
1519 {0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48},
1520 {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0CBC, 0x0CBC},
1521 {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD},
1522 {0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D},
1523 {0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6},
1524 {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E},
1525 {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC},
1526 {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35},
1527 {0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F71, 0x0F7E},
1528 {0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F90, 0x0F97},
1529 {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030},
1530 {0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039},
1531 {0x1058, 0x1059}, {0x1160, 0x11FF}, {0x135F, 0x135F},
1532 {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753},
1533 {0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD},
1534 {0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD},
1535 {0x180B, 0x180D}, {0x18A9, 0x18A9}, {0x1920, 0x1922},
1536 {0x1927, 0x1928}, {0x1932, 0x1932}, {0x1939, 0x193B},
1537 {0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34},
1538 {0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42},
1539 {0x1B6B, 0x1B73}, {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF},
1540 {0x200B, 0x200F}, {0x202A, 0x202E}, {0x2060, 0x2063},
1541 {0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F},
1542 {0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B},
1543 {0xA825, 0xA826}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F},
1544 {0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB},
1545 {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F},
1546 {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169},
1547 {0x1D173, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD},
1548 {0x1D242, 0x1D244}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F},
1549 {0xE0100, 0xE01EF}};
1554 if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
1558 if (bisearch(ucs, combining,
sizeof(combining) /
sizeof(
struct interval) - 1))
1566 ucs == 0x2329 || ucs == 0x232a ||
1567 (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) ||
1568 (ucs >= 0xac00 && ucs <= 0xd7a3) ||
1571 (ucs >= 0xfe10 && ucs <= 0xfe19) ||
1572 (ucs >= 0xfe30 && ucs <= 0xfe6f) ||
1573 (ucs >= 0xff00 && ucs <= 0xff60) ||
1574 (ucs >= 0xffe0 && ucs <= 0xffe6) ||
1575 (ucs >= 0x20000 && ucs <= 0x2fffd) ||
1576 (ucs >= 0x30000 && ucs <= 0x3fffd)));
1579 static inline int mk_wcswidth(
const wchar_t *pwcs,
size_t n) {
1582 for (; *pwcs && n-- > 0; pwcs++)
1583 if ((w = mk_wcwidth(*pwcs)) < 0)
1600 static inline int mk_wcwidth_cjk(
wchar_t ucs) {
1603 static const struct interval ambiguous[] = {
1604 {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8},
1605 {0x00AA, 0x00AA}, {0x00AE, 0x00AE}, {0x00B0, 0x00B4},
1606 {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6},
1607 {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1},
1608 {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED},
1609 {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA},
1610 {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101},
1611 {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B},
1612 {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133},
1613 {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144},
1614 {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153},
1615 {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE},
1616 {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4},
1617 {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA},
1618 {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261},
1619 {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB},
1620 {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB},
1621 {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0391, 0x03A1},
1622 {0x03A3, 0x03A9}, {0x03B1, 0x03C1}, {0x03C3, 0x03C9},
1623 {0x0401, 0x0401}, {0x0410, 0x044F}, {0x0451, 0x0451},
1624 {0x2010, 0x2010}, {0x2013, 0x2016}, {0x2018, 0x2019},
1625 {0x201C, 0x201D}, {0x2020, 0x2022}, {0x2024, 0x2027},
1626 {0x2030, 0x2030}, {0x2032, 0x2033}, {0x2035, 0x2035},
1627 {0x203B, 0x203B}, {0x203E, 0x203E}, {0x2074, 0x2074},
1628 {0x207F, 0x207F}, {0x2081, 0x2084}, {0x20AC, 0x20AC},
1629 {0x2103, 0x2103}, {0x2105, 0x2105}, {0x2109, 0x2109},
1630 {0x2113, 0x2113}, {0x2116, 0x2116}, {0x2121, 0x2122},
1631 {0x2126, 0x2126}, {0x212B, 0x212B}, {0x2153, 0x2154},
1632 {0x215B, 0x215E}, {0x2160, 0x216B}, {0x2170, 0x2179},
1633 {0x2190, 0x2199}, {0x21B8, 0x21B9}, {0x21D2, 0x21D2},
1634 {0x21D4, 0x21D4}, {0x21E7, 0x21E7}, {0x2200, 0x2200},
1635 {0x2202, 0x2203}, {0x2207, 0x2208}, {0x220B, 0x220B},
1636 {0x220F, 0x220F}, {0x2211, 0x2211}, {0x2215, 0x2215},
1637 {0x221A, 0x221A}, {0x221D, 0x2220}, {0x2223, 0x2223},
1638 {0x2225, 0x2225}, {0x2227, 0x222C}, {0x222E, 0x222E},
1639 {0x2234, 0x2237}, {0x223C, 0x223D}, {0x2248, 0x2248},
1640 {0x224C, 0x224C}, {0x2252, 0x2252}, {0x2260, 0x2261},
1641 {0x2264, 0x2267}, {0x226A, 0x226B}, {0x226E, 0x226F},
1642 {0x2282, 0x2283}, {0x2286, 0x2287}, {0x2295, 0x2295},
1643 {0x2299, 0x2299}, {0x22A5, 0x22A5}, {0x22BF, 0x22BF},
1644 {0x2312, 0x2312}, {0x2460, 0x24E9}, {0x24EB, 0x254B},
1645 {0x2550, 0x2573}, {0x2580, 0x258F}, {0x2592, 0x2595},
1646 {0x25A0, 0x25A1}, {0x25A3, 0x25A9}, {0x25B2, 0x25B3},
1647 {0x25B6, 0x25B7}, {0x25BC, 0x25BD}, {0x25C0, 0x25C1},
1648 {0x25C6, 0x25C8}, {0x25CB, 0x25CB}, {0x25CE, 0x25D1},
1649 {0x25E2, 0x25E5}, {0x25EF, 0x25EF}, {0x2605, 0x2606},
1650 {0x2609, 0x2609}, {0x260E, 0x260F}, {0x2614, 0x2615},
1651 {0x261C, 0x261C}, {0x261E, 0x261E}, {0x2640, 0x2640},
1652 {0x2642, 0x2642}, {0x2660, 0x2661}, {0x2663, 0x2665},
1653 {0x2667, 0x266A}, {0x266C, 0x266D}, {0x266F, 0x266F},
1654 {0x273D, 0x273D}, {0x2776, 0x277F}, {0xE000, 0xF8FF},
1655 {0xFFFD, 0xFFFD}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}};
1658 if (bisearch(ucs, ambiguous,
sizeof(ambiguous) /
sizeof(
struct interval) - 1))
1661 return mk_wcwidth(ucs);
1664 static inline int mk_wcswidth_cjk(
const wchar_t *pwcs,
size_t n) {
1667 for (; *pwcs && n-- > 0; pwcs++)
1668 if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
1678 static inline std::wstring utf8_decode(
const std::string& s) {
1679 std::string curLocale = setlocale(LC_ALL,
"");
1680 const char* _Source = s.c_str();
1681 size_t _Dsize = std::strlen(_Source) + 1;
1682 wchar_t* _Dest =
new wchar_t[_Dsize];
1684 mbstowcs_s(&_Osize, _Dest, _Dsize, _Source, _Dsize);
1685 std::wstring result = _Dest;
1687 setlocale(LC_ALL, curLocale.c_str());
1691 static inline std::wstring utf8_decode(
const std::string& s) {
1692 std::string curLocale = setlocale(LC_ALL,
"");
1693 const char* _Source = s.c_str();
1694 size_t _Dsize = mbstowcs(NULL, _Source, 0) + 1;
1695 wchar_t* _Dest =
new wchar_t[_Dsize];
1696 wmemset(_Dest, 0, _Dsize);
1697 mbstowcs(_Dest, _Source, _Dsize);
1698 std::wstring result = _Dest;
1700 setlocale(LC_ALL, curLocale.c_str());
1707 static inline int display_width(
const std::string &input) {
1708 using namespace unicode::details;
1709 return mk_wcswidth(utf8_decode(input).c_str(), input.size());
1712 static inline int display_width(
const std::wstring &input) {
1713 return details::mk_wcswidth(input.c_str(), input.size());
1722 #include <algorithm>
1735 inline void set_stream_color(std::ostream &os, Color color) {
1738 os << termcolor::grey;
1741 os << termcolor::red;
1744 os << termcolor::green;
1747 os << termcolor::yellow;
1750 os << termcolor::blue;
1752 case Color::magenta:
1753 os << termcolor::magenta;
1756 os << termcolor::cyan;
1759 os << termcolor::white;
1766 inline void set_font_style(std::ostream &os, FontStyle style) {
1768 case FontStyle::bold:
1769 os << termcolor::bold;
1771 case FontStyle::dark:
1772 os << termcolor::dark;
1774 case FontStyle::italic:
1775 os << termcolor::italic;
1777 case FontStyle::underline:
1778 os << termcolor::underline;
1780 case FontStyle::blink:
1781 os << termcolor::blink;
1783 case FontStyle::reverse:
1784 os << termcolor::reverse;
1786 case FontStyle::concealed:
1787 os << termcolor::concealed;
1789 case FontStyle::crossed:
1790 os << termcolor::crossed;
1797 inline std::ostream &write_duration(std::ostream &os, std::chrono::nanoseconds ns) {
1798 using namespace std;
1799 using namespace std::chrono;
1800 using days = duration<int, ratio<86400>>;
1801 char fill = os.fill();
1803 auto d = duration_cast<days>(ns);
1805 auto h = duration_cast<hours>(ns);
1807 auto m = duration_cast<minutes>(ns);
1809 auto s = duration_cast<seconds>(ns);
1811 os << setw(2) << d.count() <<
"d:";
1813 os << setw(2) << h.count() <<
"h:";
1814 os << setw(2) << m.count() <<
"m:" << setw(2) << s.count() <<
's';
1819 class BlockProgressScaleWriter {
1821 BlockProgressScaleWriter(std::ostream &os,
size_t bar_width) : os(os), bar_width(bar_width) {}
1823 std::ostream &write(
float progress) {
1824 std::string fill_text{
"█"};
1825 std::vector<std::string> lead_characters{
" ",
"▏",
"▎",
"▍",
"▌",
"▋",
"▊",
"▉"};
1826 auto value = (std::min)(1.0f, (std::max)(0.0f, progress / 100.0f));
1827 auto whole_width = std::floor(value * bar_width);
1828 auto remainder_width = fmod((value * bar_width), 1.0f);
1829 auto part_width = std::floor(remainder_width * lead_characters.size());
1830 std::string lead_text = lead_characters[size_t(part_width)];
1831 if ((bar_width - whole_width - 1) < 0)
1833 for (
size_t i = 0; i < whole_width; ++i)
1836 for (
size_t i = 0; i < (bar_width - whole_width - 1); ++i)
1843 size_t bar_width = 0;
1846 class ProgressScaleWriter {
1848 ProgressScaleWriter(std::ostream &os,
size_t bar_width,
const std::string &fill,
1849 const std::string &lead,
const std::string &remainder)
1850 : os(os), bar_width(bar_width), fill(fill), lead(lead), remainder(remainder) {}
1852 std::ostream &write(
float progress) {
1853 auto pos =
static_cast<size_t>(progress * bar_width / 100.0);
1854 for (
size_t i = 0, current_display_width = 0; i < bar_width;) {
1859 current_display_width = unicode::display_width(fill);
1860 }
else if (i == pos) {
1862 current_display_width = unicode::display_width(lead);
1865 current_display_width = unicode::display_width(remainder);
1868 i += current_display_width;
1870 if (i > bar_width) {
1873 os << std::string((bar_width - (i - current_display_width)),
' ');
1884 size_t bar_width = 0;
1887 std::string remainder;
1890 class IndeterminateProgressScaleWriter {
1892 IndeterminateProgressScaleWriter(std::ostream &os,
size_t bar_width,
const std::string &fill,
1893 const std::string &lead)
1894 : os(os), bar_width(bar_width), fill(fill), lead(lead) {}
1896 std::ostream &write(
size_t progress) {
1897 for (
size_t i = 0; i < bar_width;) {
1899 size_t current_display_width = 0;
1903 current_display_width = unicode::display_width(fill);
1904 }
else if (i == progress) {
1906 current_display_width = unicode::display_width(lead);
1909 current_display_width = unicode::display_width(fill);
1912 i += current_display_width;
1914 if (i > bar_width) {
1917 os << std::string((bar_width - (i - current_display_width)),
' ');
1928 size_t bar_width = 0;
1939 #ifndef INDICATORS_PROGRESS_BAR
1940 #define INDICATORS_PROGRESS_BAR
1944 #include <algorithm>
1958 #include <type_traits>
1965 std::tuple<option::BarWidth, option::PrefixText, option::PostfixText,
1966 option::Start, option::End, option::Fill, option::Lead,
1967 option::Remainder, option::MaxPostfixTextLen,
1968 option::Completed, option::ShowPercentage,
1969 option::ShowElapsedTime, option::ShowRemainingTime,
1970 option::SavedStartTime, option::ForegroundColor,
1971 option::FontStyles, option::MinProgress, option::MaxProgress,
1972 option::ProgressType, option::Stream>;
1975 template <
typename... Args,
1976 typename std::enable_if<
1977 details::are_settings_from_tuple<
1978 Settings,
typename std::decay<Args>::type...>::value,
1979 void *>::type =
nullptr>
1980 explicit ProgressBar(Args &&... args)
1982 details::get<details::ProgressBarOption::bar_width>(
1983 option::BarWidth{100}, std::forward<Args>(args)...),
1984 details::get<details::ProgressBarOption::prefix_text>(
1985 option::PrefixText{}, std::forward<Args>(args)...),
1986 details::get<details::ProgressBarOption::postfix_text>(
1987 option::PostfixText{}, std::forward<Args>(args)...),
1988 details::get<details::ProgressBarOption::start>(
1989 option::Start{
"["}, std::forward<Args>(args)...),
1990 details::get<details::ProgressBarOption::end>(
1991 option::End{
"]"}, std::forward<Args>(args)...),
1992 details::get<details::ProgressBarOption::fill>(
1993 option::Fill{
"="}, std::forward<Args>(args)...),
1994 details::get<details::ProgressBarOption::lead>(
1995 option::Lead{
">"}, std::forward<Args>(args)...),
1996 details::get<details::ProgressBarOption::remainder>(
1997 option::Remainder{
" "}, std::forward<Args>(args)...),
1998 details::get<details::ProgressBarOption::max_postfix_text_len>(
1999 option::MaxPostfixTextLen{0}, std::forward<Args>(args)...),
2000 details::get<details::ProgressBarOption::completed>(
2001 option::Completed{false}, std::forward<Args>(args)...),
2002 details::get<details::ProgressBarOption::show_percentage>(
2003 option::ShowPercentage{false}, std::forward<Args>(args)...),
2004 details::get<details::ProgressBarOption::show_elapsed_time>(
2005 option::ShowElapsedTime{false}, std::forward<Args>(args)...),
2006 details::get<details::ProgressBarOption::show_remaining_time>(
2007 option::ShowRemainingTime{false}, std::forward<Args>(args)...),
2008 details::get<details::ProgressBarOption::saved_start_time>(
2009 option::SavedStartTime{false}, std::forward<Args>(args)...),
2010 details::get<details::ProgressBarOption::foreground_color>(
2012 std::forward<Args>(args)...),
2013 details::get<details::ProgressBarOption::font_styles>(
2014 option::FontStyles{std::vector<
FontStyle>{}},
2015 std::forward<Args>(args)...),
2016 details::get<details::ProgressBarOption::min_progress>(
2017 option::MinProgress{0}, std::forward<Args>(args)...),
2018 details::get<details::ProgressBarOption::max_progress>(
2019 option::MaxProgress{100}, std::forward<Args>(args)...),
2020 details::get<details::ProgressBarOption::progress_type>(
2021 option::ProgressType{ProgressType::incremental},
2022 std::forward<Args>(args)...),
2023 details::get<details::ProgressBarOption::stream>(
2024 option::Stream{std::cout}, std::forward<Args>(args)...)) {
2028 const auto type = get_value<details::ProgressBarOption::progress_type>();
2029 if (type == ProgressType::incremental)
2030 progress_ = get_value<details::ProgressBarOption::min_progress>();
2032 progress_ = get_value<details::ProgressBarOption::max_progress>();
2035 template <
typename T, details::ProgressBarOption
id>
2036 void set_option(details::Setting<T, id> &&setting) {
2038 !std::is_same<T,
typename std::decay<decltype(details::get_value<id>(
2039 std::declval<Settings>()))>::type>::value,
2040 "Setting has wrong type!");
2041 std::lock_guard<std::mutex> lock(mutex_);
2042 get_value<id>() = std::move(setting).value;
2045 template <
typename T, details::ProgressBarOption
id>
2046 void set_option(
const details::Setting<T, id> &setting) {
2048 !std::is_same<T,
typename std::decay<decltype(details::get_value<id>(
2049 std::declval<Settings>()))>::type>::value,
2050 "Setting has wrong type!");
2051 std::lock_guard<std::mutex> lock(mutex_);
2052 get_value<id>() = setting.value;
2056 set_option(
const details::Setting<
2057 std::string, details::ProgressBarOption::postfix_text> &setting) {
2058 std::lock_guard<std::mutex> lock(mutex_);
2059 get_value<details::ProgressBarOption::postfix_text>() = setting.value;
2060 if (setting.value.length() >
2061 get_value<details::ProgressBarOption::max_postfix_text_len>()) {
2062 get_value<details::ProgressBarOption::max_postfix_text_len>() =
2063 setting.value.length();
2068 details::Setting<std::string, details::ProgressBarOption::postfix_text>
2070 std::lock_guard<std::mutex> lock(mutex_);
2071 get_value<details::ProgressBarOption::postfix_text>() =
2072 std::move(setting).value;
2073 auto &new_value = get_value<details::ProgressBarOption::postfix_text>();
2074 if (new_value.length() >
2075 get_value<details::ProgressBarOption::max_postfix_text_len>()) {
2076 get_value<details::ProgressBarOption::max_postfix_text_len>() =
2081 void set_progress(
size_t new_progress) {
2083 std::lock_guard<std::mutex> lock(mutex_);
2084 progress_ = new_progress;
2093 std::lock_guard<std::mutex> lock{mutex_};
2094 const auto type = get_value<details::ProgressBarOption::progress_type>();
2095 if (type == ProgressType::incremental)
2105 std::lock_guard<std::mutex> lock{mutex_};
2108 size_t(get_value<details::ProgressBarOption::max_progress>()));
2111 bool is_completed()
const {
2112 return get_value<details::ProgressBarOption::completed>();
2115 void mark_as_completed() {
2116 get_value<details::ProgressBarOption::completed>() =
true;
2121 template <details::ProgressBarOption
id>
2123 -> decltype((details::get_value<id>(std::declval<Settings &>()).value)) {
2124 return details::get_value<id>(settings_).value;
2127 template <details::ProgressBarOption
id>
2128 auto get_value() const -> decltype(
2129 (details::get_value<
id>(std::declval<const Settings &>()).value)) {
2130 return details::get_value<id>(settings_).value;
2133 size_t progress_{0};
2135 std::chrono::nanoseconds elapsed_;
2136 std::chrono::time_point<std::chrono::high_resolution_clock> start_time_point_;
2139 template <
typename Indicator,
size_t count>
friend class MultiProgress;
2140 template <
typename Indicator>
friend class DynamicProgress;
2141 std::atomic<bool> multi_progress_mode_{
false};
2143 void save_start_time() {
2144 auto &show_elapsed_time =
2145 get_value<details::ProgressBarOption::show_elapsed_time>();
2146 auto &saved_start_time =
2147 get_value<details::ProgressBarOption::saved_start_time>();
2148 auto &show_remaining_time =
2149 get_value<details::ProgressBarOption::show_remaining_time>();
2150 if ((show_elapsed_time || show_remaining_time) && !saved_start_time) {
2151 start_time_point_ = std::chrono::high_resolution_clock::now();
2152 saved_start_time =
true;
2156 std::pair<std::string, int> get_prefix_text() {
2157 std::stringstream os;
2158 os << get_value<details::ProgressBarOption::prefix_text>();
2159 const auto result = os.str();
2160 const auto result_size = unicode::display_width(result);
2161 return {result, result_size};
2164 std::pair<std::string, int> get_postfix_text() {
2165 std::stringstream os;
2166 const auto max_progress =
2167 get_value<details::ProgressBarOption::max_progress>();
2169 if (get_value<details::ProgressBarOption::show_percentage>()) {
2171 << (std::min)(
static_cast<size_t>(
static_cast<float>(progress_) /
2172 max_progress * 100),
2177 auto &saved_start_time =
2178 get_value<details::ProgressBarOption::saved_start_time>();
2180 if (get_value<details::ProgressBarOption::show_elapsed_time>()) {
2182 if (saved_start_time)
2183 details::write_duration(os, elapsed_);
2188 if (get_value<details::ProgressBarOption::show_remaining_time>()) {
2189 if (get_value<details::ProgressBarOption::show_elapsed_time>())
2194 if (saved_start_time) {
2195 auto eta = std::chrono::nanoseconds(
2197 ?
static_cast<long long>(std::ceil(
float(elapsed_.count()) *
2198 max_progress / progress_))
2200 auto remaining = eta > elapsed_ ? (eta - elapsed_) : (elapsed_ - eta);
2201 details::write_duration(os, remaining);
2208 if (get_value<details::ProgressBarOption::show_elapsed_time>())
2212 os <<
" " << get_value<details::ProgressBarOption::postfix_text>();
2214 const auto result = os.str();
2215 const auto result_size = unicode::display_width(result);
2216 return {result, result_size};
2220 void print_progress(
bool from_multi_progress =
false) {
2221 std::lock_guard<std::mutex> lock{mutex_};
2223 auto &os = get_value<details::ProgressBarOption::stream>();
2225 const auto type = get_value<details::ProgressBarOption::progress_type>();
2226 const auto min_progress =
2227 get_value<details::ProgressBarOption::min_progress>();
2228 const auto max_progress =
2229 get_value<details::ProgressBarOption::max_progress>();
2230 if (multi_progress_mode_ && !from_multi_progress) {
2231 if ((type == ProgressType::incremental && progress_ >= max_progress) ||
2232 (type == ProgressType::decremental && progress_ <= min_progress)) {
2233 get_value<details::ProgressBarOption::completed>() =
true;
2237 auto now = std::chrono::high_resolution_clock::now();
2238 if (!get_value<details::ProgressBarOption::completed>())
2239 elapsed_ = std::chrono::duration_cast<std::chrono::nanoseconds>(
2240 now - start_time_point_);
2242 if (get_value<details::ProgressBarOption::foreground_color>() !=
2244 details::set_stream_color(
2245 os, get_value<details::ProgressBarOption::foreground_color>());
2247 for (
auto &style : get_value<details::ProgressBarOption::font_styles>())
2248 details::set_font_style(os, style);
2250 const auto prefix_pair = get_prefix_text();
2251 const auto prefix_text = prefix_pair.first;
2252 const auto prefix_length = prefix_pair.second;
2253 os <<
"\r" << prefix_text;
2255 os << get_value<details::ProgressBarOption::start>();
2257 details::ProgressScaleWriter writer{
2258 os, get_value<details::ProgressBarOption::bar_width>(),
2259 get_value<details::ProgressBarOption::fill>(),
2260 get_value<details::ProgressBarOption::lead>(),
2261 get_value<details::ProgressBarOption::remainder>()};
2262 writer.write(
double(progress_) /
double(max_progress) * 100.0f);
2264 os << get_value<details::ProgressBarOption::end>();
2266 const auto postfix_pair = get_postfix_text();
2267 const auto postfix_text = postfix_pair.first;
2268 const auto postfix_length = postfix_pair.second;
2272 const auto start_length = get_value<details::ProgressBarOption::start>().size();
2273 const auto bar_width = get_value<details::ProgressBarOption::bar_width>();
2274 const auto end_length = get_value<details::ProgressBarOption::end>().size();
2275 const auto terminal_width = terminal_size().second;
2277 const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length);
2278 if (prefix_length == -1 || postfix_length == -1) {
2280 }
else if (remaining > 0) {
2281 os << std::string(remaining,
' ') <<
"\r";
2282 }
else if (remaining < 0) {
2287 if ((type == ProgressType::incremental && progress_ >= max_progress) ||
2288 (type == ProgressType::decremental && progress_ <= min_progress)) {
2289 get_value<details::ProgressBarOption::completed>() =
true;
2291 if (get_value<details::ProgressBarOption::completed>() &&
2292 !from_multi_progress)
2293 os << termcolor::reset << std::endl;
2302 #ifndef INDICATORS_BLOCK_PROGRESS_BAR
2303 #define INDICATORS_BLOCK_PROGRESS_BAR
2308 #include <algorithm>
2324 class BlockProgressBar {
2325 using Settings = std::tuple<option::ForegroundColor, option::BarWidth, option::Start, option::End,
2326 option::PrefixText, option::PostfixText, option::ShowPercentage,
2327 option::ShowElapsedTime, option::ShowRemainingTime, option::Completed,
2328 option::SavedStartTime, option::MaxPostfixTextLen, option::FontStyles,
2329 option::MaxProgress, option::Stream>;
2332 template <
typename... Args,
2333 typename std::enable_if<details::are_settings_from_tuple<
2334 Settings,
typename std::decay<Args>::type...>::value,
2335 void *>::type =
nullptr>
2336 explicit BlockProgressBar(Args &&... args)
2337 : settings_(details::get<details::ProgressBarOption::foreground_color>(
2339 details::get<details::ProgressBarOption::bar_width>(option::BarWidth{100},
2340 std::forward<Args>(args)...),
2341 details::get<details::ProgressBarOption::start>(option::Start{
"["},
2342 std::forward<Args>(args)...),
2343 details::get<details::ProgressBarOption::end>(option::End{
"]"},
2344 std::forward<Args>(args)...),
2345 details::get<details::ProgressBarOption::prefix_text>(
2346 option::PrefixText{
""}, std::forward<Args>(args)...),
2347 details::get<details::ProgressBarOption::postfix_text>(
2348 option::PostfixText{
""}, std::forward<Args>(args)...),
2349 details::get<details::ProgressBarOption::show_percentage>(
2350 option::ShowPercentage{true}, std::forward<Args>(args)...),
2351 details::get<details::ProgressBarOption::show_elapsed_time>(
2352 option::ShowElapsedTime{false}, std::forward<Args>(args)...),
2353 details::get<details::ProgressBarOption::show_remaining_time>(
2354 option::ShowRemainingTime{false}, std::forward<Args>(args)...),
2355 details::get<details::ProgressBarOption::completed>(option::Completed{false},
2356 std::forward<Args>(args)...),
2357 details::get<details::ProgressBarOption::saved_start_time>(
2358 option::SavedStartTime{false}, std::forward<Args>(args)...),
2359 details::get<details::ProgressBarOption::max_postfix_text_len>(
2360 option::MaxPostfixTextLen{0}, std::forward<Args>(args)...),
2361 details::get<details::ProgressBarOption::font_styles>(
2362 option::FontStyles{std::vector<
FontStyle>{}}, std::forward<Args>(args)...),
2363 details::get<details::ProgressBarOption::max_progress>(
2364 option::MaxProgress{100}, std::forward<Args>(args)...),
2365 details::get<details::ProgressBarOption::stream>(option::Stream{std::cout},
2366 std::forward<Args>(args)...)) {}
2368 template <
typename T, details::ProgressBarOption
id>
2369 void set_option(details::Setting<T, id> &&setting) {
2370 static_assert(!std::is_same<T,
typename std::decay<decltype(details::get_value<id>(
2371 std::declval<Settings>()))>::type>::value,
2372 "Setting has wrong type!");
2373 std::lock_guard<std::mutex> lock(mutex_);
2374 get_value<id>() = std::move(setting).value;
2377 template <
typename T, details::ProgressBarOption
id>
2378 void set_option(
const details::Setting<T, id> &setting) {
2379 static_assert(!std::is_same<T,
typename std::decay<decltype(details::get_value<id>(
2380 std::declval<Settings>()))>::type>::value,
2381 "Setting has wrong type!");
2382 std::lock_guard<std::mutex> lock(mutex_);
2383 get_value<id>() = setting.value;
2387 const details::Setting<std::string, details::ProgressBarOption::postfix_text> &setting) {
2388 std::lock_guard<std::mutex> lock(mutex_);
2389 get_value<details::ProgressBarOption::postfix_text>() = setting.value;
2390 if (setting.value.length() > get_value<details::ProgressBarOption::max_postfix_text_len>()) {
2391 get_value<details::ProgressBarOption::max_postfix_text_len>() = setting.value.length();
2396 set_option(details::Setting<std::string, details::ProgressBarOption::postfix_text> &&setting) {
2397 std::lock_guard<std::mutex> lock(mutex_);
2398 get_value<details::ProgressBarOption::postfix_text>() = std::move(setting).value;
2399 auto &new_value = get_value<details::ProgressBarOption::postfix_text>();
2400 if (new_value.length() > get_value<details::ProgressBarOption::max_postfix_text_len>()) {
2401 get_value<details::ProgressBarOption::max_postfix_text_len>() = new_value.length();
2405 void set_progress(
float value) {
2407 std::lock_guard<std::mutex> lock{mutex_};
2416 std::lock_guard<std::mutex> lock{mutex_};
2424 std::lock_guard<std::mutex> lock{mutex_};
2425 return (std::min)(
static_cast<size_t>(progress_),
2426 size_t(get_value<details::ProgressBarOption::max_progress>()));
2429 bool is_completed()
const {
return get_value<details::ProgressBarOption::completed>(); }
2431 void mark_as_completed() {
2432 get_value<details::ProgressBarOption::completed>() =
true;
2437 template <details::ProgressBarOption
id>
2438 auto get_value() -> decltype((details::get_value<id>(std::declval<Settings &>()).value)) {
2439 return details::get_value<id>(settings_).value;
2442 template <details::ProgressBarOption
id>
2443 auto get_value() const
2444 -> decltype((details::get_value<
id>(std::declval<const Settings &>()).value)) {
2445 return details::get_value<id>(settings_).value;
2449 float progress_{0.0};
2450 std::chrono::time_point<std::chrono::high_resolution_clock> start_time_point_;
2453 template <
typename Indicator,
size_t count>
friend class MultiProgress;
2454 template <
typename Indicator>
friend class DynamicProgress;
2455 std::atomic<bool> multi_progress_mode_{
false};
2457 void save_start_time() {
2458 auto &show_elapsed_time = get_value<details::ProgressBarOption::show_elapsed_time>();
2459 auto &saved_start_time = get_value<details::ProgressBarOption::saved_start_time>();
2460 auto &show_remaining_time = get_value<details::ProgressBarOption::show_remaining_time>();
2461 if ((show_elapsed_time || show_remaining_time) && !saved_start_time) {
2462 start_time_point_ = std::chrono::high_resolution_clock::now();
2463 saved_start_time =
true;
2467 std::pair<std::string, int> get_prefix_text() {
2468 std::stringstream os;
2469 os << get_value<details::ProgressBarOption::prefix_text>();
2470 const auto result = os.str();
2471 const auto result_size = unicode::display_width(result);
2472 return {result, result_size};
2475 std::pair<std::string, int> get_postfix_text() {
2476 std::stringstream os;
2477 const auto max_progress = get_value<details::ProgressBarOption::max_progress>();
2478 auto now = std::chrono::high_resolution_clock::now();
2479 auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(now - start_time_point_);
2481 if (get_value<details::ProgressBarOption::show_percentage>()) {
2482 os <<
" " << (std::min)(
static_cast<size_t>(progress_ / max_progress * 100.0), size_t(100))
2486 auto &saved_start_time = get_value<details::ProgressBarOption::saved_start_time>();
2488 if (get_value<details::ProgressBarOption::show_elapsed_time>()) {
2490 if (saved_start_time)
2491 details::write_duration(os, elapsed);
2496 if (get_value<details::ProgressBarOption::show_remaining_time>()) {
2497 if (get_value<details::ProgressBarOption::show_elapsed_time>())
2502 if (saved_start_time) {
2503 auto eta = std::chrono::nanoseconds(
2505 ?
static_cast<long long>(std::ceil(
float(elapsed.count()) *
2506 max_progress / progress_))
2508 auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
2509 details::write_duration(os, remaining);
2516 if (get_value<details::ProgressBarOption::show_elapsed_time>())
2520 os <<
" " << get_value<details::ProgressBarOption::postfix_text>();
2522 const auto result = os.str();
2523 const auto result_size = unicode::display_width(result);
2524 return {result, result_size};
2528 void print_progress(
bool from_multi_progress =
false) {
2529 std::lock_guard<std::mutex> lock{mutex_};
2531 auto &os = get_value<details::ProgressBarOption::stream>();
2533 const auto max_progress = get_value<details::ProgressBarOption::max_progress>();
2534 if (multi_progress_mode_ && !from_multi_progress) {
2535 if (progress_ > max_progress) {
2536 get_value<details::ProgressBarOption::completed>() =
true;
2541 if (get_value<details::ProgressBarOption::foreground_color>() != Color::unspecified)
2542 details::set_stream_color(os, get_value<details::ProgressBarOption::foreground_color>());
2544 for (
auto &style : get_value<details::ProgressBarOption::font_styles>())
2545 details::set_font_style(os, style);
2547 const auto prefix_pair = get_prefix_text();
2548 const auto prefix_text = prefix_pair.first;
2549 const auto prefix_length = prefix_pair.second;
2550 os <<
"\r" << prefix_text;
2552 os << get_value<details::ProgressBarOption::start>();
2554 details::BlockProgressScaleWriter writer{os,
2555 get_value<details::ProgressBarOption::bar_width>()};
2556 writer.write(progress_ / max_progress * 100);
2558 os << get_value<details::ProgressBarOption::end>();
2560 const auto postfix_pair = get_postfix_text();
2561 const auto postfix_text = postfix_pair.first;
2562 const auto postfix_length = postfix_pair.second;
2566 const auto start_length = get_value<details::ProgressBarOption::start>().size();
2567 const auto bar_width = get_value<details::ProgressBarOption::bar_width>();
2568 const auto end_length = get_value<details::ProgressBarOption::end>().size();
2569 const auto terminal_width = terminal_size().second;
2571 const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length);
2572 if (prefix_length == -1 || postfix_length == -1) {
2574 }
else if (remaining > 0) {
2575 os << std::string(remaining,
' ') <<
"\r";
2576 }
else if (remaining < 0) {
2581 if (progress_ > max_progress) {
2582 get_value<details::ProgressBarOption::completed>() =
true;
2584 if (get_value<details::ProgressBarOption::completed>() &&
2585 !from_multi_progress)
2586 os << termcolor::reset << std::endl;
2595 #ifndef INDICATORS_INDETERMINATE_PROGRESS_BAR
2596 #define INDICATORS_INDETERMINATE_PROGRESS_BAR
2600 #include <algorithm>
2613 #include <type_traits>
2619 class IndeterminateProgressBar {
2621 std::tuple<option::BarWidth, option::PrefixText, option::PostfixText, option::Start,
2622 option::End, option::Fill, option::Lead, option::MaxPostfixTextLen,
2623 option::Completed, option::ForegroundColor, option::FontStyles, option::Stream>;
2625 enum class Direction { forward, backward };
2627 Direction direction_{Direction::forward};
2630 template <
typename... Args,
2631 typename std::enable_if<details::are_settings_from_tuple<
2632 Settings,
typename std::decay<Args>::type...>::value,
2633 void *>::type =
nullptr>
2634 explicit IndeterminateProgressBar(Args &&... args)
2635 : settings_(details::get<details::ProgressBarOption::bar_width>(option::BarWidth{100},
2636 std::forward<Args>(args)...),
2637 details::get<details::ProgressBarOption::prefix_text>(
2638 option::PrefixText{}, std::forward<Args>(args)...),
2639 details::get<details::ProgressBarOption::postfix_text>(
2640 option::PostfixText{}, std::forward<Args>(args)...),
2641 details::get<details::ProgressBarOption::start>(option::Start{
"["},
2642 std::forward<Args>(args)...),
2643 details::get<details::ProgressBarOption::end>(option::End{
"]"},
2644 std::forward<Args>(args)...),
2645 details::get<details::ProgressBarOption::fill>(option::Fill{
"."},
2646 std::forward<Args>(args)...),
2647 details::get<details::ProgressBarOption::lead>(option::Lead{
"<==>"},
2648 std::forward<Args>(args)...),
2649 details::get<details::ProgressBarOption::max_postfix_text_len>(
2650 option::MaxPostfixTextLen{0}, std::forward<Args>(args)...),
2651 details::get<details::ProgressBarOption::completed>(option::Completed{false},
2652 std::forward<Args>(args)...),
2653 details::get<details::ProgressBarOption::foreground_color>(
2655 details::get<details::ProgressBarOption::font_styles>(
2656 option::FontStyles{std::vector<
FontStyle>{}}, std::forward<Args>(args)...),
2657 details::get<details::ProgressBarOption::stream>(option::Stream{std::cout},
2658 std::forward<Args>(args)...)) {
2667 max_progress_ = get_value<details::ProgressBarOption::bar_width>() -
2668 get_value<details::ProgressBarOption::lead>().size() +
2669 get_value<details::ProgressBarOption::start>().size() +
2670 get_value<details::ProgressBarOption::end>().size();
2673 template <
typename T, details::ProgressBarOption
id>
2674 void set_option(details::Setting<T, id> &&setting) {
2675 static_assert(!std::is_same<T,
typename std::decay<decltype(details::get_value<id>(
2676 std::declval<Settings>()))>::type>::value,
2677 "Setting has wrong type!");
2678 std::lock_guard<std::mutex> lock(mutex_);
2679 get_value<id>() = std::move(setting).value;
2682 template <
typename T, details::ProgressBarOption
id>
2683 void set_option(
const details::Setting<T, id> &setting) {
2684 static_assert(!std::is_same<T,
typename std::decay<decltype(details::get_value<id>(
2685 std::declval<Settings>()))>::type>::value,
2686 "Setting has wrong type!");
2687 std::lock_guard<std::mutex> lock(mutex_);
2688 get_value<id>() = setting.value;
2692 const details::Setting<std::string, details::ProgressBarOption::postfix_text> &setting) {
2693 std::lock_guard<std::mutex> lock(mutex_);
2694 get_value<details::ProgressBarOption::postfix_text>() = setting.value;
2695 if (setting.value.length() > get_value<details::ProgressBarOption::max_postfix_text_len>()) {
2696 get_value<details::ProgressBarOption::max_postfix_text_len>() = setting.value.length();
2701 set_option(details::Setting<std::string, details::ProgressBarOption::postfix_text> &&setting) {
2702 std::lock_guard<std::mutex> lock(mutex_);
2703 get_value<details::ProgressBarOption::postfix_text>() = std::move(setting).value;
2704 auto &new_value = get_value<details::ProgressBarOption::postfix_text>();
2705 if (new_value.length() > get_value<details::ProgressBarOption::max_postfix_text_len>()) {
2706 get_value<details::ProgressBarOption::max_postfix_text_len>() = new_value.length();
2712 std::lock_guard<std::mutex> lock{mutex_};
2713 if (get_value<details::ProgressBarOption::completed>())
2716 progress_ += (direction_ == Direction::forward) ? 1 : -1;
2717 if (direction_ == Direction::forward && progress_ == max_progress_) {
2719 direction_ = Direction::backward;
2720 }
else if (direction_ == Direction::backward && progress_ == 0) {
2721 direction_ = Direction::forward;
2727 bool is_completed() {
return get_value<details::ProgressBarOption::completed>(); }
2729 void mark_as_completed() {
2730 get_value<details::ProgressBarOption::completed>() =
true;
2735 template <details::ProgressBarOption
id>
2736 auto get_value() -> decltype((details::get_value<id>(std::declval<Settings &>()).value)) {
2737 return details::get_value<id>(settings_).value;
2740 template <details::ProgressBarOption
id>
2741 auto get_value() const
2742 -> decltype((details::get_value<
id>(std::declval<const Settings &>()).value)) {
2743 return details::get_value<id>(settings_).value;
2746 size_t progress_{0};
2747 size_t max_progress_;
2749 std::chrono::nanoseconds elapsed_;
2752 template <
typename Indicator,
size_t count>
friend class MultiProgress;
2753 template <
typename Indicator>
friend class DynamicProgress;
2754 std::atomic<bool> multi_progress_mode_{
false};
2756 std::pair<std::string, int> get_prefix_text() {
2757 std::stringstream os;
2758 os << get_value<details::ProgressBarOption::prefix_text>();
2759 const auto result = os.str();
2760 const auto result_size = unicode::display_width(result);
2761 return {result, result_size};
2764 std::pair<std::string, int> get_postfix_text() {
2765 std::stringstream os;
2766 os <<
" " << get_value<details::ProgressBarOption::postfix_text>();
2768 const auto result = os.str();
2769 const auto result_size = unicode::display_width(result);
2770 return {result, result_size};
2774 void print_progress(
bool from_multi_progress =
false) {
2775 std::lock_guard<std::mutex> lock{mutex_};
2777 auto &os = get_value<details::ProgressBarOption::stream>();
2779 if (multi_progress_mode_ && !from_multi_progress) {
2782 if (get_value<details::ProgressBarOption::foreground_color>() != Color::unspecified)
2783 details::set_stream_color(os, get_value<details::ProgressBarOption::foreground_color>());
2785 for (
auto &style : get_value<details::ProgressBarOption::font_styles>())
2786 details::set_font_style(os, style);
2788 const auto prefix_pair = get_prefix_text();
2789 const auto prefix_text = prefix_pair.first;
2790 const auto prefix_length = prefix_pair.second;
2791 os <<
"\r" << prefix_text;
2793 os << get_value<details::ProgressBarOption::start>();
2795 details::IndeterminateProgressScaleWriter writer{
2796 os, get_value<details::ProgressBarOption::bar_width>(),
2797 get_value<details::ProgressBarOption::fill>(),
2798 get_value<details::ProgressBarOption::lead>()};
2799 writer.write(progress_);
2801 os << get_value<details::ProgressBarOption::end>();
2803 const auto postfix_pair = get_postfix_text();
2804 const auto postfix_text = postfix_pair.first;
2805 const auto postfix_length = postfix_pair.second;
2809 const auto start_length = get_value<details::ProgressBarOption::start>().size();
2810 const auto bar_width = get_value<details::ProgressBarOption::bar_width>();
2811 const auto end_length = get_value<details::ProgressBarOption::end>().size();
2812 const auto terminal_width = terminal_size().second;
2814 const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length);
2815 if (prefix_length == -1 || postfix_length == -1) {
2817 }
else if (remaining > 0) {
2818 os << std::string(remaining,
' ') <<
"\r";
2819 }
else if (remaining < 0) {
2824 if (get_value<details::ProgressBarOption::completed>() &&
2825 !from_multi_progress)
2826 os << termcolor::reset << std::endl;
2835 #ifndef INDICATORS_MULTI_PROGRESS
2836 #define INDICATORS_MULTI_PROGRESS
2838 #include <functional>
2849 template <
typename Indicator,
size_t count>
class MultiProgress {
2851 template <
typename... Indicators,
2852 typename =
typename std::enable_if<(
sizeof...(Indicators) == count)>::type>
2853 explicit MultiProgress(Indicators &... bars) {
2855 for (
auto &bar : bars_) {
2856 bar.get().multi_progress_mode_ =
true;
2860 template <
size_t index>
2861 typename std::enable_if<(index >= 0 && index < count), void>::type set_progress(
size_t value) {
2862 if (!bars_[index].get().is_completed())
2863 bars_[index].get().set_progress(value);
2867 template <
size_t index>
2868 typename std::enable_if<(index >= 0 && index < count), void>::type set_progress(
float value) {
2869 if (!bars_[index].get().is_completed())
2870 bars_[index].get().set_progress(value);
2874 template <
size_t index>
2875 typename std::enable_if<(index >= 0 && index < count), void>::type tick() {
2876 if (!bars_[index].get().is_completed())
2877 bars_[index].get().tick();
2881 template <
size_t index>
2882 typename std::enable_if<(index >= 0 && index < count), bool>::type is_completed()
const {
2883 return bars_[index].get().is_completed();
2887 std::atomic<bool> started_{
false};
2889 std::vector<std::reference_wrapper<Indicator>> bars_;
2891 bool _all_completed() {
2893 for (
size_t i = 0; i < count; ++i)
2894 result &= bars_[i].get().is_completed();
2899 void print_progress() {
2900 std::lock_guard<std::mutex> lock{mutex_};
2903 for (
auto &bar : bars_) {
2904 bar.get().print_progress(
true);
2907 std::cout << termcolor::reset;
2918 #ifndef INDICATORS_DYNAMIC_PROGRESS
2919 #define INDICATORS_DYNAMIC_PROGRESS
2922 #include <functional>
2934 template <
typename Indicator>
class DynamicProgress {
2935 using Settings = std::tuple<option::HideBarWhenComplete>;
2938 template <
typename... Indicators>
explicit DynamicProgress(Indicators &... bars) {
2940 for (
auto &bar : bars_) {
2941 bar.get().multi_progress_mode_ =
true;
2943 ++incomplete_count_;
2947 Indicator &operator[](
size_t index) {
2949 std::lock_guard<std::mutex> lock{mutex_};
2950 return bars_[index].get();
2953 size_t push_back(Indicator &bar) {
2954 std::lock_guard<std::mutex> lock{mutex_};
2955 bar.multi_progress_mode_ =
true;
2956 bars_.push_back(bar);
2957 return bars_.size() - 1;
2960 template <
typename T, details::ProgressBarOption
id>
2961 void set_option(details::Setting<T, id> &&setting) {
2962 static_assert(!std::is_same<T,
typename std::decay<decltype(details::get_value<id>(
2963 std::declval<Settings>()))>::type>::value,
2964 "Setting has wrong type!");
2965 std::lock_guard<std::mutex> lock(mutex_);
2966 get_value<id>() = std::move(setting).value;
2969 template <
typename T, details::ProgressBarOption
id>
2970 void set_option(
const details::Setting<T, id> &setting) {
2971 static_assert(!std::is_same<T,
typename std::decay<decltype(details::get_value<id>(
2972 std::declval<Settings>()))>::type>::value,
2973 "Setting has wrong type!");
2974 std::lock_guard<std::mutex> lock(mutex_);
2975 get_value<id>() = setting.value;
2980 std::atomic<bool> started_{
false};
2982 std::vector<std::reference_wrapper<Indicator>> bars_;
2983 std::atomic<size_t> total_count_{0};
2984 std::atomic<size_t> incomplete_count_{0};
2986 template <details::ProgressBarOption
id>
2987 auto get_value() -> decltype((details::get_value<id>(std::declval<Settings &>()).value)) {
2988 return details::get_value<id>(settings_).value;
2991 template <details::ProgressBarOption
id>
2992 auto get_value() const
2993 -> decltype((details::get_value<
id>(std::declval<const Settings &>()).value)) {
2994 return details::get_value<id>(settings_).value;
2998 void print_progress() {
2999 std::lock_guard<std::mutex> lock{mutex_};
3000 auto &hide_bar_when_complete = get_value<details::ProgressBarOption::hide_bar_when_complete>();
3001 if (hide_bar_when_complete) {
3004 for (
size_t i = 0; i < incomplete_count_; ++i) {
3007 std::cout << std::flush;
3010 incomplete_count_ = 0;
3011 for (
auto &bar : bars_) {
3012 if (!bar.get().is_completed()) {
3013 bar.get().print_progress(
true);
3015 ++incomplete_count_;
3023 move_up(
static_cast<int>(total_count_));
3024 for (
auto &bar : bars_) {
3025 bar.get().print_progress(
true);
3031 total_count_ = bars_.size();
3032 std::cout << termcolor::reset;
3041 #ifndef INDICATORS_PROGRESS_SPINNER
3042 #define INDICATORS_PROGRESS_SPINNER
3046 #include <algorithm>
3062 class ProgressSpinner {
3064 std::tuple<option::ForegroundColor, option::PrefixText, option::PostfixText,
3065 option::ShowPercentage, option::ShowElapsedTime, option::ShowRemainingTime,
3066 option::ShowSpinner, option::SavedStartTime, option::Completed,
3067 option::MaxPostfixTextLen, option::SpinnerStates, option::FontStyles,
3068 option::MaxProgress, option::Stream>;
3071 template <
typename... Args,
3072 typename std::enable_if<details::are_settings_from_tuple<
3073 Settings,
typename std::decay<Args>::type...>::value,
3074 void *>::type =
nullptr>
3075 explicit ProgressSpinner(Args &&... args)
3077 details::get<details::ProgressBarOption::foreground_color>(
3079 details::get<details::ProgressBarOption::prefix_text>(option::PrefixText{},
3080 std::forward<Args>(args)...),
3081 details::get<details::ProgressBarOption::postfix_text>(option::PostfixText{},
3082 std::forward<Args>(args)...),
3083 details::get<details::ProgressBarOption::show_percentage>(option::ShowPercentage{true},
3084 std::forward<Args>(args)...),
3085 details::get<details::ProgressBarOption::show_elapsed_time>(
3086 option::ShowElapsedTime{false}, std::forward<Args>(args)...),
3087 details::get<details::ProgressBarOption::show_remaining_time>(
3088 option::ShowRemainingTime{false}, std::forward<Args>(args)...),
3089 details::get<details::ProgressBarOption::spinner_show>(option::ShowSpinner{true},
3090 std::forward<Args>(args)...),
3091 details::get<details::ProgressBarOption::saved_start_time>(
3092 option::SavedStartTime{false}, std::forward<Args>(args)...),
3093 details::get<details::ProgressBarOption::completed>(option::Completed{false},
3094 std::forward<Args>(args)...),
3095 details::get<details::ProgressBarOption::max_postfix_text_len>(
3096 option::MaxPostfixTextLen{0}, std::forward<Args>(args)...),
3097 details::get<details::ProgressBarOption::spinner_states>(
3098 option::SpinnerStates{
3099 std::vector<std::string>{
"⠋",
"⠙",
"⠹",
"⠸",
"⠼",
"⠴",
"⠦",
"⠧",
"⠇",
"⠏"}},
3100 std::forward<Args>(args)...),
3101 details::get<details::ProgressBarOption::font_styles>(
3102 option::FontStyles{std::vector<FontStyle>{}}, std::forward<Args>(args)...),
3103 details::get<details::ProgressBarOption::max_progress>(option::MaxProgress{100},
3104 std::forward<Args>(args)...),
3105 details::get<details::ProgressBarOption::stream>(option::Stream{std::cout},
3106 std::forward<Args>(args)...)) {}
3108 template <
typename T, details::ProgressBarOption
id>
3109 void set_option(details::Setting<T, id> &&setting) {
3110 static_assert(!std::is_same<T,
typename std::decay<decltype(details::get_value<id>(
3111 std::declval<Settings>()))>::type>::value,
3112 "Setting has wrong type!");
3113 std::lock_guard<std::mutex> lock(mutex_);
3114 get_value<id>() = std::move(setting).value;
3117 template <
typename T, details::ProgressBarOption
id>
3118 void set_option(
const details::Setting<T, id> &setting) {
3119 static_assert(!std::is_same<T,
typename std::decay<decltype(details::get_value<id>(
3120 std::declval<Settings>()))>::type>::value,
3121 "Setting has wrong type!");
3122 std::lock_guard<std::mutex> lock(mutex_);
3123 get_value<id>() = setting.value;
3127 const details::Setting<std::string, details::ProgressBarOption::postfix_text> &setting) {
3128 std::lock_guard<std::mutex> lock(mutex_);
3129 get_value<details::ProgressBarOption::postfix_text>() = setting.value;
3130 if (setting.value.length() > get_value<details::ProgressBarOption::max_postfix_text_len>()) {
3131 get_value<details::ProgressBarOption::max_postfix_text_len>() = setting.value.length();
3136 set_option(details::Setting<std::string, details::ProgressBarOption::postfix_text> &&setting) {
3137 std::lock_guard<std::mutex> lock(mutex_);
3138 get_value<details::ProgressBarOption::postfix_text>() = std::move(setting).value;
3139 auto &new_value = get_value<details::ProgressBarOption::postfix_text>();
3140 if (new_value.length() > get_value<details::ProgressBarOption::max_postfix_text_len>()) {
3141 get_value<details::ProgressBarOption::max_postfix_text_len>() = new_value.length();
3145 void set_progress(
size_t value) {
3147 std::lock_guard<std::mutex> lock{mutex_};
3156 std::lock_guard<std::mutex> lock{mutex_};
3164 std::lock_guard<std::mutex> lock{mutex_};
3165 return (std::min)(progress_, size_t(get_value<details::ProgressBarOption::max_progress>()));
3168 bool is_completed()
const {
return get_value<details::ProgressBarOption::completed>(); }
3170 void mark_as_completed() {
3171 get_value<details::ProgressBarOption::completed>() =
true;
3177 size_t progress_{0};
3179 std::chrono::time_point<std::chrono::high_resolution_clock> start_time_point_;
3182 template <details::ProgressBarOption
id>
3183 auto get_value() -> decltype((details::get_value<id>(std::declval<Settings &>()).value)) {
3184 return details::get_value<id>(settings_).value;
3187 template <details::ProgressBarOption
id>
3188 auto get_value() const
3189 -> decltype((details::get_value<
id>(std::declval<const Settings &>()).value)) {
3190 return details::get_value<id>(settings_).value;
3193 void save_start_time() {
3194 auto &show_elapsed_time = get_value<details::ProgressBarOption::show_elapsed_time>();
3195 auto &show_remaining_time = get_value<details::ProgressBarOption::show_remaining_time>();
3196 auto &saved_start_time = get_value<details::ProgressBarOption::saved_start_time>();
3197 if ((show_elapsed_time || show_remaining_time) && !saved_start_time) {
3198 start_time_point_ = std::chrono::high_resolution_clock::now();
3199 saved_start_time =
true;
3204 void print_progress() {
3205 std::lock_guard<std::mutex> lock{mutex_};
3207 auto &os = get_value<details::ProgressBarOption::stream>();
3209 const auto max_progress = get_value<details::ProgressBarOption::max_progress>();
3210 auto now = std::chrono::high_resolution_clock::now();
3211 auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(now - start_time_point_);
3214 details::set_stream_color(os, get_value<details::ProgressBarOption::foreground_color>());
3216 for (
auto &style : get_value<details::ProgressBarOption::font_styles>())
3217 details::set_font_style(os, style);
3219 os << get_value<details::ProgressBarOption::prefix_text>();
3220 if (get_value<details::ProgressBarOption::spinner_show>())
3221 os << get_value<details::ProgressBarOption::spinner_states>()
3222 [index_ % get_value<details::ProgressBarOption::spinner_states>().size()];
3223 if (get_value<details::ProgressBarOption::show_percentage>()) {
3224 os <<
" " << std::size_t(progress_ /
double(max_progress) * 100) <<
"%";
3227 if (get_value<details::ProgressBarOption::show_elapsed_time>()) {
3229 details::write_duration(os, elapsed);
3232 if (get_value<details::ProgressBarOption::show_remaining_time>()) {
3233 if (get_value<details::ProgressBarOption::show_elapsed_time>())
3237 auto eta = std::chrono::nanoseconds(
3239 ?
static_cast<long long>(std::ceil(
float(elapsed.count()) *
3240 max_progress / progress_))
3242 auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
3243 details::write_duration(os, remaining);
3246 if (get_value<details::ProgressBarOption::show_elapsed_time>())
3250 if (get_value<details::ProgressBarOption::max_postfix_text_len>() == 0)
3251 get_value<details::ProgressBarOption::max_postfix_text_len>() = 10;
3252 os <<
" " << get_value<details::ProgressBarOption::postfix_text>()
3253 << std::string(get_value<details::ProgressBarOption::max_postfix_text_len>(),
' ') <<
"\r";
3256 if (progress_ > max_progress) {
3257 get_value<details::ProgressBarOption::completed>() =
true;
3259 if (get_value<details::ProgressBarOption::completed>())
3260 os << termcolor::reset << std::endl;