1 #pragma once
2 #include <plog/Appenders/ConsoleAppender.h>
3 #include <plog/WinApi.h>
4 
5 namespace plog
6 {
7     template<class Formatter>
8     class ColorConsoleAppender : public ConsoleAppender<Formatter>
9     {
10     public:
11 #ifdef _WIN32
ColorConsoleAppender()12         ColorConsoleAppender() : m_originalAttr()
13         {
14             if (this->m_isatty)
15             {
16                 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
17                 GetConsoleScreenBufferInfo(this->m_stdoutHandle, &csbiInfo);
18 
19                 m_originalAttr = csbiInfo.wAttributes;
20             }
21         }
22 #else
23         ColorConsoleAppender() {}
24 #endif
25 
write(const Record & record)26         virtual void write(const Record& record)
27         {
28             util::nstring str = Formatter::format(record);
29             util::MutexLock lock(this->m_mutex);
30 
31             setColor(record.getSeverity());
32             this->writestr(str);
33             resetColor();
34         }
35 
36     private:
setColor(Severity severity)37         void setColor(Severity severity)
38         {
39             if (this->m_isatty)
40             {
41                 switch (severity)
42                 {
43 #ifdef _WIN32
44                 case fatal:
45                     SetConsoleTextAttribute(this->m_stdoutHandle, foreground::kRed | foreground::kGreen | foreground::kBlue | foreground::kIntensity | background::kRed); // white on red background
46                     break;
47 
48                 case error:
49                     SetConsoleTextAttribute(this->m_stdoutHandle, static_cast<WORD>(foreground::kRed | foreground::kIntensity | (m_originalAttr & 0xf0))); // red
50                     break;
51 
52                 case warning:
53                     SetConsoleTextAttribute(this->m_stdoutHandle, static_cast<WORD>(foreground::kRed | foreground::kGreen | foreground::kIntensity | (m_originalAttr & 0xf0))); // yellow
54                     break;
55 
56                 case debug:
57                 case verbose:
58                     SetConsoleTextAttribute(this->m_stdoutHandle, static_cast<WORD>(foreground::kGreen | foreground::kBlue | foreground::kIntensity | (m_originalAttr & 0xf0))); // cyan
59                     break;
60 #else
61                 case fatal:
62                     std::cout << "\x1B[97m\x1B[41m"; // white on red background
63                     break;
64 
65                 case error:
66                     std::cout << "\x1B[91m"; // red
67                     break;
68 
69                 case warning:
70                     std::cout << "\x1B[93m"; // yellow
71                     break;
72 
73                 case debug:
74                 case verbose:
75                     std::cout << "\x1B[96m"; // cyan
76                     break;
77 #endif
78                 default:
79                     break;
80                 }
81             }
82         }
83 
resetColor()84         void resetColor()
85         {
86             if (this->m_isatty)
87             {
88 #ifdef _WIN32
89                 SetConsoleTextAttribute(this->m_stdoutHandle, m_originalAttr);
90 #else
91                 std::cout << "\x1B[0m\x1B[0K";
92 #endif
93             }
94         }
95 
96     private:
97 #ifdef _WIN32
98         WORD   m_originalAttr;
99 #endif
100     };
101 }
102