Skip to content

Commit

Permalink
docs: "Text Output" chapter updated
Browse files Browse the repository at this point in the history
  • Loading branch information
mpusz committed Dec 27, 2023
1 parent 8dae093 commit b75cf85
Showing 1 changed file with 50 additions and 36 deletions.
86 changes: 50 additions & 36 deletions docs/users_guide/framework_basics/text_output.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ inline constexpr bool space_before_unit_symbol<non_si::degree> = false;
!!! note

The above works only for [the default formatting](#default-formatting). In case we provide our own
format specification (e.g. `std::format("{:%Q %q}", q)`), the library will always obey this
format specification (e.g., `std::format("{:%Q %q}", q)`), the library will always obey this
specification for all the units (no matter of what is the actual value of the
`space_before_unit_symbol` customization point) and the separating space will always be present
in this case.
Expand Down Expand Up @@ -152,7 +152,7 @@ associated with this quantity.
!!! important "Important: Don't assume a unit"
Remember that when we deal with a quantity of an "unknown" (e.g. `auto`) type, it is a good
Remember that when we deal with a quantity of an "unknown" (e.g., `auto`) type, it is a good
practice to always [convert the unit to the expected one](value_conversions.md#value-conversions)
before passing it to the text output:
Expand All @@ -174,6 +174,11 @@ std::cout << "|" << std::setw(10) << std::left << 123 * m << "|\n"; //
std::cout << "|" << std::setw(10) << std::setfill('*') << 123 * m << "|\n"; // |123 m*****|
```

!!! note

To have more control over the formatting of the quantity that is printed with the output
stream just use `std::cout << std::format(...)`.


### `std::format`

Expand All @@ -188,49 +193,58 @@ fine-grained control over what and how it is being printed in the text output.

#### Grammar

```text
units-format-spec ::= [fill-and-align] [width] [units-specs]
units-specs ::= conversion-spec
units-specs conversion-spec
units-specs literal-char
literal-char ::= any character other than '{' or '}'
conversion-spec ::= '%' units-type
units-type ::= [units-rep-modifier] 'Q'
[units-unit-modifier] 'q'
units-rep-modifier ::= [sign] [#] [precision] [L] [units-rep-type]
units-rep-type ::= one of "aAbBdeEfFgGoxX"
units-unit-modifier ::= [units-text-encoding units-unit-symbol-denominator units-unit-symbol-separator]
units-text-encoding ::= one of "UA"
units-unit-symbol-solidus ::= one of "oan"
units-unit-symbol-separator ::= one of "sd"
```ebnf
quantity-format-spec ::= [fill-and-align] [width] [quantity-specs]
quantity-specs ::= conversion-spec
quantity-specs conversion-spec
quantity-specs literal-char
literal-char ::= any character other than '{' or '}'
conversion-spec ::= '%' type
type ::= [rep-modifier] 'Q'
[unit-modifier] 'q'
rep-modifier ::= [sign] [#] [precision] [L] [rep-type]
rep-type ::= one of
a A b B d e E f F g G o x X
unit-modifier ::= [text-encoding] [unit-symbol-solidus] [unit-symbol-separator]
[text-encoding] [unit-symbol-separator] [unit-symbol-solidus]
[unit-symbol-solidus] [text-encoding] [unit-symbol-separator]
[unit-symbol-solidus] [unit-symbol-separator] [text-encoding]
[unit-symbol-separator] [text-encoding] [unit-symbol-solidus]
[unit-symbol-separator] [unit-symbol-solidus] [text-encoding]
text-encoding ::= one of
U A
unit-symbol-solidus ::= one of
o a n
unit-symbol-separator ::= one of
s d
```


In the above grammar:

- `fill-and-align`, `width`, `sign`, `#`, `precision`, and `L` tokens, as well as the individual
tokens of `units-rep-type` are defined in the [format.string.std](https://wg21.link/format.string.std)
tokens of `rep-type` are defined in the [format.string.std](https://wg21.link/format.string.std)
chapter of the C++ standard specification,
- tokens `Q` and `q` of `units-type` are described in the [time.format](https://wg21.link/time.format)
- tokens `Q` and `q` of `type` are described in the [time.format](https://wg21.link/time.format)
chapter of the C++ standard specification,
- `units-text-encoding` tokens specify the unit text encoding:
- `text-encoding` tokens specify the unit text encoding:
- `U` (default) uses the **Unicode** symbols defined by the [SI](../../appendix/glossary.md#si)
specification (e.g. ``, `µs`)
- `A` token forces non-standard **ASCII**-only output (e.g. `m^3`, `us`)
- `units-unit-symbol-solidus` tokens specify how the division of units should look like:
specification (e.g., ``, `µs`)
- `A` token forces non-standard **ASCII**-only output (e.g., `m^3`, `us`)
- `unit-symbol-solidus` tokens specify how the division of units should look like:
- `o` (default) outputs `/` only when there is only **one** unit in the denominator, otherwise negative
exponents are printed (e.g. `m/s`, `kg m⁻¹ s⁻¹`)
- `a` **always** uses solidus (e.g. `m/s`, `kg/(m s)`)
- `n` **never** prints solidus, which means that negative exponents are always used (e.g. `m s⁻¹`,
exponents are printed (e.g., `m/s`, `kg m⁻¹ s⁻¹`)
- `a` **always** uses solidus (e.g., `m/s`, `kg/(m s)`)
- `n` **never** prints solidus, which means that negative exponents are always used (e.g., `m s⁻¹`,
`kg m⁻¹ s⁻¹`)
- `units-unit-symbol-separator` tokens specify how multiplied unit symbols should be separated:
- `s` (default) uses **space** as a separator (e.g. `kg m²/s²`)
- `d` uses half-high **dot** (``) as a separator (e.g. `kg⋅m²/s²`)
- `unit-symbol-separator` tokens specify how multiplied unit symbols should be separated:
- `s` (default) uses **space** as a separator (e.g., `kg m²/s²`)
- `d` uses half-high **dot** (``) as a separator (e.g., `kg⋅m²/s²`)


#### Default formatting

To format `quantity` values, the formatting facility uses `units-format-spec`. If left empty,
To format `quantity` values, the formatting facility uses `quantity-format-spec`. If left empty,
the default formatting is applied. The same default formatting is also applied to the output streams.
This is why the following code lines produce the same output:

Expand Down Expand Up @@ -313,7 +327,7 @@ std::println("{:%.1Q %q}", 1.2345 * m); // 1.2 m
std::println("{:%.2Q %q}", 1.2345 * m); // 1.23 m
```

`units-rep-type` specifies how a value of the representation type is being printed.
`rep-type` specifies how a value of the representation type is being printed.
For integral types:

```cpp
Expand All @@ -335,7 +349,7 @@ std::println("{:%#xQ %q}", 42 * m); // 0x2a m
std::println("{:%#XQ %q}", 42 * m); // 0X2A m
```

For floating-point values, the `units-rep-type` token works as follows:
For floating-point values, the `rep-type` token works as follows:

```cpp
std::println("{:%aQ %q}", 1.2345678 * m); // 0x1.3c0ca2a5b1d5dp+0 m
Expand All @@ -360,11 +374,11 @@ std::println("{:%.3GQ %q}", 1.2345678e8 * m); // 1.23E+08 m
#### Unit symbol formatting
Unit symbols of some quantities are specified to use Unicode signs by the
[SI](../../appendix/glossary.md#si) (e.g. `Ω` symbol for the resistance quantity). The **mp-units**
[SI](../../appendix/glossary.md#si) (e.g., `Ω` symbol for the resistance quantity). The **mp-units**
library follows this by default. From the engineering point of view, sometimes Unicode text might
not be the best solution as terminals of many (especially embedded) devices are ASCII-only.
In such a case, the unit symbol can be forced to be printed using ASCII-only characters thanks to
`units-text-encoding` token:
`text-encoding` token:
```cpp
std::println("{}", 10 * si::ohm); // 10 Ω
Expand All @@ -378,7 +392,7 @@ std::println("{:%Q %Aq}", 9.8 * (m / s2)); // 9.8 m/s^2
Additionally, both [ISQ](../../appendix/glossary.md#isq) and [SI](../../appendix/glossary.md#si)
leave some freedom on how to print unit symbols. This is why two additional tokens were introduced.

`units-unit-symbol-solidus` specifies how the division of units should look like. By default,
`unit-symbol-solidus` specifies how the division of units should look like. By default,
`/` will be used only when the denominator contains only one unit. However, with the `a` or `n`
options, we can force the facility to print the `/` character always (even when there are more units
in the denominator), or never in which case a parenthesis will be added to enclose all denominator
Expand Down Expand Up @@ -410,7 +424,7 @@ to just use the `·` symbol as a separator.
Please let us know in case you require more formatting options here.
The `units-unit-symbol-separator` token allows us to obtain the following outputs:
The `unit-symbol-separator` token allows us to obtain the following outputs:
```cpp
std::println("{:%Q %q}", 1 * kg * m2 / s2); // 1 kg m²/s²
Expand Down

0 comments on commit b75cf85

Please sign in to comment.