16enum class color : uint32_t {
17 alice_blue = 0xF0F8FF,
18 antique_white = 0xFAEBD7,
20 aquamarine = 0x7FFFD4,
25 blanched_almond = 0xFFEBCD,
27 blue_violet = 0x8A2BE2,
29 burly_wood = 0xDEB887,
30 cadet_blue = 0x5F9EA0,
31 chartreuse = 0x7FFF00,
34 cornflower_blue = 0x6495ED,
40 dark_golden_rod = 0xB8860B,
42 dark_green = 0x006400,
43 dark_khaki = 0xBDB76B,
44 dark_magenta = 0x8B008B,
45 dark_olive_green = 0x556B2F,
46 dark_orange = 0xFF8C00,
47 dark_orchid = 0x9932CC,
49 dark_salmon = 0xE9967A,
50 dark_sea_green = 0x8FBC8F,
51 dark_slate_blue = 0x483D8B,
52 dark_slate_gray = 0x2F4F4F,
53 dark_turquoise = 0x00CED1,
54 dark_violet = 0x9400D3,
56 deep_sky_blue = 0x00BFFF,
58 dodger_blue = 0x1E90FF,
59 fire_brick = 0xB22222,
60 floral_white = 0xFFFAF0,
61 forest_green = 0x228B22,
64 ghost_white = 0xF8F8FF,
66 golden_rod = 0xDAA520,
69 green_yellow = 0xADFF2F,
72 indian_red = 0xCD5C5C,
77 lavender_blush = 0xFFF0F5,
78 lawn_green = 0x7CFC00,
79 lemon_chiffon = 0xFFFACD,
80 light_blue = 0xADD8E6,
81 light_coral = 0xF08080,
82 light_cyan = 0xE0FFFF,
83 light_golden_rod_yellow = 0xFAFAD2,
84 light_gray = 0xD3D3D3,
85 light_green = 0x90EE90,
86 light_pink = 0xFFB6C1,
87 light_salmon = 0xFFA07A,
88 light_sea_green = 0x20B2AA,
89 light_sky_blue = 0x87CEFA,
90 light_slate_gray = 0x778899,
91 light_steel_blue = 0xB0C4DE,
92 light_yellow = 0xFFFFE0,
94 lime_green = 0x32CD32,
98 medium_aquamarine = 0x66CDAA,
99 medium_blue = 0x0000CD,
100 medium_orchid = 0xBA55D3,
101 medium_purple = 0x9370DB,
102 medium_sea_green = 0x3CB371,
103 medium_slate_blue = 0x7B68EE,
104 medium_spring_green = 0x00FA9A,
105 medium_turquoise = 0x48D1CC,
106 medium_violet_red = 0xC71585,
107 midnight_blue = 0x191970,
108 mint_cream = 0xF5FFFA,
109 misty_rose = 0xFFE4E1,
111 navajo_white = 0xFFDEAD,
115 olive_drab = 0x6B8E23,
117 orange_red = 0xFF4500,
119 pale_golden_rod = 0xEEE8AA,
120 pale_green = 0x98FB98,
121 pale_turquoise = 0xAFEEEE,
122 pale_violet_red = 0xDB7093,
123 papaya_whip = 0xFFEFD5,
124 peach_puff = 0xFFDAB9,
128 powder_blue = 0xB0E0E6,
130 rebecca_purple = 0x663399,
132 rosy_brown = 0xBC8F8F,
133 royal_blue = 0x4169E1,
134 saddle_brown = 0x8B4513,
136 sandy_brown = 0xF4A460,
137 sea_green = 0x2E8B57,
138 sea_shell = 0xFFF5EE,
142 slate_blue = 0x6A5ACD,
143 slate_gray = 0x708090,
145 spring_green = 0x00FF7F,
146 steel_blue = 0x4682B4,
151 turquoise = 0x40E0D0,
155 white_smoke = 0xF5F5F5,
157 yellow_green = 0x9ACD32
160enum class terminal_color : uint8_t {
179enum class emphasis : uint8_t {
187 strikethrough = 1 << 7,
193 FMT_CONSTEXPR rgb() : r(0), g(0), b(0) {}
194 FMT_CONSTEXPR rgb(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {}
195 FMT_CONSTEXPR rgb(uint32_t hex)
196 : r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b(hex & 0xFF) {}
197 FMT_CONSTEXPR rgb(color hex)
198 : r((uint32_t(hex) >> 16) & 0xFF),
199 g((uint32_t(hex) >> 8) & 0xFF),
200 b(uint32_t(hex) & 0xFF) {}
210 FMT_CONSTEXPR color_type() noexcept : is_rgb(), value{} {}
211 FMT_CONSTEXPR color_type(color rgb_color) noexcept : is_rgb(
true), value{} {
212 value.rgb_color =
static_cast<uint32_t
>(rgb_color);
214 FMT_CONSTEXPR color_type(
rgb rgb_color) noexcept : is_rgb(
true), value{} {
215 value.rgb_color = (
static_cast<uint32_t
>(rgb_color.r) << 16) |
216 (
static_cast<uint32_t
>(rgb_color.g) << 8) | rgb_color.b;
218 FMT_CONSTEXPR color_type(terminal_color term_color) noexcept
219 : is_rgb(), value{} {
220 value.term_color =
static_cast<uint8_t
>(term_color);
233 FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept
234 : set_foreground_color(), set_background_color(), ems(em) {}
236 FMT_CONSTEXPR
auto operator|=(
const text_style& rhs) -> text_style& {
237 if (!set_foreground_color) {
238 set_foreground_color = rhs.set_foreground_color;
239 foreground_color = rhs.foreground_color;
240 }
else if (rhs.set_foreground_color) {
241 if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
242 report_error(
"can't OR a terminal color");
243 foreground_color.value.rgb_color |= rhs.foreground_color.value.rgb_color;
246 if (!set_background_color) {
247 set_background_color = rhs.set_background_color;
248 background_color = rhs.background_color;
249 }
else if (rhs.set_background_color) {
250 if (!background_color.is_rgb || !rhs.background_color.is_rgb)
251 report_error(
"can't OR a terminal color");
252 background_color.value.rgb_color |= rhs.background_color.value.rgb_color;
255 ems =
static_cast<emphasis
>(
static_cast<uint8_t
>(ems) |
256 static_cast<uint8_t
>(rhs.ems));
260 friend FMT_CONSTEXPR
auto operator|(text_style lhs,
const text_style& rhs)
265 FMT_CONSTEXPR
auto has_foreground()
const noexcept ->
bool {
266 return set_foreground_color;
268 FMT_CONSTEXPR
auto has_background()
const noexcept ->
bool {
269 return set_background_color;
271 FMT_CONSTEXPR
auto has_emphasis()
const noexcept ->
bool {
272 return static_cast<uint8_t
>(ems) != 0;
275 FMT_ASSERT(has_foreground(),
"no foreground specified for this style");
276 return foreground_color;
279 FMT_ASSERT(has_background(),
"no background specified for this style");
280 return background_color;
282 FMT_CONSTEXPR
auto get_emphasis()
const noexcept -> emphasis {
283 FMT_ASSERT(has_emphasis(),
"no emphasis specified for this style");
288 FMT_CONSTEXPR text_style(
bool is_foreground,
290 : set_foreground_color(), set_background_color(), ems() {
292 foreground_color = text_color;
293 set_foreground_color =
true;
295 background_color = text_color;
296 set_background_color =
true;
308 bool set_foreground_color;
309 bool set_background_color;
316 return text_style(
true, foreground);
322 return text_style(
false, background);
325FMT_CONSTEXPR
inline auto operator|(emphasis lhs, emphasis rhs)
noexcept
332template <
typename Char>
struct ansi_color_escape {
334 const char* esc)
noexcept {
337 if (!text_color.is_rgb) {
338 bool is_background = esc == string_view(
"\x1b[48;2;");
339 uint32_t
value = text_color.value.term_color;
342 if (is_background)
value += 10u;
345 buffer[index++] =
static_cast<Char
>(
'\x1b');
346 buffer[index++] =
static_cast<Char
>(
'[');
349 buffer[index++] =
static_cast<Char
>(
'1');
352 buffer[index++] =
static_cast<Char
>(
'0' +
value / 10u);
353 buffer[index++] =
static_cast<Char
>(
'0' +
value % 10u);
355 buffer[index++] =
static_cast<Char
>(
'm');
356 buffer[index++] =
static_cast<Char
>(
'\0');
360 for (
int i = 0; i < 7; i++) {
361 buffer[i] =
static_cast<Char
>(esc[i]);
363 rgb color(text_color.value.rgb_color);
364 to_esc(color.r, buffer + 7,
';');
365 to_esc(color.g, buffer + 11,
';');
366 to_esc(color.b, buffer + 15,
'm');
367 buffer[19] =
static_cast<Char
>(0);
369 FMT_CONSTEXPR ansi_color_escape(emphasis em)
noexcept {
370 uint8_t em_codes[num_emphases] = {};
371 if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1;
372 if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2;
373 if (has_emphasis(em, emphasis::italic)) em_codes[2] = 3;
374 if (has_emphasis(em, emphasis::underline)) em_codes[3] = 4;
375 if (has_emphasis(em, emphasis::blink)) em_codes[4] = 5;
376 if (has_emphasis(em, emphasis::reverse)) em_codes[5] = 7;
377 if (has_emphasis(em, emphasis::conceal)) em_codes[6] = 8;
378 if (has_emphasis(em, emphasis::strikethrough)) em_codes[7] = 9;
381 for (
size_t i = 0; i < num_emphases; ++i) {
382 if (!em_codes[i])
continue;
383 buffer[index++] =
static_cast<Char
>(
'\x1b');
384 buffer[index++] =
static_cast<Char
>(
'[');
385 buffer[index++] =
static_cast<Char
>(
'0' + em_codes[i]);
386 buffer[index++] =
static_cast<Char
>(
'm');
388 buffer[index++] =
static_cast<Char
>(0);
390 FMT_CONSTEXPR
operator const Char*()
const noexcept {
return buffer; }
392 FMT_CONSTEXPR
auto begin()
const noexcept ->
const Char* {
return buffer; }
393 FMT_CONSTEXPR20
auto end()
const noexcept ->
const Char* {
398 static constexpr size_t num_emphases = 8;
399 Char buffer[7u + 3u * num_emphases + 1u];
401 static FMT_CONSTEXPR
void to_esc(uint8_t c, Char* out,
402 char delimiter)
noexcept {
403 out[0] =
static_cast<Char
>(
'0' + c / 100);
404 out[1] =
static_cast<Char
>(
'0' + c / 10 % 10);
405 out[2] =
static_cast<Char
>(
'0' + c % 10);
406 out[3] =
static_cast<Char
>(delimiter);
408 static FMT_CONSTEXPR
auto has_emphasis(emphasis em, emphasis mask)
noexcept
410 return static_cast<uint8_t
>(em) &
static_cast<uint8_t
>(mask);
414template <
typename Char>
420template <
typename Char>
422 -> ansi_color_escape<Char> {
423 return ansi_color_escape<Char>(background,
"\x1b[48;2;");
426template <
typename Char>
427FMT_CONSTEXPR
auto make_emphasis(emphasis em)
noexcept
433 auto reset_color = string_view(
"\x1b[0m");
440 styled_arg(
const T& v,
text_style s) : value(v), style(s) {}
443template <
typename Char>
447 bool has_style =
false;
448 if (ts.has_emphasis()) {
450 auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
451 buf.
append(emphasis.begin(), emphasis.end());
453 if (ts.has_foreground()) {
455 auto foreground = detail::make_foreground_color<Char>(ts.get_foreground());
456 buf.
append(foreground.begin(), foreground.end());
458 if (ts.has_background()) {
460 auto background = detail::make_background_color<Char>(ts.get_background());
461 buf.
append(background.begin(), background.end());
463 detail::vformat_to(buf, format_str, args, {});
464 if (has_style) detail::reset_color<Char>(buf);
469inline void vprint(FILE* f,
const text_style& ts, string_view fmt,
471 auto buf = memory_buffer();
472 detail::vformat_to(buf, ts, fmt, args);
473 print(f, FMT_STRING(
"{}"), string_view(buf.begin(), buf.
size()));
485template <
typename... T>
486void print(FILE* f,
const text_style& ts, format_string<T...> fmt,
488 vprint(f, ts, fmt, fmt::make_format_args(args...));
500template <
typename... T>
501void print(
const text_style& ts, format_string<T...> fmt, T&&... args) {
502 return print(stdout, ts, fmt, std::forward<T>(args)...);
505inline auto vformat(
const text_style& ts, string_view fmt, format_args args)
507 auto buf = memory_buffer();
508 detail::vformat_to(buf, ts, fmt, args);
509 return fmt::to_string(buf);
524template <
typename... T>
525inline auto format(
const text_style& ts, format_string<T...> fmt, T&&... args)
527 return fmt::vformat(ts, fmt, fmt::make_format_args(args...));
531template <
typename OutputIt,
533auto vformat_to(OutputIt out,
const text_style& ts, string_view fmt,
534 format_args args) -> OutputIt {
535 auto&& buf = detail::get_buffer<char>(out);
536 detail::vformat_to(buf, ts, fmt, args);
537 return detail::get_iterator(buf, out);
550template <
typename OutputIt,
typename... T,
552inline auto format_to(OutputIt out,
const text_style& ts,
553 format_string<T...> fmt, T&&... args) -> OutputIt {
554 return vformat_to(out, ts, fmt, fmt::make_format_args(args...));
557template <
typename T,
typename Char>
558struct formatter<detail::styled_arg<T>, Char> : formatter<T, Char> {
559 template <
typename FormatContext>
561 ->
decltype(ctx.out()) {
562 const auto& ts = arg.style;
563 const auto& value = arg.value;
564 auto out = ctx.out();
566 bool has_style =
false;
567 if (ts.has_emphasis()) {
569 auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
570 out = std::copy(emphasis.begin(), emphasis.end(), out);
572 if (ts.has_foreground()) {
575 detail::make_foreground_color<Char>(ts.get_foreground());
576 out = std::copy(foreground.begin(), foreground.end(), out);
578 if (ts.has_background()) {
581 detail::make_background_color<Char>(ts.get_background());
582 out = std::copy(background.begin(), background.end(), out);
584 out = formatter<T, Char>::format(value, ctx);
586 auto reset_color = string_view(
"\x1b[0m");
587 out = std::copy(reset_color.begin(), reset_color.end(), out);
604FMT_CONSTEXPR
auto styled(
const T& value,
text_style ts)
constexpr auto size() const noexcept -> size_t
Returns the string size.
Definition base.h:555
constexpr auto size() const noexcept -> size_t
Returns the size of this buffer.
Definition base.h:894
void append(const U *begin, const U *end)
Appends data to the end of the buffer.
Definition base.h:927
A text style consisting of foreground and background colors and emphasis.
Definition color.h:231
friend FMT_CONSTEXPR auto fg(detail::color_type foreground) noexcept -> text_style
Creates a text style from the foreground (text) color.
Definition color.h:314
friend FMT_CONSTEXPR auto bg(detail::color_type background) noexcept -> text_style
Creates a text style from the background color.
Definition color.h:320