Ookii.CommandLine for C++  2.0.0
vt_helper.h
Go to the documentation of this file.
1 #ifndef OOKII_VT_HELPER_H_
4 #define OOKII_VT_HELPER_H_
5 
6 #pragma once
7 
8 #include "console_helper.h"
9 #include "scope_helper.h"
10 #include <string_view>
11 #include <locale>
12 
14 namespace ookii::vt
15 {
16  namespace details
17  {
18  template<typename CharType, typename Traits>
19  struct vt_helper
20  {
21  static constexpr CharType c_escape = '\x1b';
22 
23  static CharType *find_csi_end(CharType *begin, CharType *end, const std::locale &loc)
24  {
25  for (auto current = begin; current < end; ++current)
26  {
27  auto ch = *current;
28  if (!std::isdigit(ch, loc) && !Traits::eq(ch, ';') && !Traits::eq(ch, ' '))
29  {
30  return current;
31  }
32  }
33 
34  return nullptr;
35  }
36 
37  static CharType *find_osc_end(CharType *begin, CharType *end)
38  {
39  bool has_escape = false;
40  for (auto current = begin; current < end; ++current)
41  {
42  auto ch = *current;
43  if (Traits::eq(ch, 0x7))
44  {
45  return current;
46  }
47 
48  if (has_escape)
49  {
50  if (Traits::eq(ch, '\\'))
51  {
52  return current;
53  }
54 
55  // Invalid next character, just pretend the escape character was the end.
56  return current - 1;
57  }
58 
59  if (Traits::eq(ch, c_escape))
60  {
61  has_escape = true;
62  }
63  }
64 
65  return nullptr;
66  }
67 
68  static CharType *find_sequence_end(CharType *begin, CharType *end, const std::locale &loc)
69  {
70  if (begin == end)
71  {
72  return begin;
73  }
74 
75  switch (*begin)
76  {
77  case '[':
78  return find_csi_end(begin + 1, end, loc);
79 
80  case ']':
81  return find_osc_end(begin + 1, end);
82 
83  case '(':
84  ++begin;
85  if (begin != end)
86  {
87  return begin;
88  }
89  else
90  {
91  return nullptr;
92  }
93 
94  default:
95  return begin;
96  }
97  }
98  };
99  }
100 
102  namespace text_format
103  {
104 
106  constexpr const char *default_format = "\x1b[0m";
107 
109  constexpr const char *bold_bright = "\x1b[1m";
110 
112  constexpr const char *no_bold_bright = "\x1b[22m";
113 
115  constexpr const char *underline = "\x1b[4m";
116 
118  constexpr const char *no_underline = "\x1b[24m";
119 
121  constexpr const char *negative = "\x1b[7m";
122 
124  constexpr const char *positive = "\x1b[27m";
125 
127  constexpr const char *foreground_black = "\x1b[30m";
128 
130  constexpr const char *foreground_red = "\x1b[31m";
131 
133  constexpr const char *foreground_green = "\x1b[32m";
134 
136  constexpr const char *foreground_yellow = "\x1b[33m";
137 
139  constexpr const char *foreground_blue = "\x1b[34m";
140 
142  constexpr const char *foreground_magenta = "\x1b[35m";
143 
145  constexpr const char *foreground_cyan = "\x1b[36m";
146 
148  constexpr const char *foreground_white = "\x1b[37m";
149 
151  constexpr const char *foreground_default = "\x1b[39m";
152 
154  constexpr const char *background_black = "\x1b[40m";
155 
157  constexpr const char *background_red = "\x1b[41m";
158 
160  constexpr const char *background_green = "\x1b[42m";
161 
163  constexpr const char *background_yellow = "\x1b[43m";
164 
166  constexpr const char *background_blue = "\x1b[44m";
167 
169  constexpr const char *background_magenta = "\x1b[45m";
170 
172  constexpr const char *background_cyan = "\x1b[46m";
173 
175  constexpr const char *background_white = "\x1b[47m";
176 
178  constexpr const char *background_default = "\x1b[49m";
179 
181  constexpr const char *bright_foreground_black = "\x1b[90m";
182 
184  constexpr const char *bright_foreground_red = "\x1b[91m";
185 
187  constexpr const char *bright_foreground_green = "\x1b[92m";
188 
190  constexpr const char *bright_foreground_yellow = "\x1b[93m";
191 
193  constexpr const char *bright_foreground_blue = "\x1b[94m";
194 
196  constexpr const char *bright_foreground_magenta = "\x1b[95m";
197 
199  constexpr const char *bright_foreground_cyan = "\x1b[96m";
200 
202  constexpr const char *bright_foreground_white = "\x1b[97m";
203 
205  constexpr const char *bright_background_black = "\x1b[100m";
206 
208  constexpr const char *bright_background_red = "\x1b[101m";
209 
211  constexpr const char *bright_background_green = "\x1b[102m";
212 
214  constexpr const char *bright_background_yellow = "\x1b[103m";
215 
217  constexpr const char *bright_background_blue = "\x1b[104m";
218 
220  constexpr const char *bright_background_magenta = "\x1b[105m";
221 
223  constexpr const char *bright_background_cyan = "\x1b[106m";
224 
226  constexpr const char *bright_background_white = "\x1b[107m";
227 
228 
238  template<typename CharType = ookii::details::default_char_type>
239  inline std::basic_string<CharType> get_extended_color(int red, int green, int blue, bool foreground = true)
240  {
241  static constexpr auto format_string = literal_cast<CharType>("\x1b[{};2;{};{};{}m");
242  return OOKII_FMT_NS format(format_string.data(), (foreground ? 38 : 48), red, green, blue);
243  }
244  }
245 
253  class [[nodiscard]] virtual_terminal_support
254  {
255  public:
261 
263  virtual_terminal_support &operator=(const virtual_terminal_support &) = delete;
264 
269 
270  ~virtual_terminal_support() noexcept
271  {
272  reset();
273  }
274 
289  {
290  if ((stream != standard_stream::output && stream != standard_stream::error) ||
291  !ookii::details::is_console(stream))
292  {
293  return {};
294  }
295 
296  bool has_term = false;
297 #ifdef _WIN32
298  char term[10]{};
299  size_t required;
300  // If the buffer is too small, it can't be equal to "dumb", so we don't care.
301  getenv_s(&required, term, "TERM");
302  has_term = required > 0;
303 #else
304  auto term = getenv("TERM");
305  has_term = term != nullptr;
306 #endif
307 
308  // If "TERM=dumb" is set, assume no support.
309  if (has_term && strcmp(term, "dumb") == 0)
310  {
311  return {};
312  }
313 
314 #ifndef _WIN32
315  // Except on Windows, TERM not set is assumed to mean no support.
316  if (!has_term)
317  {
318  return {};
319  }
320 #endif
321 
322  return {stream, set_console_vt_support(stream, true)};
323  }
324 
338  {
339  bool has_env;
340 #ifdef _WIN32
341  size_t required;
342  getenv_s(&required, nullptr, 0, "NO_COLOR");
343  has_env = required > 0;
344 #else
345  has_env = getenv("NO_COLOR") != nullptr;
346 #endif
347  if (has_env)
348  {
349  return {stream, vt_result::failed};
350  }
351 
352  return enable(stream);
353  }
354 
357  bool is_supported() const noexcept
358  {
359  return _result != vt_result::failed;
360  }
361 
364  operator bool() const noexcept
365  {
366  return is_supported();
367  }
368 
372  void reset() noexcept
373  {
374  if (_result == vt_result::success)
375  {
376  set_console_vt_support(_stream, false);
377 
378  // Set to failed to reset() again won't do anything and is_supported will return
379  // false.
380  _result = vt_result::failed;
381  }
382  }
383 
384  private:
385  virtual_terminal_support(standard_stream stream, vt_result result) noexcept
386  : _stream{stream},
387  _result{result}
388  {
389  }
390 
391  standard_stream _stream;
392  vt_result _result;
393  };
394 }
395 
396 #endif
Handles the lifetime of virtual terminal support.
Definition: vt_helper.h:254
static virtual_terminal_support enable_color(standard_stream stream)
Enables color support using virtual terminal sequences for the console attached to the specified stre...
Definition: vt_helper.h:337
static virtual_terminal_support enable(standard_stream stream)
Enables virtual terminal sequences for the console attached to the specified stream.
Definition: vt_helper.h:288
virtual_terminal_support(virtual_terminal_support &&)=default
Move constructor for virtual_terminal_support.
bool is_supported() const noexcept
Gets a value that indicates whether the stream supports virtual terminal sequences.
Definition: vt_helper.h:357
virtual_terminal_support & operator=(virtual_terminal_support &&)=default
Move assignment operator for virtual_terminal_support.
void reset() noexcept
Restores the console mode to its previous value, if it had been changed.
Definition: vt_helper.h:372
virtual_terminal_support()=default
Initializes a new instance of the virtual_terminal_support class.
Provides helpers for using the console.
#define OOKII_FMT_NS
The namespace which contains the formatting library.
Definition: format_helper.h:34
constexpr const char * bold_bright
Applies the brightness/intensity flag to the foreground color.
Definition: vt_helper.h:109
constexpr const char * negative
Swaps foreground and background colors.
Definition: vt_helper.h:121
constexpr const char * foreground_white
Sets the foreground color to white.
Definition: vt_helper.h:148
constexpr const char * bright_foreground_cyan
Sets the foreground color to bright cyan.
Definition: vt_helper.h:199
constexpr const char * background_blue
Sets the background color to blue.
Definition: vt_helper.h:166
constexpr const char * no_underline
Removes underline.
Definition: vt_helper.h:118
constexpr const char * bright_foreground_magenta
Sets the foreground color to bright magenta.
Definition: vt_helper.h:196
constexpr const char * bright_foreground_blue
Sets the foreground color to bright blue.
Definition: vt_helper.h:193
constexpr const char * background_white
Sets the background color to white.
Definition: vt_helper.h:175
constexpr const char * foreground_blue
Sets the foreground color to blue.
Definition: vt_helper.h:139
constexpr const char * foreground_default
Sets the foreground color to default.
Definition: vt_helper.h:151
constexpr const char * bright_background_blue
Sets the background color to bright blue.
Definition: vt_helper.h:217
constexpr const char * default_format
Resets the text format to the settings before modification.
Definition: vt_helper.h:106
constexpr const char * bright_foreground_yellow
Sets the foreground color to bright yellow.
Definition: vt_helper.h:190
constexpr const char * bright_background_white
Sets the background color to bright white.
Definition: vt_helper.h:226
constexpr const char * positive
Returns foreground and background colors to normal.
Definition: vt_helper.h:124
constexpr const char * bright_foreground_white
Sets the foreground color to bright white.
Definition: vt_helper.h:202
constexpr const char * background_default
Sets the background color to default.
Definition: vt_helper.h:178
constexpr const char * bright_background_black
Sets the background color to bright black.
Definition: vt_helper.h:205
constexpr const char * foreground_cyan
Sets the foreground color to cyan.
Definition: vt_helper.h:145
constexpr const char * bright_background_red
Sets the background color to bright red.
Definition: vt_helper.h:208
constexpr const char * foreground_magenta
Sets the foreground color to magenta.
Definition: vt_helper.h:142
constexpr const char * background_magenta
Sets the background color to magenta.
Definition: vt_helper.h:169
constexpr const char * bright_foreground_green
Sets the foreground color to bright green.
Definition: vt_helper.h:187
std::basic_string< CharType > get_extended_color(int red, int green, int blue, bool foreground=true)
Returns the virtual terminal sequence to the foreground or background color to an RGB color.
Definition: vt_helper.h:239
constexpr const char * foreground_black
Sets the foreground color to black.
Definition: vt_helper.h:127
constexpr const char * bright_background_yellow
Sets the background color to bright yellow.
Definition: vt_helper.h:214
constexpr const char * background_yellow
Sets the background color to yellow.
Definition: vt_helper.h:163
constexpr const char * foreground_red
Sets the foreground color to red.
Definition: vt_helper.h:130
constexpr const char * foreground_green
Sets the foreground color to green.
Definition: vt_helper.h:133
constexpr const char * underline
Adds underline.
Definition: vt_helper.h:115
constexpr const char * bright_background_cyan
Sets the background color to bright cyan.
Definition: vt_helper.h:223
constexpr const char * bright_foreground_red
Sets the foreground color to bright red.
Definition: vt_helper.h:184
constexpr const char * background_green
Sets the background color to green.
Definition: vt_helper.h:160
constexpr const char * bright_background_green
Sets the background color to bright green.
Definition: vt_helper.h:211
constexpr const char * background_black
Sets the background color to black.
Definition: vt_helper.h:154
constexpr const char * bright_background_magenta
Sets the background color to bright magenta.
Definition: vt_helper.h:220
constexpr const char * bright_foreground_black
Sets the foreground color to bright black.
Definition: vt_helper.h:181
constexpr const char * background_red
Sets the background color to red.
Definition: vt_helper.h:157
constexpr const char * no_bold_bright
Removes the brightness/intensity flag to the foreground color.
Definition: vt_helper.h:112
constexpr const char * foreground_yellow
Sets the foreground color to yellow.
Definition: vt_helper.h:136
constexpr const char * background_cyan
Sets the background color to cyan.
Definition: vt_helper.h:172
Namespace containing functions and types for working with virtual terminal sequences.
Definition: vt_helper.h:15
standard_stream
Represents one of the standard console streams.
Definition: console_helper.h:32
@ output
The standard output stream.
@ error
The standard error stream.
vt_result
Indicates the result of the set_console_vt_support operation.
Definition: console_helper.h:162
@ success
Virtual terminal sequences were successfully enabled.
@ failed
Virtual terminal sequences could not be enabled.
vt_result set_console_vt_support([[maybe_unused]] standard_stream stream, [[maybe_unused]] bool enable) noexcept
Enables or disables console support for virtual terminal sequences.
Definition: console_helper.h:223
Provides RAII types.