1 // Formatting library for C++ - color support
3 // Copyright (c) 2018 - present, Victor Zverovich and fmt contributors
4 // All rights reserved.
6 // For the license information refer to format.h.
16 enum class color
: uint32_t {
17 alice_blue
= 0xF0F8FF, // rgb(240,248,255)
18 antique_white
= 0xFAEBD7, // rgb(250,235,215)
19 aqua
= 0x00FFFF, // rgb(0,255,255)
20 aquamarine
= 0x7FFFD4, // rgb(127,255,212)
21 azure
= 0xF0FFFF, // rgb(240,255,255)
22 beige
= 0xF5F5DC, // rgb(245,245,220)
23 bisque
= 0xFFE4C4, // rgb(255,228,196)
24 black
= 0x000000, // rgb(0,0,0)
25 blanched_almond
= 0xFFEBCD, // rgb(255,235,205)
26 blue
= 0x0000FF, // rgb(0,0,255)
27 blue_violet
= 0x8A2BE2, // rgb(138,43,226)
28 brown
= 0xA52A2A, // rgb(165,42,42)
29 burly_wood
= 0xDEB887, // rgb(222,184,135)
30 cadet_blue
= 0x5F9EA0, // rgb(95,158,160)
31 chartreuse
= 0x7FFF00, // rgb(127,255,0)
32 chocolate
= 0xD2691E, // rgb(210,105,30)
33 coral
= 0xFF7F50, // rgb(255,127,80)
34 cornflower_blue
= 0x6495ED, // rgb(100,149,237)
35 cornsilk
= 0xFFF8DC, // rgb(255,248,220)
36 crimson
= 0xDC143C, // rgb(220,20,60)
37 cyan
= 0x00FFFF, // rgb(0,255,255)
38 dark_blue
= 0x00008B, // rgb(0,0,139)
39 dark_cyan
= 0x008B8B, // rgb(0,139,139)
40 dark_golden_rod
= 0xB8860B, // rgb(184,134,11)
41 dark_gray
= 0xA9A9A9, // rgb(169,169,169)
42 dark_green
= 0x006400, // rgb(0,100,0)
43 dark_khaki
= 0xBDB76B, // rgb(189,183,107)
44 dark_magenta
= 0x8B008B, // rgb(139,0,139)
45 dark_olive_green
= 0x556B2F, // rgb(85,107,47)
46 dark_orange
= 0xFF8C00, // rgb(255,140,0)
47 dark_orchid
= 0x9932CC, // rgb(153,50,204)
48 dark_red
= 0x8B0000, // rgb(139,0,0)
49 dark_salmon
= 0xE9967A, // rgb(233,150,122)
50 dark_sea_green
= 0x8FBC8F, // rgb(143,188,143)
51 dark_slate_blue
= 0x483D8B, // rgb(72,61,139)
52 dark_slate_gray
= 0x2F4F4F, // rgb(47,79,79)
53 dark_turquoise
= 0x00CED1, // rgb(0,206,209)
54 dark_violet
= 0x9400D3, // rgb(148,0,211)
55 deep_pink
= 0xFF1493, // rgb(255,20,147)
56 deep_sky_blue
= 0x00BFFF, // rgb(0,191,255)
57 dim_gray
= 0x696969, // rgb(105,105,105)
58 dodger_blue
= 0x1E90FF, // rgb(30,144,255)
59 fire_brick
= 0xB22222, // rgb(178,34,34)
60 floral_white
= 0xFFFAF0, // rgb(255,250,240)
61 forest_green
= 0x228B22, // rgb(34,139,34)
62 fuchsia
= 0xFF00FF, // rgb(255,0,255)
63 gainsboro
= 0xDCDCDC, // rgb(220,220,220)
64 ghost_white
= 0xF8F8FF, // rgb(248,248,255)
65 gold
= 0xFFD700, // rgb(255,215,0)
66 golden_rod
= 0xDAA520, // rgb(218,165,32)
67 gray
= 0x808080, // rgb(128,128,128)
68 green
= 0x008000, // rgb(0,128,0)
69 green_yellow
= 0xADFF2F, // rgb(173,255,47)
70 honey_dew
= 0xF0FFF0, // rgb(240,255,240)
71 hot_pink
= 0xFF69B4, // rgb(255,105,180)
72 indian_red
= 0xCD5C5C, // rgb(205,92,92)
73 indigo
= 0x4B0082, // rgb(75,0,130)
74 ivory
= 0xFFFFF0, // rgb(255,255,240)
75 khaki
= 0xF0E68C, // rgb(240,230,140)
76 lavender
= 0xE6E6FA, // rgb(230,230,250)
77 lavender_blush
= 0xFFF0F5, // rgb(255,240,245)
78 lawn_green
= 0x7CFC00, // rgb(124,252,0)
79 lemon_chiffon
= 0xFFFACD, // rgb(255,250,205)
80 light_blue
= 0xADD8E6, // rgb(173,216,230)
81 light_coral
= 0xF08080, // rgb(240,128,128)
82 light_cyan
= 0xE0FFFF, // rgb(224,255,255)
83 light_golden_rod_yellow
= 0xFAFAD2, // rgb(250,250,210)
84 light_gray
= 0xD3D3D3, // rgb(211,211,211)
85 light_green
= 0x90EE90, // rgb(144,238,144)
86 light_pink
= 0xFFB6C1, // rgb(255,182,193)
87 light_salmon
= 0xFFA07A, // rgb(255,160,122)
88 light_sea_green
= 0x20B2AA, // rgb(32,178,170)
89 light_sky_blue
= 0x87CEFA, // rgb(135,206,250)
90 light_slate_gray
= 0x778899, // rgb(119,136,153)
91 light_steel_blue
= 0xB0C4DE, // rgb(176,196,222)
92 light_yellow
= 0xFFFFE0, // rgb(255,255,224)
93 lime
= 0x00FF00, // rgb(0,255,0)
94 lime_green
= 0x32CD32, // rgb(50,205,50)
95 linen
= 0xFAF0E6, // rgb(250,240,230)
96 magenta
= 0xFF00FF, // rgb(255,0,255)
97 maroon
= 0x800000, // rgb(128,0,0)
98 medium_aquamarine
= 0x66CDAA, // rgb(102,205,170)
99 medium_blue
= 0x0000CD, // rgb(0,0,205)
100 medium_orchid
= 0xBA55D3, // rgb(186,85,211)
101 medium_purple
= 0x9370DB, // rgb(147,112,219)
102 medium_sea_green
= 0x3CB371, // rgb(60,179,113)
103 medium_slate_blue
= 0x7B68EE, // rgb(123,104,238)
104 medium_spring_green
= 0x00FA9A, // rgb(0,250,154)
105 medium_turquoise
= 0x48D1CC, // rgb(72,209,204)
106 medium_violet_red
= 0xC71585, // rgb(199,21,133)
107 midnight_blue
= 0x191970, // rgb(25,25,112)
108 mint_cream
= 0xF5FFFA, // rgb(245,255,250)
109 misty_rose
= 0xFFE4E1, // rgb(255,228,225)
110 moccasin
= 0xFFE4B5, // rgb(255,228,181)
111 navajo_white
= 0xFFDEAD, // rgb(255,222,173)
112 navy
= 0x000080, // rgb(0,0,128)
113 old_lace
= 0xFDF5E6, // rgb(253,245,230)
114 olive
= 0x808000, // rgb(128,128,0)
115 olive_drab
= 0x6B8E23, // rgb(107,142,35)
116 orange
= 0xFFA500, // rgb(255,165,0)
117 orange_red
= 0xFF4500, // rgb(255,69,0)
118 orchid
= 0xDA70D6, // rgb(218,112,214)
119 pale_golden_rod
= 0xEEE8AA, // rgb(238,232,170)
120 pale_green
= 0x98FB98, // rgb(152,251,152)
121 pale_turquoise
= 0xAFEEEE, // rgb(175,238,238)
122 pale_violet_red
= 0xDB7093, // rgb(219,112,147)
123 papaya_whip
= 0xFFEFD5, // rgb(255,239,213)
124 peach_puff
= 0xFFDAB9, // rgb(255,218,185)
125 peru
= 0xCD853F, // rgb(205,133,63)
126 pink
= 0xFFC0CB, // rgb(255,192,203)
127 plum
= 0xDDA0DD, // rgb(221,160,221)
128 powder_blue
= 0xB0E0E6, // rgb(176,224,230)
129 purple
= 0x800080, // rgb(128,0,128)
130 rebecca_purple
= 0x663399, // rgb(102,51,153)
131 red
= 0xFF0000, // rgb(255,0,0)
132 rosy_brown
= 0xBC8F8F, // rgb(188,143,143)
133 royal_blue
= 0x4169E1, // rgb(65,105,225)
134 saddle_brown
= 0x8B4513, // rgb(139,69,19)
135 salmon
= 0xFA8072, // rgb(250,128,114)
136 sandy_brown
= 0xF4A460, // rgb(244,164,96)
137 sea_green
= 0x2E8B57, // rgb(46,139,87)
138 sea_shell
= 0xFFF5EE, // rgb(255,245,238)
139 sienna
= 0xA0522D, // rgb(160,82,45)
140 silver
= 0xC0C0C0, // rgb(192,192,192)
141 sky_blue
= 0x87CEEB, // rgb(135,206,235)
142 slate_blue
= 0x6A5ACD, // rgb(106,90,205)
143 slate_gray
= 0x708090, // rgb(112,128,144)
144 snow
= 0xFFFAFA, // rgb(255,250,250)
145 spring_green
= 0x00FF7F, // rgb(0,255,127)
146 steel_blue
= 0x4682B4, // rgb(70,130,180)
147 tan
= 0xD2B48C, // rgb(210,180,140)
148 teal
= 0x008080, // rgb(0,128,128)
149 thistle
= 0xD8BFD8, // rgb(216,191,216)
150 tomato
= 0xFF6347, // rgb(255,99,71)
151 turquoise
= 0x40E0D0, // rgb(64,224,208)
152 violet
= 0xEE82EE, // rgb(238,130,238)
153 wheat
= 0xF5DEB3, // rgb(245,222,179)
154 white
= 0xFFFFFF, // rgb(255,255,255)
155 white_smoke
= 0xF5F5F5, // rgb(245,245,245)
156 yellow
= 0xFFFF00, // rgb(255,255,0)
157 yellow_green
= 0x9ACD32 // rgb(154,205,50)
158 }; // enum class color
160 enum class terminal_color
: uint8_t {
179 enum class emphasis
: uint8_t {
187 strikethrough
= 1 << 7,
190 // rgb is a struct for red, green and blue colors.
191 // Using the name "rgb" makes some editors show the color in a tooltip.
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) {}
208 // color is a struct of either a rgb color or a terminal color.
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
);
228 } // namespace detail
230 /// A text style consisting of foreground and background colors and emphasis.
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;
274 FMT_CONSTEXPR
auto get_foreground() const noexcept
-> detail::color_type
{
275 FMT_ASSERT(has_foreground(), "no foreground specified for this style");
276 return foreground_color
;
278 FMT_CONSTEXPR
auto get_background() const noexcept
-> detail::color_type
{
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
,
289 detail::color_type text_color
) noexcept
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;
300 friend FMT_CONSTEXPR
auto fg(detail::color_type foreground
) noexcept
303 friend FMT_CONSTEXPR
auto bg(detail::color_type background
) noexcept
306 detail::color_type foreground_color
;
307 detail::color_type background_color
;
308 bool set_foreground_color
;
309 bool set_background_color
;
313 /// Creates a text style from the foreground (text) color.
314 FMT_CONSTEXPR
inline auto fg(detail::color_type foreground
) noexcept
316 return text_style(true, foreground
);
319 /// Creates a text style from the background color.
320 FMT_CONSTEXPR
inline auto bg(detail::color_type background
) noexcept
322 return text_style(false, background
);
325 FMT_CONSTEXPR
inline auto operator|(emphasis lhs
, emphasis rhs
) noexcept
327 return text_style(lhs
) | rhs
;
332 template <typename Char
> struct ansi_color_escape
{
333 FMT_CONSTEXPR
ansi_color_escape(detail::color_type text_color
,
334 const char* esc
) noexcept
{
335 // If we have a terminal color, we need to output another escape code
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
;
340 // Background ASCII codes are the same as the foreground ones but with
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
* {
394 return buffer
+ basic_string_view
<Char
>(buffer
).size();
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
);
414 template <typename Char
>
415 FMT_CONSTEXPR
auto make_foreground_color(detail::color_type foreground
) noexcept
416 -> ansi_color_escape
<Char
> {
417 return ansi_color_escape
<Char
>(foreground
, "\x1b[38;2;");
420 template <typename Char
>
421 FMT_CONSTEXPR
auto make_background_color(detail::color_type background
) noexcept
422 -> ansi_color_escape
<Char
> {
423 return ansi_color_escape
<Char
>(background
, "\x1b[48;2;");
426 template <typename Char
>
427 FMT_CONSTEXPR
auto make_emphasis(emphasis em
) noexcept
428 -> ansi_color_escape
<Char
> {
429 return ansi_color_escape
<Char
>(em
);
432 template <typename Char
> inline void reset_color(buffer
<Char
>& buffer
) {
433 auto reset_color
= string_view("\x1b[0m");
434 buffer
.append(reset_color
.begin(), reset_color
.end());
437 template <typename T
> struct styled_arg
: detail::view
{
440 styled_arg(const T
& v
, text_style s
) : value(v
), style(s
) {}
443 template <typename Char
>
445 buffer
<Char
>& buf
, const text_style
& ts
, basic_string_view
<Char
> format_str
,
446 basic_format_args
<buffered_context
<type_identity_t
<Char
>>> args
) {
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
);
467 } // namespace detail
469 inline 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()));
477 * Formats a string and prints it to the specified file stream using ANSI
478 * escape sequences to specify text formatting.
482 * fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
483 * "Elapsed time: {0:.2f} seconds", 1.23);
485 template <typename
... T
>
486 void print(FILE* f
, const text_style
& ts
, format_string
<T
...> fmt
,
488 vprint(f
, ts
, fmt
, fmt::make_format_args(args
...));
492 * Formats a string and prints it to stdout using ANSI escape sequences to
493 * specify text formatting.
497 * fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
498 * "Elapsed time: {0:.2f} seconds", 1.23);
500 template <typename
... T
>
501 void print(const text_style
& ts
, format_string
<T
...> fmt
, T
&&... args
) {
502 return print(stdout
, ts
, fmt
, std::forward
<T
>(args
)...);
505 inline 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
);
513 * Formats arguments and returns the result as a string using ANSI escape
514 * sequences to specify text formatting.
519 * #include <fmt/color.h>
520 * std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red),
521 * "The answer is {}", 42);
524 template <typename
... T
>
525 inline auto format(const text_style
& ts
, format_string
<T
...> fmt
, T
&&... args
)
527 return fmt::vformat(ts
, fmt
, fmt::make_format_args(args
...));
530 /// Formats a string with the given text_style and writes the output to `out`.
531 template <typename OutputIt
,
532 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, char>::value
)>
533 auto 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
);
541 * Formats arguments with the given text style, writes the result to the output
542 * iterator `out` and returns the iterator past the end of the output range.
546 * std::vector<char> out;
547 * fmt::format_to(std::back_inserter(out),
548 * fmt::emphasis::bold | fg(fmt::color::red), "{}", 42);
550 template <typename OutputIt
, typename
... T
,
551 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, char>::value
)>
552 inline 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
...));
557 template <typename T
, typename Char
>
558 struct formatter
<detail::styled_arg
<T
>, Char
> : formatter
<T
, Char
> {
559 template <typename FormatContext
>
560 auto format(const detail::styled_arg
<T
>& arg
, FormatContext
& ctx
) const
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
);
594 * Returns an argument that will be formatted using ANSI escape sequences,
595 * to be used in a formatting function.
599 * fmt::print("Elapsed time: {0:.2f} seconds",
600 * fmt::styled(1.23, fmt::fg(fmt::color::green) |
601 * fmt::bg(fmt::color::blue)));
603 template <typename T
>
604 FMT_CONSTEXPR
auto styled(const T
& value
, text_style ts
)
605 -> detail::styled_arg
<remove_cvref_t
<T
>> {
606 return detail::styled_arg
<remove_cvref_t
<T
>>{value
, ts
};
612 #endif // FMT_COLOR_H_