From 51ceef3dee58477718ebf0c436e7e8a8da246d4e Mon Sep 17 00:00:00 2001 From: Ryuuke Date: Sat, 7 Feb 2015 22:39:08 +0000 Subject: [PATCH 1/5] added color support for windows --- format.cc | 21 +++++++++++++-------- format.h | 25 ++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/format.cc b/format.cc index 4974b355..ba978035 100644 --- a/format.cc +++ b/format.cc @@ -35,13 +35,6 @@ #include #include -#ifdef _WIN32 -# ifdef __MINGW32__ -# include -# endif -# include -#endif - using fmt::internal::Arg; // Check if exceptions are disabled. @@ -119,7 +112,11 @@ struct IntChecker { } }; -const char RESET_COLOR[] = "\x1b[0m"; +#ifdef _WIN32 + const char RESET_COLOR = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE; +#else + const char RESET_COLOR[] = "\x1b[0m"; +#endif typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef); @@ -1098,11 +1095,19 @@ FMT_FUNC void fmt::print(std::ostream &os, StringRef format_str, ArgList args) { } FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) { +#ifdef _WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); +#else char escape[] = "\x1b[30m"; escape[3] = '0' + static_cast(c); std::fputs(escape, stdout); +#endif print(format, args); +#ifdef _WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), RESET_COLOR); +#else std::fputs(RESET_COLOR, stdout); +#endif } FMT_FUNC int fmt::fprintf(std::FILE *f, StringRef format, ArgList args) { diff --git a/format.h b/format.h index 0af01439..17dce15b 100644 --- a/format.h +++ b/format.h @@ -40,6 +40,15 @@ #include #include +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# ifdef __MINGW32__ +# include +# endif +# include +# undef ERROR +#endif + #if _SECURE_SCL # include #endif @@ -2154,7 +2163,21 @@ void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT(true); #endif -enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; +#ifdef _WIN32 + enum Color : uint8_t + { + BLACK = 0, + RED = FOREGROUND_RED | FOREGROUND_INTENSITY, + GREEN = FOREGROUND_GREEN | FOREGROUND_INTENSITY, + YELLOW = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY, + BLUE = FOREGROUND_BLUE | FOREGROUND_INTENSITY, + MAGENTA = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY, + CYAN = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE, + WHITE = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY + }; +#else + enum Color : uint8_t { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; +#endif /** Formats a string and prints it to stdout using ANSI escape sequences From bce73e2bd827b27261259beb6b2c90edc61c8824 Mon Sep 17 00:00:00 2001 From: Ryuuke Date: Sat, 7 Feb 2015 22:47:42 +0000 Subject: [PATCH 2/5] remove forward enum declaration --- format.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/format.h b/format.h index 17dce15b..1e78f8dd 100644 --- a/format.h +++ b/format.h @@ -2164,7 +2164,7 @@ void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT(true); #endif #ifdef _WIN32 - enum Color : uint8_t + enum Color { BLACK = 0, RED = FOREGROUND_RED | FOREGROUND_INTENSITY, @@ -2176,7 +2176,7 @@ void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT(true); WHITE = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY }; #else - enum Color : uint8_t { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; + enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; #endif /** From 5a9dc8f99110ee5ae8d17b9d8e896a1a9560ff4b Mon Sep 17 00:00:00 2001 From: Ryuuke Date: Sun, 8 Feb 2015 16:08:29 +0000 Subject: [PATCH 3/5] windows cli colors revision and test case --- format.cc | 42 ++++++++++++++++++++++++++++++++++++++---- format.h | 25 +------------------------ test/format-test.cc | 9 ++++++++- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/format.cc b/format.cc index ba978035..07e630d5 100644 --- a/format.cc +++ b/format.cc @@ -35,6 +35,15 @@ #include #include +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# ifdef __MINGW32__ +# include +# endif +# include +# undef ERROR +#endif + using fmt::internal::Arg; // Check if exceptions are disabled. @@ -113,9 +122,21 @@ struct IntChecker { }; #ifdef _WIN32 - const char RESET_COLOR = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE; + uint8_t win32_colors[] = + { + 0, + FOREGROUND_RED | FOREGROUND_INTENSITY, + FOREGROUND_GREEN | FOREGROUND_INTENSITY, + FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY, + FOREGROUND_BLUE | FOREGROUND_INTENSITY, + FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY, + FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE, + FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY + }; + WORD RESET_COLOR = 0; + bool reset_color_flag = false; #else - const char RESET_COLOR[] = "\x1b[0m"; + const char RESET_COLOR[] = "\x1b[0m"; #endif typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef); @@ -1096,7 +1117,19 @@ FMT_FUNC void fmt::print(std::ostream &os, StringRef format_str, ArgList args) { FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) { #ifdef _WIN32 - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); + HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); + if (handle == INVALID_HANDLE_VALUE) + FMT_THROW(GetLastError(), "cannot get output handle"); + if (!reset_color_flag) { + CONSOLE_SCREEN_BUFFER_INFO infoCon; + if (!GetConsoleScreenBufferInfo(handle, &infoCon)) + FMT_THROW(GetLastError(), "cannot get console informations"); + RESET_COLOR = infoCon.wAttributes; + reset_color_flag = true; + } + WORD color = static_cast(c) >= ARRAYSIZE(win32_colors) ? RESET_COLOR : win32_colors[c]; + if (!SetConsoleTextAttribute(handle, color)) + FMT_THROW(GetLastError(), "cannot set console color"); #else char escape[] = "\x1b[30m"; escape[3] = '0' + static_cast(c); @@ -1104,7 +1137,8 @@ FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) { #endif print(format, args); #ifdef _WIN32 - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), RESET_COLOR); + if(!SetConsoleTextAttribute(handle, RESET_COLOR)) + FMT_THROW(GetLastError(), "cannot set console color"); #else std::fputs(RESET_COLOR, stdout); #endif diff --git a/format.h b/format.h index 1e78f8dd..0af01439 100644 --- a/format.h +++ b/format.h @@ -40,15 +40,6 @@ #include #include -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN -# ifdef __MINGW32__ -# include -# endif -# include -# undef ERROR -#endif - #if _SECURE_SCL # include #endif @@ -2163,21 +2154,7 @@ void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT(true); #endif -#ifdef _WIN32 - enum Color - { - BLACK = 0, - RED = FOREGROUND_RED | FOREGROUND_INTENSITY, - GREEN = FOREGROUND_GREEN | FOREGROUND_INTENSITY, - YELLOW = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY, - BLUE = FOREGROUND_BLUE | FOREGROUND_INTENSITY, - MAGENTA = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY, - CYAN = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE, - WHITE = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY - }; -#else - enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; -#endif +enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; /** Formats a string and prints it to stdout using ANSI escape sequences diff --git a/test/format-test.cc b/test/format-test.cc index d1f4f074..e8f968b9 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1371,8 +1371,15 @@ TEST(FormatTest, Print) { #if FMT_USE_FILE_DESCRIPTORS TEST(FormatTest, PrintColored) { +#if _WIN32 EXPECT_WRITE(stdout, fmt::print_colored(fmt::RED, "Hello, {}!\n", "world"), - "\x1b[31mHello, world!\n\x1b[0m"); + "Hello, world!\n"); + EXPECT_WRITE(stdout, fmt::print_colored(static_cast(29673), + "Hello, {}!\n", "world"), "Hello, world!\n"); +#else + EXPECT_WRITE(stdout, fmt::print_colored(fmt::RED, "Hello, {}!\n", "world"), + "\x1b[31mHello, world!\n\x1b[0m"); +#endif } #endif From 4806f754697ecf2a0e73f52b2e35058208becdab Mon Sep 17 00:00:00 2001 From: Ryuuke Date: Sun, 8 Feb 2015 16:14:46 +0000 Subject: [PATCH 4/5] remove unused define --- format.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/format.cc b/format.cc index 07e630d5..d64861aa 100644 --- a/format.cc +++ b/format.cc @@ -36,12 +36,10 @@ #include #ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN # ifdef __MINGW32__ # include # endif # include -# undef ERROR #endif using fmt::internal::Arg; From bc78ca42a96a03269d6371a597fb0d47f118d2d6 Mon Sep 17 00:00:00 2001 From: Ryuuke Date: Sun, 8 Feb 2015 23:10:13 +0000 Subject: [PATCH 5/5] remove global variables --- format.cc | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/format.cc b/format.cc index d64861aa..c4a00a14 100644 --- a/format.cc +++ b/format.cc @@ -131,8 +131,6 @@ struct IntChecker { FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE, FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY }; - WORD RESET_COLOR = 0; - bool reset_color_flag = false; #else const char RESET_COLOR[] = "\x1b[0m"; #endif @@ -1115,19 +1113,16 @@ FMT_FUNC void fmt::print(std::ostream &os, StringRef format_str, ArgList args) { FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) { #ifdef _WIN32 - HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); - if (handle == INVALID_HANDLE_VALUE) - FMT_THROW(GetLastError(), "cannot get output handle"); - if (!reset_color_flag) { - CONSOLE_SCREEN_BUFFER_INFO infoCon; - if (!GetConsoleScreenBufferInfo(handle, &infoCon)) - FMT_THROW(GetLastError(), "cannot get console informations"); - RESET_COLOR = infoCon.wAttributes; - reset_color_flag = true; - } - WORD color = static_cast(c) >= ARRAYSIZE(win32_colors) ? RESET_COLOR : win32_colors[c]; - if (!SetConsoleTextAttribute(handle, color)) - FMT_THROW(GetLastError(), "cannot set console color"); + HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); + if(handle == INVALID_HANDLE_VALUE) + FMT_THROW(GetLastError(), "cannot get output handle"); + CONSOLE_SCREEN_BUFFER_INFO infoCon; + if(!GetConsoleScreenBufferInfo(handle, &infoCon)) + FMT_THROW(GetLastError(), "cannot get console informations"); + WORD reset_color = infoCon.wAttributes; + WORD color = static_cast(c) >= ARRAYSIZE(win32_colors) ? reset_color : win32_colors[c]; + if(!SetConsoleTextAttribute(handle, color)) + FMT_THROW(GetLastError(), "cannot set console color"); #else char escape[] = "\x1b[30m"; escape[3] = '0' + static_cast(c); @@ -1135,7 +1130,7 @@ FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) { #endif print(format, args); #ifdef _WIN32 - if(!SetConsoleTextAttribute(handle, RESET_COLOR)) + if(!SetConsoleTextAttribute(handle, reset_color)) FMT_THROW(GetLastError(), "cannot set console color"); #else std::fputs(RESET_COLOR, stdout);