1 #include "./ansiescapecodes.h"
2 
3 namespace CppUtilities {
4 
5 /*!
6  * \brief Encapsulates functions for formatted terminal output using ANSI escape codes.
7  */
8 namespace EscapeCodes {
9 
10 /*!
11  * \brief Controls whether the functions inside the EscapeCodes namespace actually make use of escape codes.
12  *
13  * This allows to disable use of escape codes when not appropriate.
14  *
15  * The default value can be configured at build time by setting the CMake variable ENABLE_ESCAPE_CODES_BY_DEFAULT.
16  * The "default for the default" is true.
17  * However, the default is overridden with the value of the environment variable ENABLE_ESCAPE_CODES when instantiating
18  * a NoColorArgument (if ENABLE_ESCAPE_CODES is present).
19  *
20  * \sa NoColorArgument
21  */
22 bool enabled =
23 #ifdef CPP_UTILITIES_ESCAPE_CODES_ENABLED_BY_DEFAULT
24     true
25 #else
26     false
27 #endif
28     ;
29 
30 /*!
31  * \brief Prints the specified \a phrase in a formatted manner using ANSI escape codes.
32  */
operator <<(std::ostream & stream,Phrases phrase)33 std::ostream &operator<<(std::ostream &stream, Phrases phrase)
34 {
35     switch (phrase) {
36     case Phrases::Error:
37         setStyle(stream, Color::Red, ColorContext::Foreground, TextAttribute::Bold);
38         stream << "Error: ";
39         setStyle(stream, TextAttribute::Reset);
40         setStyle(stream, TextAttribute::Bold);
41         break;
42     case Phrases::Warning:
43         setStyle(stream, Color::Yellow, ColorContext::Foreground, TextAttribute::Bold);
44         stream << "Warning: ";
45         setStyle(stream, TextAttribute::Reset);
46         setStyle(stream, TextAttribute::Bold);
47         break;
48     case Phrases::End:
49         setStyle(stream, TextAttribute::Reset);
50         stream << '\n';
51         break;
52     case Phrases::PlainMessage:
53         stream << "    ";
54         setStyle(stream, TextAttribute::Reset);
55         setStyle(stream, TextAttribute::Bold);
56         break;
57     case Phrases::SuccessMessage:
58         setStyle(stream, Color::Green, ColorContext::Foreground, TextAttribute::Bold);
59         stream << "==> ";
60         setStyle(stream, TextAttribute::Reset);
61         setStyle(stream, TextAttribute::Bold);
62         break;
63     case Phrases::SubMessage:
64         setStyle(stream, Color::Green, ColorContext::Foreground, TextAttribute::Bold);
65         stream << "  -> ";
66         setStyle(stream, TextAttribute::Reset);
67         setStyle(stream, TextAttribute::Bold);
68         break;
69     case Phrases::ErrorMessage:
70         setStyle(stream, Color::Red, ColorContext::Foreground, TextAttribute::Bold);
71         stream << "==> ERROR: ";
72         setStyle(stream, TextAttribute::Reset);
73         setStyle(stream, TextAttribute::Bold);
74         break;
75     case Phrases::WarningMessage:
76         setStyle(stream, Color::Yellow, ColorContext::Foreground, TextAttribute::Bold);
77         stream << "==> WARNING: ";
78         setStyle(stream, TextAttribute::Reset);
79         setStyle(stream, TextAttribute::Bold);
80         break;
81     case Phrases::EndFlush:
82         setStyle(stream, TextAttribute::Reset);
83         stream << std::endl;
84         break;
85     case Phrases::Info:
86         setStyle(stream, Color::Blue, ColorContext::Foreground, TextAttribute::Bold);
87         stream << "Info: ";
88         setStyle(stream, TextAttribute::Reset);
89         setStyle(stream, TextAttribute::Bold);
90         break;
91     case Phrases::Override:
92         eraseLine(stream);
93         stream << '\r';
94         break;
95     case Phrases::SubError:
96         setStyle(stream, Color::Red, ColorContext::Foreground, TextAttribute::Bold);
97         stream << "  -> ERROR: ";
98         setStyle(stream, TextAttribute::Reset);
99         setStyle(stream, TextAttribute::Bold);
100         break;
101     case Phrases::SubWarning:
102         setStyle(stream, Color::Yellow, ColorContext::Foreground, TextAttribute::Bold);
103         stream << "  -> WARNING: ";
104         setStyle(stream, TextAttribute::Reset);
105         setStyle(stream, TextAttribute::Bold);
106         break;
107     case Phrases::InfoMessage:
108         setStyle(stream, Color::White, ColorContext::Foreground, TextAttribute::Bold);
109         stream << "==> ";
110         setStyle(stream, TextAttribute::Reset);
111         setStyle(stream, TextAttribute::Bold);
112         break;
113     }
114     return stream;
115 }
116 
117 /*!
118  * \brief Returns a string for the specified \a phrase *without* formatting.
119  */
phraseString(Phrases phrase)120 std::string_view phraseString(Phrases phrase)
121 {
122     using namespace std::string_view_literals;
123     switch (phrase) {
124     case Phrases::Error:
125         return "Error: "sv;
126     case Phrases::Warning:
127         return "Warning: "sv;
128     case Phrases::PlainMessage:
129         return "    "sv;
130     case Phrases::SuccessMessage:
131         return "==> "sv;
132     case Phrases::SubMessage:
133         return "  -> "sv;
134     case Phrases::ErrorMessage:
135         return "==> ERROR: "sv;
136     case Phrases::WarningMessage:
137         return "==> WARNING: ";
138     case Phrases::Info:
139         return "Info: "sv;
140     case Phrases::SubError:
141         return "  -> ERROR: "sv;
142     case Phrases::SubWarning:
143         return "  -> WARNING: "sv;
144     case Phrases::InfoMessage:
145         return "==> "sv;
146     case Phrases::End:
147     case Phrases::EndFlush:
148         return "\n";
149     default:
150         return std::string_view{};
151     }
152 }
153 
154 /*!
155  * \brief Returns a string for the specified \a phrase which is formatted using ANSI escape codes.
156  * \remarks This function is still experimental. It might be modified in an incompatible way or even removed
157  *          in the next minor or patch release.
158  */
formattedPhraseString(Phrases phrase)159 std::string_view formattedPhraseString(Phrases phrase)
160 {
161     if (!enabled) {
162         return phraseString(phrase);
163     }
164     using namespace std::string_view_literals;
165     switch (phrase) {
166     case Phrases::Error:
167         return "\e[1;31mError: \e[0m\e[1m"sv;
168     case Phrases::Warning:
169         return "\e[1;33mWarning: \e[0m\e[1m"sv;
170     case Phrases::PlainMessage:
171         return "    \e[0m\e[1m"sv;
172     case Phrases::SuccessMessage:
173         return "\e[1;32m==> \e[0m\e[1m"sv;
174     case Phrases::SubMessage:
175         return "\e[1;32m  -> \e[0m\e[1m"sv;
176     case Phrases::ErrorMessage:
177         return "\e[1;31m==> ERROR: \e[0m\e[1m"sv;
178     case Phrases::WarningMessage:
179         return "\e[1;33m==> WARNING: \e[0m\e[1m";
180     case Phrases::Info:
181         return "\e[1;34mInfo: \e[0m\e[1m"sv;
182     case Phrases::SubError:
183         return "\e[1;31m  -> ERROR: \e[0m\e[1m"sv;
184     case Phrases::SubWarning:
185         return "\e[1;33m  -> WARNING: \e[0m\e[1m"sv;
186     case Phrases::InfoMessage:
187         return "\e[1;37m==> \e[0m\e[1m"sv;
188     case Phrases::End:
189     case Phrases::EndFlush:
190         return "\e[0m\n";
191     default:
192         return std::string_view{};
193     }
194 }
195 
196 } // namespace EscapeCodes
197 
198 } // namespace CppUtilities
199