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.
14 FMT_MODULE_EXPORT_BEGIN
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) {}
206 FMT_BEGIN_DETAIL_NAMESPACE
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
);
229 FMT_END_DETAIL_NAMESPACE
231 /** A text style consisting of foreground and background colors and emphasis. */
234 FMT_CONSTEXPR
text_style(emphasis em
= emphasis()) noexcept
235 : set_foreground_color(), set_background_color(), ems(em
) {}
237 FMT_CONSTEXPR text_style
& operator|=(const text_style
& rhs
) {
238 if (!set_foreground_color
) {
239 set_foreground_color
= rhs
.set_foreground_color
;
240 foreground_color
= rhs
.foreground_color
;
241 } else if (rhs
.set_foreground_color
) {
242 if (!foreground_color
.is_rgb
|| !rhs
.foreground_color
.is_rgb
)
243 FMT_THROW(format_error("can't OR a terminal color"));
244 foreground_color
.value
.rgb_color
|= rhs
.foreground_color
.value
.rgb_color
;
247 if (!set_background_color
) {
248 set_background_color
= rhs
.set_background_color
;
249 background_color
= rhs
.background_color
;
250 } else if (rhs
.set_background_color
) {
251 if (!background_color
.is_rgb
|| !rhs
.background_color
.is_rgb
)
252 FMT_THROW(format_error("can't OR a terminal color"));
253 background_color
.value
.rgb_color
|= rhs
.background_color
.value
.rgb_color
;
256 ems
= static_cast<emphasis
>(static_cast<uint8_t>(ems
) |
257 static_cast<uint8_t>(rhs
.ems
));
261 friend FMT_CONSTEXPR text_style
operator|(text_style lhs
,
262 const text_style
& rhs
) {
266 FMT_CONSTEXPR
bool has_foreground() const noexcept
{
267 return set_foreground_color
;
269 FMT_CONSTEXPR
bool has_background() const noexcept
{
270 return set_background_color
;
272 FMT_CONSTEXPR
bool has_emphasis() const noexcept
{
273 return static_cast<uint8_t>(ems
) != 0;
275 FMT_CONSTEXPR
detail::color_type
get_foreground() const noexcept
{
276 FMT_ASSERT(has_foreground(), "no foreground specified for this style");
277 return foreground_color
;
279 FMT_CONSTEXPR
detail::color_type
get_background() const noexcept
{
280 FMT_ASSERT(has_background(), "no background specified for this style");
281 return background_color
;
283 FMT_CONSTEXPR emphasis
get_emphasis() const noexcept
{
284 FMT_ASSERT(has_emphasis(), "no emphasis specified for this style");
289 FMT_CONSTEXPR
text_style(bool is_foreground
,
290 detail::color_type text_color
) noexcept
291 : set_foreground_color(), set_background_color(), ems() {
293 foreground_color
= text_color
;
294 set_foreground_color
= true;
296 background_color
= text_color
;
297 set_background_color
= true;
301 friend FMT_CONSTEXPR text_style
fg(detail::color_type foreground
) noexcept
;
303 friend FMT_CONSTEXPR text_style
bg(detail::color_type background
) noexcept
;
305 detail::color_type foreground_color
;
306 detail::color_type background_color
;
307 bool set_foreground_color
;
308 bool set_background_color
;
312 /** Creates a text style from the foreground (text) color. */
313 FMT_CONSTEXPR
inline text_style
fg(detail::color_type foreground
) noexcept
{
314 return text_style(true, foreground
);
317 /** Creates a text style from the background color. */
318 FMT_CONSTEXPR
inline text_style
bg(detail::color_type background
) noexcept
{
319 return text_style(false, background
);
322 FMT_CONSTEXPR
inline text_style
operator|(emphasis lhs
, emphasis rhs
) noexcept
{
323 return text_style(lhs
) | rhs
;
326 FMT_BEGIN_DETAIL_NAMESPACE
328 template <typename Char
> struct ansi_color_escape
{
329 FMT_CONSTEXPR
ansi_color_escape(detail::color_type text_color
,
330 const char* esc
) noexcept
{
331 // If we have a terminal color, we need to output another escape code
333 if (!text_color
.is_rgb
) {
334 bool is_background
= esc
== string_view("\x1b[48;2;");
335 uint32_t value
= text_color
.value
.term_color
;
336 // Background ASCII codes are the same as the foreground ones but with
338 if (is_background
) value
+= 10u;
341 buffer
[index
++] = static_cast<Char
>('\x1b');
342 buffer
[index
++] = static_cast<Char
>('[');
345 buffer
[index
++] = static_cast<Char
>('1');
348 buffer
[index
++] = static_cast<Char
>('0' + value
/ 10u);
349 buffer
[index
++] = static_cast<Char
>('0' + value
% 10u);
351 buffer
[index
++] = static_cast<Char
>('m');
352 buffer
[index
++] = static_cast<Char
>('\0');
356 for (int i
= 0; i
< 7; i
++) {
357 buffer
[i
] = static_cast<Char
>(esc
[i
]);
359 rgb
color(text_color
.value
.rgb_color
);
360 to_esc(color
.r
, buffer
+ 7, ';');
361 to_esc(color
.g
, buffer
+ 11, ';');
362 to_esc(color
.b
, buffer
+ 15, 'm');
363 buffer
[19] = static_cast<Char
>(0);
365 FMT_CONSTEXPR
ansi_color_escape(emphasis em
) noexcept
{
366 uint8_t em_codes
[num_emphases
] = {};
367 if (has_emphasis(em
, emphasis::bold
)) em_codes
[0] = 1;
368 if (has_emphasis(em
, emphasis::faint
)) em_codes
[1] = 2;
369 if (has_emphasis(em
, emphasis::italic
)) em_codes
[2] = 3;
370 if (has_emphasis(em
, emphasis::underline
)) em_codes
[3] = 4;
371 if (has_emphasis(em
, emphasis::blink
)) em_codes
[4] = 5;
372 if (has_emphasis(em
, emphasis::reverse
)) em_codes
[5] = 7;
373 if (has_emphasis(em
, emphasis::conceal
)) em_codes
[6] = 8;
374 if (has_emphasis(em
, emphasis::strikethrough
)) em_codes
[7] = 9;
377 for (size_t i
= 0; i
< num_emphases
; ++i
) {
378 if (!em_codes
[i
]) continue;
379 buffer
[index
++] = static_cast<Char
>('\x1b');
380 buffer
[index
++] = static_cast<Char
>('[');
381 buffer
[index
++] = static_cast<Char
>('0' + em_codes
[i
]);
382 buffer
[index
++] = static_cast<Char
>('m');
384 buffer
[index
++] = static_cast<Char
>(0);
386 FMT_CONSTEXPR
operator const Char
*() const noexcept
{ return buffer
; }
388 FMT_CONSTEXPR
const Char
* begin() const noexcept
{ return buffer
; }
389 FMT_CONSTEXPR_CHAR_TRAITS
const Char
* end() const noexcept
{
390 return buffer
+ std::char_traits
<Char
>::length(buffer
);
394 static constexpr size_t num_emphases
= 8;
395 Char buffer
[7u + 3u * num_emphases
+ 1u];
397 static FMT_CONSTEXPR
void to_esc(uint8_t c
, Char
* out
,
398 char delimiter
) noexcept
{
399 out
[0] = static_cast<Char
>('0' + c
/ 100);
400 out
[1] = static_cast<Char
>('0' + c
/ 10 % 10);
401 out
[2] = static_cast<Char
>('0' + c
% 10);
402 out
[3] = static_cast<Char
>(delimiter
);
404 static FMT_CONSTEXPR
bool has_emphasis(emphasis em
, emphasis mask
) noexcept
{
405 return static_cast<uint8_t>(em
) & static_cast<uint8_t>(mask
);
409 template <typename Char
>
410 FMT_CONSTEXPR ansi_color_escape
<Char
> make_foreground_color(
411 detail::color_type foreground
) noexcept
{
412 return ansi_color_escape
<Char
>(foreground
, "\x1b[38;2;");
415 template <typename Char
>
416 FMT_CONSTEXPR ansi_color_escape
<Char
> make_background_color(
417 detail::color_type background
) noexcept
{
418 return ansi_color_escape
<Char
>(background
, "\x1b[48;2;");
421 template <typename Char
>
422 FMT_CONSTEXPR ansi_color_escape
<Char
> make_emphasis(emphasis em
) noexcept
{
423 return ansi_color_escape
<Char
>(em
);
426 template <typename Char
> inline void fputs(const Char
* chars
, FILE* stream
) {
427 int result
= std::fputs(chars
, stream
);
429 FMT_THROW(system_error(errno
, FMT_STRING("cannot write to file")));
432 template <> inline void fputs
<wchar_t>(const wchar_t* chars
, FILE* stream
) {
433 int result
= std::fputws(chars
, stream
);
435 FMT_THROW(system_error(errno
, FMT_STRING("cannot write to file")));
438 template <typename Char
> inline void reset_color(FILE* stream
) {
439 fputs("\x1b[0m", stream
);
442 template <> inline void reset_color
<wchar_t>(FILE* stream
) {
443 fputs(L
"\x1b[0m", stream
);
446 template <typename Char
> inline void reset_color(buffer
<Char
>& buffer
) {
447 auto reset_color
= string_view("\x1b[0m");
448 buffer
.append(reset_color
.begin(), reset_color
.end());
451 template <typename T
> struct styled_arg
{
456 template <typename Char
>
457 void vformat_to(buffer
<Char
>& buf
, const text_style
& ts
,
458 basic_string_view
<Char
> format_str
,
459 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) {
460 bool has_style
= false;
461 if (ts
.has_emphasis()) {
463 auto emphasis
= detail::make_emphasis
<Char
>(ts
.get_emphasis());
464 buf
.append(emphasis
.begin(), emphasis
.end());
466 if (ts
.has_foreground()) {
468 auto foreground
= detail::make_foreground_color
<Char
>(ts
.get_foreground());
469 buf
.append(foreground
.begin(), foreground
.end());
471 if (ts
.has_background()) {
473 auto background
= detail::make_background_color
<Char
>(ts
.get_background());
474 buf
.append(background
.begin(), background
.end());
476 detail::vformat_to(buf
, format_str
, args
, {});
477 if (has_style
) detail::reset_color
<Char
>(buf
);
480 FMT_END_DETAIL_NAMESPACE
482 template <typename S
, typename Char
= char_t
<S
>>
483 void vprint(std::FILE* f
, const text_style
& ts
, const S
& format
,
484 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) {
485 basic_memory_buffer
<Char
> buf
;
486 detail::vformat_to(buf
, ts
, detail::to_string_view(format
), args
);
487 if (detail::is_utf8()) {
488 detail::print(f
, basic_string_view
<Char
>(buf
.begin(), buf
.size()));
490 buf
.push_back(Char(0));
491 detail::fputs(buf
.data(), f
);
497 Formats a string and prints it to the specified file stream using ANSI
498 escape sequences to specify text formatting.
502 fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
503 "Elapsed time: {0:.2f} seconds", 1.23);
506 template <typename S
, typename
... Args
,
507 FMT_ENABLE_IF(detail::is_string
<S
>::value
)>
508 void print(std::FILE* f
, const text_style
& ts
, const S
& format_str
,
509 const Args
&... args
) {
510 vprint(f
, ts
, format_str
,
511 fmt::make_format_args
<buffer_context
<char_t
<S
>>>(args
...));
516 Formats a string and prints it to stdout using ANSI escape sequences to
517 specify text formatting.
521 fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
522 "Elapsed time: {0:.2f} seconds", 1.23);
525 template <typename S
, typename
... Args
,
526 FMT_ENABLE_IF(detail::is_string
<S
>::value
)>
527 void print(const text_style
& ts
, const S
& format_str
, const Args
&... args
) {
528 return print(stdout
, ts
, format_str
, args
...);
531 template <typename S
, typename Char
= char_t
<S
>>
532 inline std::basic_string
<Char
> vformat(
533 const text_style
& ts
, const S
& format_str
,
534 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) {
535 basic_memory_buffer
<Char
> buf
;
536 detail::vformat_to(buf
, ts
, detail::to_string_view(format_str
), args
);
537 return fmt::to_string(buf
);
542 Formats arguments and returns the result as a string using ANSI
543 escape sequences to specify text formatting.
547 #include <fmt/color.h>
548 std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red),
549 "The answer is {}", 42);
552 template <typename S
, typename
... Args
, typename Char
= char_t
<S
>>
553 inline std::basic_string
<Char
> format(const text_style
& ts
, const S
& format_str
,
554 const Args
&... args
) {
555 return fmt::vformat(ts
, detail::to_string_view(format_str
),
556 fmt::make_format_args
<buffer_context
<Char
>>(args
...));
560 Formats a string with the given text_style and writes the output to ``out``.
562 template <typename OutputIt
, typename Char
,
563 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
)>
565 OutputIt out
, const text_style
& ts
, basic_string_view
<Char
> format_str
,
566 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) {
567 auto&& buf
= detail::get_buffer
<Char
>(out
);
568 detail::vformat_to(buf
, ts
, format_str
, args
);
569 return detail::get_iterator(buf
);
574 Formats arguments with the given text_style, writes the result to the output
575 iterator ``out`` and returns the iterator past the end of the output range.
579 std::vector<char> out;
580 fmt::format_to(std::back_inserter(out),
581 fmt::emphasis::bold | fg(fmt::color::red), "{}", 42);
584 template <typename OutputIt
, typename S
, typename
... Args
,
585 bool enable
= detail::is_output_iterator
<OutputIt
, char_t
<S
>>::value
&&
586 detail::is_string
<S
>::value
>
587 inline auto format_to(OutputIt out
, const text_style
& ts
, const S
& format_str
,
589 typename
std::enable_if
<enable
, OutputIt
>::type
{
590 return vformat_to(out
, ts
, detail::to_string_view(format_str
),
591 fmt::make_format_args
<buffer_context
<char_t
<S
>>>(args
...));
594 template <typename T
, typename Char
>
595 struct formatter
<detail::styled_arg
<T
>, Char
> : formatter
<T
, Char
> {
596 template <typename FormatContext
>
597 auto format(const detail::styled_arg
<T
>& arg
, FormatContext
& ctx
) const
598 -> decltype(ctx
.out()) {
599 const auto& ts
= arg
.style
;
600 const auto& value
= arg
.value
;
601 auto out
= ctx
.out();
603 bool has_style
= false;
604 if (ts
.has_emphasis()) {
606 auto emphasis
= detail::make_emphasis
<Char
>(ts
.get_emphasis());
607 out
= std::copy(emphasis
.begin(), emphasis
.end(), out
);
609 if (ts
.has_foreground()) {
612 detail::make_foreground_color
<Char
>(ts
.get_foreground());
613 out
= std::copy(foreground
.begin(), foreground
.end(), out
);
615 if (ts
.has_background()) {
618 detail::make_background_color
<Char
>(ts
.get_background());
619 out
= std::copy(background
.begin(), background
.end(), out
);
621 out
= formatter
<T
, Char
>::format(value
, ctx
);
623 auto reset_color
= string_view("\x1b[0m");
624 out
= std::copy(reset_color
.begin(), reset_color
.end(), out
);
632 Returns an argument that will be formatted using ANSI escape sequences,
633 to be used in a formatting function.
637 fmt::print("Elapsed time: {0:.2f} seconds",
638 fmt::styled(1.23, fmt::fg(fmt::color::green) |
639 fmt::bg(fmt::color::blue)));
642 template <typename T
>
643 FMT_CONSTEXPR
auto styled(const T
& value
, text_style ts
)
644 -> detail::styled_arg
<remove_cvref_t
<T
>> {
645 return detail::styled_arg
<remove_cvref_t
<T
>>{value
, ts
};
648 FMT_MODULE_EXPORT_END
651 #endif // FMT_COLOR_H_