mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
Documentation: Document string formatting format
This commit is contained in:
parent
f5b584f966
commit
e8c71605b9
Notes:
sideshowbarker
2024-07-17 21:26:16 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/SerenityOS/serenity/commit/e8c71605b9e Pull-request: https://github.com/SerenityOS/serenity/pull/11615 Reviewed-by: https://github.com/alimpfard Reviewed-by: https://github.com/trflynn89
1 changed files with 140 additions and 0 deletions
140
Documentation/StringFormatting.md
Normal file
140
Documentation/StringFormatting.md
Normal file
|
@ -0,0 +1,140 @@
|
|||
# String Formatting
|
||||
|
||||
Many places in Serenity allow you to format strings, similar to `printf()`, for example `String::formatted()`
|
||||
, `StringBuilder::appendff()`, or `dbgln()`. These are checked at compile time to ensure the format string matches the
|
||||
number of parameters. The syntax is largely based on
|
||||
the [C++ `std::formatter` syntax](https://en.cppreference.com/w/cpp/utility/format/formatter#Standard_format_specification)
|
||||
but there are some differences.
|
||||
|
||||
For basic usage, any occurrences of `{}` in the format string are replaced with the other arguments, converted to string
|
||||
form, in order:
|
||||
|
||||
```c++
|
||||
String::formatted("Well, {} my {} friends!", "hello", 42) == "Well, hello my 42 friends!";
|
||||
```
|
||||
|
||||
If you want to include a literal `{` in the output, use `{{`:
|
||||
|
||||
```c++
|
||||
String::formatted("{{ {}", "hello") == "{ hello";
|
||||
```
|
||||
|
||||
You can refer to the arguments by index, if you want to repeat one or change the order:
|
||||
|
||||
```c++
|
||||
String::formatted("{2}{0}{1}", "a", "b", "c") == "cab";
|
||||
```
|
||||
|
||||
To control how the arguments are formatted, add colon after the optional index, and then add format specifier
|
||||
characters:
|
||||
|
||||
```c++
|
||||
String::formatted("{:.4}", "cool dude") == "cool";
|
||||
String::formatted("{0:.4}", "cool dude") == "cool";
|
||||
```
|
||||
|
||||
## Format specifiers
|
||||
|
||||
In order, the format can contain:
|
||||
|
||||
- Fill character and alignment
|
||||
- Sign
|
||||
- `#` Hash
|
||||
- `0` Zero
|
||||
- Width
|
||||
- Precision
|
||||
- Type specifier
|
||||
|
||||
Each of these is optional. You can include any combination of them, but they must be in this order.
|
||||
|
||||
### Fill and alignment
|
||||
|
||||
This is an optional fill character, followed by an alignment. The fill character can be anything apart from `{` or `}`,
|
||||
and is used to fill any space left when the input has fewer characters than the format requests. By default, it is a
|
||||
space. (` `)
|
||||
|
||||
The alignment characters are:
|
||||
|
||||
- `<`: Align left.
|
||||
- `>`: Align right.
|
||||
- `^`: Align centered.
|
||||
|
||||
### Sign
|
||||
|
||||
- `+`: Always display a sign before the number.
|
||||
- `-`: Display a sign for negative numbers only.
|
||||
- (space): Display a sign for negative numbers, and a leading space for other numbers.
|
||||
|
||||
### Hash
|
||||
|
||||
`#` causes an "alternate form" to be used.
|
||||
|
||||
For integer types, this adds the number-base prefix after the sign:
|
||||
|
||||
- `0b` for binary.
|
||||
- `0` for octal.
|
||||
- `0x` for hexadecimal.
|
||||
|
||||
### Zero
|
||||
|
||||
`0` pads the number with leading zeros.
|
||||
|
||||
### Width and Precision
|
||||
|
||||
The width defines the minimum number of characters in the output. The precision is a `.` followed by a precision number,
|
||||
which is used as the precision of floating-point numbers, or a maximum-width for string values.
|
||||
|
||||
Both the width and precision can be provided as a replacement field (`{}`, optionally including an argument index) which
|
||||
allows you to use an integer argument instead of a hard-coded number.
|
||||
|
||||
### Type specifiers
|
||||
|
||||
| Type | Effect | Example output |
|
||||
|-----------|-----------------------|--------------------------|
|
||||
| *nothing* | default format | Anything! :^) |
|
||||
| b | binary | `110`, `0b000110` |
|
||||
| B | binary uppercase | `110`, `0B000110` |
|
||||
| d | decimal | `42`, `+0000042` |
|
||||
| o | octal | `043` |
|
||||
| x | hexadecimal | `ff0`, `0x00000ff0` |
|
||||
| X | hexadecimal uppercase | `FF0`, `0X00000FF0` |
|
||||
| c | character | `a` |
|
||||
| s | string | `well, hello friends!` |
|
||||
| p | pointer | `0xdeadc0de` |
|
||||
| f | float | `1.234`, `-inf` |
|
||||
| a | hex float | |
|
||||
| A | hex float uppercase | |
|
||||
| hex-dump | hexadecimal dump | `fdfdfdfd`, `3030 00` |
|
||||
|
||||
Not all type specifiers are compatible with all input types, of course.
|
||||
|
||||
## Formatting custom types
|
||||
|
||||
You can provide a custom `AK::Formatter<Foo>` class to format `Foo` values. For the simplest case where you already have
|
||||
a function that produces a string from your type, that would look like this:
|
||||
|
||||
```c++
|
||||
template<>
|
||||
struct AK::Formatter<Web::CSS::Selector> : Formatter<StringView> {
|
||||
ErrorOr<void> format(FormatBuilder& builder, Web::CSS::Selector const& selector)
|
||||
{
|
||||
return Formatter<StringView>::format(builder, selector.serialize());
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
More advanced formatters that make check for format-specifier flags can be written by referring to the fields
|
||||
in `StandardFormatter` (which most `Formatter` classes extend).
|
||||
|
||||
## Detecting if a type can be formatted
|
||||
|
||||
The `AK::HasFormatter<T>` template has a boolean value representing whether `T` can be formatted.
|
||||
|
||||
The `FormatIfSupported<T>` makes use of this to return either the formatted value of `T`, or a series of `?`s if the
|
||||
type cannot be formatted. For example:
|
||||
|
||||
```c++
|
||||
// B has a Formatter defined, but A does not.
|
||||
String::formatted("{}", FormatIfSupported { A {} }) == "?";
|
||||
String::formatted("{}", FormatIfSupported { B {} }) == "B";
|
||||
```
|
Loading…
Reference in a new issue