12 #ifndef TERMCOLOR_HPP_
13 #define TERMCOLOR_HPP_
20 #if defined(_WIN32) || defined(_WIN64)
21 # define TERMCOLOR_TARGET_WINDOWS
22 #elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
23 # define TERMCOLOR_TARGET_POSIX
28 #if !defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) && !defined(TERMCOLOR_USE_WINDOWS_API) && !defined(TERMCOLOR_USE_NOOP)
29 # if defined(TERMCOLOR_TARGET_POSIX)
30 # define TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES
31 # define TERMCOLOR_AUTODETECTED_IMPLEMENTATION
32 # elif defined(TERMCOLOR_TARGET_WINDOWS)
33 # define TERMCOLOR_USE_WINDOWS_API
34 # define TERMCOLOR_AUTODETECTED_IMPLEMENTATION
40 #if defined(TERMCOLOR_TARGET_POSIX)
42 #elif defined(TERMCOLOR_TARGET_WINDOWS)
54 inline int colorize_index();
55 inline FILE* get_standard_stream(
const std::ostream& stream);
56 inline bool is_colorized(std::ostream& stream);
57 inline bool is_atty(
const std::ostream& stream);
59 #if defined(TERMCOLOR_TARGET_WINDOWS)
60 inline void win_change_attributes(std::ostream& stream,
int foreground,
int background = -1);
65 std::ostream& colorize(std::ostream& stream)
67 stream.iword(_internal::colorize_index()) = 1L;
72 std::ostream& nocolorize(std::ostream& stream)
74 stream.iword(_internal::colorize_index()) = 0L;
79 std::ostream& reset(std::ostream& stream)
81 if (_internal::is_colorized(stream))
83 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
85 #elif defined(TERMCOLOR_USE_WINDOWS_API)
86 _internal::win_change_attributes(stream, -1, -1);
93 std::ostream& bold(std::ostream& stream)
95 if (_internal::is_colorized(stream))
97 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
99 #elif defined(TERMCOLOR_USE_WINDOWS_API)
106 std::ostream& dark(std::ostream& stream)
108 if (_internal::is_colorized(stream))
110 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
112 #elif defined(TERMCOLOR_USE_WINDOWS_API)
119 std::ostream& italic(std::ostream& stream)
121 if (_internal::is_colorized(stream))
123 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
125 #elif defined(TERMCOLOR_USE_WINDOWS_API)
132 std::ostream& underline(std::ostream& stream)
134 if (_internal::is_colorized(stream))
136 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
138 #elif defined(TERMCOLOR_USE_WINDOWS_API)
139 _internal::win_change_attributes(stream, -1, COMMON_LVB_UNDERSCORE);
146 std::ostream& blink(std::ostream& stream)
148 if (_internal::is_colorized(stream))
150 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
152 #elif defined(TERMCOLOR_USE_WINDOWS_API)
159 std::ostream& reverse(std::ostream& stream)
161 if (_internal::is_colorized(stream))
163 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
165 #elif defined(TERMCOLOR_USE_WINDOWS_API)
172 std::ostream& concealed(std::ostream& stream)
174 if (_internal::is_colorized(stream))
176 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
178 #elif defined(TERMCOLOR_USE_WINDOWS_API)
185 std::ostream& crossed(std::ostream& stream)
187 if (_internal::is_colorized(stream))
189 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
191 #elif defined(TERMCOLOR_USE_WINDOWS_API)
197 template <u
int8_t code>
inline
198 std::ostream& color(std::ostream& stream)
200 if (_internal::is_colorized(stream))
202 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
204 std::snprintf(command,
sizeof(command),
"\033[38;5;%dm", code);
206 #elif defined(TERMCOLOR_USE_WINDOWS_API)
212 template <u
int8_t code>
inline
213 std::ostream& on_color(std::ostream& stream)
215 if (_internal::is_colorized(stream))
217 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
219 std::snprintf(command,
sizeof(command),
"\033[48;5;%dm", code);
221 #elif defined(TERMCOLOR_USE_WINDOWS_API)
227 template <u
int8_t r, u
int8_t g, u
int8_t b>
inline
228 std::ostream& color(std::ostream& stream)
230 if (_internal::is_colorized(stream))
232 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
234 std::snprintf(command,
sizeof(command),
"\033[38;2;%d;%d;%dm", r, g, b);
236 #elif defined(TERMCOLOR_USE_WINDOWS_API)
242 template <u
int8_t r, u
int8_t g, u
int8_t b>
inline
243 std::ostream& on_color(std::ostream& stream)
245 if (_internal::is_colorized(stream))
247 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
249 std::snprintf(command,
sizeof(command),
"\033[48;2;%d;%d;%dm", r, g, b);
251 #elif defined(TERMCOLOR_USE_WINDOWS_API)
258 std::ostream& grey(std::ostream& stream)
260 if (_internal::is_colorized(stream))
262 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
263 stream <<
"\033[30m";
264 #elif defined(TERMCOLOR_USE_WINDOWS_API)
265 _internal::win_change_attributes(stream,
274 std::ostream& red(std::ostream& stream)
276 if (_internal::is_colorized(stream))
278 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
279 stream <<
"\033[31m";
280 #elif defined(TERMCOLOR_USE_WINDOWS_API)
281 _internal::win_change_attributes(stream,
290 std::ostream& green(std::ostream& stream)
292 if (_internal::is_colorized(stream))
294 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
295 stream <<
"\033[32m";
296 #elif defined(TERMCOLOR_USE_WINDOWS_API)
297 _internal::win_change_attributes(stream,
306 std::ostream& yellow(std::ostream& stream)
308 if (_internal::is_colorized(stream))
310 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
311 stream <<
"\033[33m";
312 #elif defined(TERMCOLOR_USE_WINDOWS_API)
313 _internal::win_change_attributes(stream,
314 FOREGROUND_GREEN | FOREGROUND_RED
322 std::ostream& blue(std::ostream& stream)
324 if (_internal::is_colorized(stream))
326 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
327 stream <<
"\033[34m";
328 #elif defined(TERMCOLOR_USE_WINDOWS_API)
329 _internal::win_change_attributes(stream,
338 std::ostream& magenta(std::ostream& stream)
340 if (_internal::is_colorized(stream))
342 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
343 stream <<
"\033[35m";
344 #elif defined(TERMCOLOR_USE_WINDOWS_API)
345 _internal::win_change_attributes(stream,
346 FOREGROUND_BLUE | FOREGROUND_RED
354 std::ostream& cyan(std::ostream& stream)
356 if (_internal::is_colorized(stream))
358 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
359 stream <<
"\033[36m";
360 #elif defined(TERMCOLOR_USE_WINDOWS_API)
361 _internal::win_change_attributes(stream,
362 FOREGROUND_BLUE | FOREGROUND_GREEN
370 std::ostream& white(std::ostream& stream)
372 if (_internal::is_colorized(stream))
374 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
375 stream <<
"\033[37m";
376 #elif defined(TERMCOLOR_USE_WINDOWS_API)
377 _internal::win_change_attributes(stream,
378 FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
387 std::ostream& bright_grey(std::ostream& stream)
389 if (_internal::is_colorized(stream))
391 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
392 stream <<
"\033[90m";
393 #elif defined(TERMCOLOR_USE_WINDOWS_API)
394 _internal::win_change_attributes(stream,
395 0 | FOREGROUND_INTENSITY
403 std::ostream& bright_red(std::ostream& stream)
405 if (_internal::is_colorized(stream))
407 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
408 stream <<
"\033[91m";
409 #elif defined(TERMCOLOR_USE_WINDOWS_API)
410 _internal::win_change_attributes(stream,
411 FOREGROUND_RED | FOREGROUND_INTENSITY
419 std::ostream& bright_green(std::ostream& stream)
421 if (_internal::is_colorized(stream))
423 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
424 stream <<
"\033[92m";
425 #elif defined(TERMCOLOR_USE_WINDOWS_API)
426 _internal::win_change_attributes(stream,
427 FOREGROUND_GREEN | FOREGROUND_INTENSITY
435 std::ostream& bright_yellow(std::ostream& stream)
437 if (_internal::is_colorized(stream))
439 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
440 stream <<
"\033[93m";
441 #elif defined(TERMCOLOR_USE_WINDOWS_API)
442 _internal::win_change_attributes(stream,
443 FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
451 std::ostream& bright_blue(std::ostream& stream)
453 if (_internal::is_colorized(stream))
455 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
456 stream <<
"\033[94m";
457 #elif defined(TERMCOLOR_USE_WINDOWS_API)
458 _internal::win_change_attributes(stream,
459 FOREGROUND_BLUE | FOREGROUND_INTENSITY
467 std::ostream& bright_magenta(std::ostream& stream)
469 if (_internal::is_colorized(stream))
471 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
472 stream <<
"\033[95m";
473 #elif defined(TERMCOLOR_USE_WINDOWS_API)
474 _internal::win_change_attributes(stream,
475 FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY
483 std::ostream& bright_cyan(std::ostream& stream)
485 if (_internal::is_colorized(stream))
487 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
488 stream <<
"\033[96m";
489 #elif defined(TERMCOLOR_USE_WINDOWS_API)
490 _internal::win_change_attributes(stream,
491 FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY
499 std::ostream& bright_white(std::ostream& stream)
501 if (_internal::is_colorized(stream))
503 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
504 stream <<
"\033[97m";
505 #elif defined(TERMCOLOR_USE_WINDOWS_API)
506 _internal::win_change_attributes(stream,
507 FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
516 std::ostream& on_grey(std::ostream& stream)
518 if (_internal::is_colorized(stream))
520 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
521 stream <<
"\033[40m";
522 #elif defined(TERMCOLOR_USE_WINDOWS_API)
523 _internal::win_change_attributes(stream, -1,
532 std::ostream& on_red(std::ostream& stream)
534 if (_internal::is_colorized(stream))
536 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
537 stream <<
"\033[41m";
538 #elif defined(TERMCOLOR_USE_WINDOWS_API)
539 _internal::win_change_attributes(stream, -1,
548 std::ostream& on_green(std::ostream& stream)
550 if (_internal::is_colorized(stream))
552 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
553 stream <<
"\033[42m";
554 #elif defined(TERMCOLOR_USE_WINDOWS_API)
555 _internal::win_change_attributes(stream, -1,
564 std::ostream& on_yellow(std::ostream& stream)
566 if (_internal::is_colorized(stream))
568 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
569 stream <<
"\033[43m";
570 #elif defined(TERMCOLOR_USE_WINDOWS_API)
571 _internal::win_change_attributes(stream, -1,
572 BACKGROUND_GREEN | BACKGROUND_RED
580 std::ostream& on_blue(std::ostream& stream)
582 if (_internal::is_colorized(stream))
584 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
585 stream <<
"\033[44m";
586 #elif defined(TERMCOLOR_USE_WINDOWS_API)
587 _internal::win_change_attributes(stream, -1,
596 std::ostream& on_magenta(std::ostream& stream)
598 if (_internal::is_colorized(stream))
600 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
601 stream <<
"\033[45m";
602 #elif defined(TERMCOLOR_USE_WINDOWS_API)
603 _internal::win_change_attributes(stream, -1,
604 BACKGROUND_BLUE | BACKGROUND_RED
612 std::ostream& on_cyan(std::ostream& stream)
614 if (_internal::is_colorized(stream))
616 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
617 stream <<
"\033[46m";
618 #elif defined(TERMCOLOR_USE_WINDOWS_API)
619 _internal::win_change_attributes(stream, -1,
620 BACKGROUND_GREEN | BACKGROUND_BLUE
628 std::ostream& on_white(std::ostream& stream)
630 if (_internal::is_colorized(stream))
632 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
633 stream <<
"\033[47m";
634 #elif defined(TERMCOLOR_USE_WINDOWS_API)
635 _internal::win_change_attributes(stream, -1,
636 BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
646 std::ostream& on_bright_grey(std::ostream& stream)
648 if (_internal::is_colorized(stream))
650 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
651 stream <<
"\033[100m";
652 #elif defined(TERMCOLOR_USE_WINDOWS_API)
653 _internal::win_change_attributes(stream, -1,
654 0 | BACKGROUND_INTENSITY
662 std::ostream& on_bright_red(std::ostream& stream)
664 if (_internal::is_colorized(stream))
666 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
667 stream <<
"\033[101m";
668 #elif defined(TERMCOLOR_USE_WINDOWS_API)
669 _internal::win_change_attributes(stream, -1,
670 BACKGROUND_RED | BACKGROUND_INTENSITY
678 std::ostream& on_bright_green(std::ostream& stream)
680 if (_internal::is_colorized(stream))
682 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
683 stream <<
"\033[102m";
684 #elif defined(TERMCOLOR_USE_WINDOWS_API)
685 _internal::win_change_attributes(stream, -1,
686 BACKGROUND_GREEN | BACKGROUND_INTENSITY
694 std::ostream& on_bright_yellow(std::ostream& stream)
696 if (_internal::is_colorized(stream))
698 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
699 stream <<
"\033[103m";
700 #elif defined(TERMCOLOR_USE_WINDOWS_API)
701 _internal::win_change_attributes(stream, -1,
702 BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY
710 std::ostream& on_bright_blue(std::ostream& stream)
712 if (_internal::is_colorized(stream))
714 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
715 stream <<
"\033[104m";
716 #elif defined(TERMCOLOR_USE_WINDOWS_API)
717 _internal::win_change_attributes(stream, -1,
718 BACKGROUND_BLUE | BACKGROUND_INTENSITY
726 std::ostream& on_bright_magenta(std::ostream& stream)
728 if (_internal::is_colorized(stream))
730 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
731 stream <<
"\033[105m";
732 #elif defined(TERMCOLOR_USE_WINDOWS_API)
733 _internal::win_change_attributes(stream, -1,
734 BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY
742 std::ostream& on_bright_cyan(std::ostream& stream)
744 if (_internal::is_colorized(stream))
746 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
747 stream <<
"\033[106m";
748 #elif defined(TERMCOLOR_USE_WINDOWS_API)
749 _internal::win_change_attributes(stream, -1,
750 BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY
758 std::ostream& on_bright_white(std::ostream& stream)
760 if (_internal::is_colorized(stream))
762 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
763 stream <<
"\033[107m";
764 #elif defined(TERMCOLOR_USE_WINDOWS_API)
765 _internal::win_change_attributes(stream, -1,
766 BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY
787 inline int colorize_index()
789 static int colorize_index = std::ios_base::xalloc();
790 return colorize_index;
797 FILE* get_standard_stream(
const std::ostream& stream)
799 if (&stream == &std::cout)
801 else if ((&stream == &std::cerr) || (&stream == &std::clog))
811 bool is_colorized(std::ostream& stream)
813 return is_atty(stream) ||
static_cast<bool>(stream.iword(colorize_index()));
819 bool is_atty(
const std::ostream& stream)
821 FILE* std_stream = get_standard_stream(stream);
830 #if defined(TERMCOLOR_TARGET_POSIX)
831 return ::isatty(fileno(std_stream));
832 #elif defined(TERMCOLOR_TARGET_WINDOWS)
833 return ::_isatty(_fileno(std_stream));
839 #if defined(TERMCOLOR_TARGET_WINDOWS)
840 inline void win_change_attributes(std::ostream& stream,
int foreground,
int background)
845 static WORD defaultAttributes = 0;
851 if (!_internal::is_atty(stream))
855 HANDLE hTerminal = INVALID_HANDLE_VALUE;
856 if (&stream == &std::cout)
857 hTerminal = GetStdHandle(STD_OUTPUT_HANDLE);
858 else if (&stream == &std::cerr)
859 hTerminal = GetStdHandle(STD_ERROR_HANDLE);
862 if (!defaultAttributes)
864 CONSOLE_SCREEN_BUFFER_INFO info;
865 if (!GetConsoleScreenBufferInfo(hTerminal, &info))
867 defaultAttributes = info.wAttributes;
871 if (foreground == -1 && background == -1)
873 SetConsoleTextAttribute(hTerminal, defaultAttributes);
878 CONSOLE_SCREEN_BUFFER_INFO info;
879 if (!GetConsoleScreenBufferInfo(hTerminal, &info))
882 if (foreground != -1)
884 info.wAttributes &= ~(info.wAttributes & 0x0F);
885 info.wAttributes |=
static_cast<WORD
>(foreground);
888 if (background != -1)
890 info.wAttributes &= ~(info.wAttributes & 0xF0);
891 info.wAttributes |=
static_cast<WORD
>(background);
894 SetConsoleTextAttribute(hTerminal, info.wAttributes);
896 #endif // TERMCOLOR_TARGET_WINDOWS
903 #undef TERMCOLOR_TARGET_POSIX
904 #undef TERMCOLOR_TARGET_WINDOWS
906 #if defined(TERMCOLOR_AUTODETECTED_IMPLEMENTATION)
907 # undef TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES
908 # undef TERMCOLOR_USE_WINDOWS_API
911 #endif // TERMCOLOR_HPP_