diff --git a/doc/syntax.md b/doc/syntax.md index 014b41aa..e2a5219d 100644 --- a/doc/syntax.md +++ b/doc/syntax.md @@ -1,4 +1,4 @@ -# Format String Syntax {#syntax} +# Format String Syntax [Formatting functions](api.md) such as `fmt::format` and `fmt::print` use the same format string syntax described in this section. @@ -38,9 +38,11 @@ Named arguments can be referred to by their names or indices. Some simple format string examples: - "First, thou shalt count to {0}" // References the first argument - "Bring me a {}" // Implicitly references the first argument - "From {} to {}" // Same as "From {0} to {1}" +```c++ +"First, thou shalt count to {0}" // References the first argument +"Bring me a {}" // Implicitly references the first argument +"From {} to {}" // Same as "From {0} to {1}" +``` The *format_spec* field contains a specification of how the value should be presented, including such details as field width, alignment, padding, @@ -55,7 +57,7 @@ certain positions within it. These nested replacement fields can contain only an argument id; format specifications are not allowed. This allows the formatting of a value to be dynamically specified. -See the [Format Examples](#formatexamples) section for some examples. +See the [Format Examples](#format-examples) section for some examples. ## Format Specification Mini-Language @@ -81,12 +83,11 @@ type ::= "a" | "A" | "b" | "B" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "o" | "p" | "s" | "x" | "X" | "?" -The *fill* character can be any Unicode code point other than `'{'` or -`'}'`. The presence of a fill character is signaled by the character -following it, which must be one of the alignment options. If the second -character of *format_spec* is not a valid alignment option, then it is -assumed that both the fill character and the alignment option are -absent. +The *fill* character can be any Unicode code point other than `'{'` or `'}'`. +The presence of a fill character is signaled by the character following it, +which must be one of the alignment options. If the second character of +*format_spec* is not a valid alignment option, then it is assumed that both +the fill character and the alignment option are absent. The meaning of the various alignment options is as follows: @@ -257,14 +258,14 @@ The available presentation types for pointers are: | `'p'` | Pointer format. This is the default type for pointers and may be omitted. | | none | The same as `'p'`. | -## Chrono Format Specifications {#chrono-specs} +## Chrono Format Specifications Format specifications for chrono duration and time point types as well as `std::tm` have the following syntax:
-chrono_format_spec ::= [[fill]align][width]["." precision][chrono_specs] +chrono_format_spec ::= [[fill]align][width]["." precision][chrono_specs] chrono_specs ::= [chrono_specs] conversion_spec | chrono_specs literal_char conversion_spec ::= "%" [modifier] chrono_type literal_char ::= @@ -358,24 +359,26 @@ characters or strings are printed according to the provided specification. Examples: - fmt::format("{}", std::vector{10, 20, 30}); - // Result: [10, 20, 30] - fmt::format("{::#x}", std::vector{10, 20, 30}); - // Result: [0xa, 0x14, 0x1e] - fmt::format("{}", vector{'h', 'e', 'l', 'l', 'o'}); - // Result: ['h', 'e', 'l', 'l', 'o'] - fmt::format("{:n}", vector{'h', 'e', 'l', 'l', 'o'}); - // Result: 'h', 'e', 'l', 'l', 'o' - fmt::format("{:s}", vector{'h', 'e', 'l', 'l', 'o'}); - // Result: "hello" - fmt::format("{:?s}", vector{'h', 'e', 'l', 'l', 'o', '\n'}); - // Result: "hello\n" - fmt::format("{::}", vector{'h', 'e', 'l', 'l', 'o'}); - // Result: [h, e, l, l, o] - fmt::format("{::d}", vector{'h', 'e', 'l', 'l', 'o'}); - // Result: [104, 101, 108, 108, 111] +```c++ +fmt::print("{}", std::vector{10, 20, 30}); +// Output: [10, 20, 30] +fmt::print("{::#x}", std::vector{10, 20, 30}); +// Output: [0xa, 0x14, 0x1e] +fmt::print("{}", std::vector{'h', 'e', 'l', 'l', 'o'}); +// Output: ['h', 'e', 'l', 'l', 'o'] +fmt::print("{:n}", std::vector{'h', 'e', 'l', 'l', 'o'}); +// Output: 'h', 'e', 'l', 'l', 'o' +fmt::print("{:s}", std::vector{'h', 'e', 'l', 'l', 'o'}); +// Output: "hello" +fmt::print("{:?s}", std::vector{'h', 'e', 'l', 'l', 'o', '\n'}); +// Output: "hello\n" +fmt::print("{::}", std::vector{'h', 'e', 'l', 'l', 'o'}); +// Output: [h, e, l, l, o] +fmt::print("{::d}", std::vector{'h', 'e', 'l', 'l', 'o'}); +// Output: [104, 101, 108, 108, 111] +``` -## Format Examples {#formatexamples} +## Format Examples This section contains examples of the format syntax and comparison with the printf formatting. @@ -389,88 +392,110 @@ the following examples. Accessing arguments by position: - fmt::format("{0}, {1}, {2}", 'a', 'b', 'c'); - // Result: "a, b, c" - fmt::format("{}, {}, {}", 'a', 'b', 'c'); - // Result: "a, b, c" - fmt::format("{2}, {1}, {0}", 'a', 'b', 'c'); - // Result: "c, b, a" - fmt::format("{0}{1}{0}", "abra", "cad"); // arguments' indices can be repeated - // Result: "abracadabra" +```c++ +fmt::format("{0}, {1}, {2}", 'a', 'b', 'c'); +// Result: "a, b, c" +fmt::format("{}, {}, {}", 'a', 'b', 'c'); +// Result: "a, b, c" +fmt::format("{2}, {1}, {0}", 'a', 'b', 'c'); +// Result: "c, b, a" +fmt::format("{0}{1}{0}", "abra", "cad"); // arguments' indices can be repeated +// Result: "abracadabra" +``` Aligning the text and specifying a width: - fmt::format("{:<30}", "left aligned"); - // Result: "left aligned " - fmt::format("{:>30}", "right aligned"); - // Result: " right aligned" - fmt::format("{:^30}", "centered"); - // Result: " centered " - fmt::format("{:*^30}", "centered"); // use '*' as a fill char - // Result: "***********centered***********" +```c++ +fmt::format("{:<30}", "left aligned"); +// Result: "left aligned " +fmt::format("{:>30}", "right aligned"); +// Result: " right aligned" +fmt::format("{:^30}", "centered"); +// Result: " centered " +fmt::format("{:*^30}", "centered"); // use '*' as a fill char +// Result: "***********centered***********" +``` Dynamic width: - fmt::format("{:<{}}", "left aligned", 30); - // Result: "left aligned " +```c++ +fmt::format("{:<{}}", "left aligned", 30); +// Result: "left aligned " +``` Dynamic precision: - fmt::format("{:.{}f}", 3.14, 1); - // Result: "3.1" +```c++ +fmt::format("{:.{}f}", 3.14, 1); +// Result: "3.1" +``` Replacing `%+f`, `%-f`, and `% f` and specifying a sign: - fmt::format("{:+f}; {:+f}", 3.14, -3.14); // show it always - // Result: "+3.140000; -3.140000" - fmt::format("{: f}; {: f}", 3.14, -3.14); // show a space for positive numbers - // Result: " 3.140000; -3.140000" - fmt::format("{:-f}; {:-f}", 3.14, -3.14); // show only the minus -- same as '{:f}; {:f}' - // Result: "3.140000; -3.140000" +```c++ +fmt::format("{:+f}; {:+f}", 3.14, -3.14); // show it always +// Result: "+3.140000; -3.140000" +fmt::format("{: f}; {: f}", 3.14, -3.14); // show a space for positive numbers +// Result: " 3.140000; -3.140000" +fmt::format("{:-f}; {:-f}", 3.14, -3.14); // show only the minus -- same as '{:f}; {:f}' +// Result: "3.140000; -3.140000" +``` Replacing `%x` and `%o` and converting the value to different bases: - fmt::format("int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); - // Result: "int: 42; hex: 2a; oct: 52; bin: 101010" - // with 0x or 0 or 0b as prefix: - fmt::format("int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}", 42); - // Result: "int: 42; hex: 0x2a; oct: 052; bin: 0b101010" +```c++ +fmt::format("int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); +// Result: "int: 42; hex: 2a; oct: 52; bin: 101010" +// with 0x or 0 or 0b as prefix: +fmt::format("int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}", 42); +// Result: "int: 42; hex: 0x2a; oct: 052; bin: 0b101010" +``` Padded hex byte with prefix and always prints both hex characters: - fmt::format("{:#04x}", 0); - // Result: "0x00" +```c++ +fmt::format("{:#04x}", 0); +// Result: "0x00" +``` Box drawing using Unicode fill: - fmt::print( - "┌{0:─^{2}}┐\n" - "│{1: ^{2}}│\n" - "└{0:─^{2}}┘\n", "", "Hello, world!", 20); +```c++ +fmt::print( + "┌{0:─^{2}}┐\n" + "│{1: ^{2}}│\n" + "└{0:─^{2}}┘\n", "", "Hello, world!", 20); +``` prints: - ┌────────────────────┐ - │ Hello, world! │ - └────────────────────┘ +``` +┌────────────────────┐ +│ Hello, world! │ +└────────────────────┘ +``` Using type-specific formatting: - #include+```c++ +#include - auto t = tm(); - t.tm_year = 2010 - 1900; - t.tm_mon = 7; - t.tm_mday = 4; - t.tm_hour = 12; - t.tm_min = 15; - t.tm_sec = 58; - fmt::print("{:%Y-%m-%d %H:%M:%S}", t); - // Prints: 2010-08-04 12:15:58 +auto t = tm(); +t.tm_year = 2010 - 1900; +t.tm_mon = 7; +t.tm_mday = 4; +t.tm_hour = 12; +t.tm_min = 15; +t.tm_sec = 58; +fmt::print("{:%Y-%m-%d %H:%M:%S}", t); +// Prints: 2010-08-04 12:15:58 +``` Using the comma as a thousands separator: - #include +```c++ +#include - auto s = fmt::format(std::locale("en_US.UTF-8"), "{:L}", 1234567890); - // s == "1,234,567,890" +auto s = fmt::format(std::locale("en_US.UTF-8"), "{:L}", 1234567890); +// s == "1,234,567,890" +```