<h1 align="center">formatx</h1>
[](https://crates.io/formatx)
[](https://crates.io/crates/formatx)
[](https://github.com/clitic/formatx/actions)
[](https://docs.rs/formatx)
[](https://crates.io/crates/formatx)
[](https://github.com/clitic/formatx)
`formatx` lets you format strings at runtime using the same syntax as [`std::fmt`] (`{}`, `{:?}`, `{name}`, etc.), but with runtime template strings instead of compile-time literals with **zero** dependencies.
<div align="center">
<img src="https://raw.githubusercontent.com/clitic/formatx/refs/heads/main/images/benchmark.svg" width="700px">
</div>
## Getting Started
Add this to your `Cargo.toml` file.
```toml
[dependencies]
formatx = "0.3"
```
Or add from command line.
```bash
cargo add formatx
```
See [docs](https://docs.rs/formatx) and [examples](https://github.com/clitic/formatx/tree/main/examples) to know how to use it.
## Examples
### Using [`formatx!`](https://docs.rs/formatx/latest/formatx/macro.formatx.html)
Works just like [`format!`](https://doc.rust-lang.org/std/macro.format.html), but accepts runtime template strings.
```rust
use formatx::formatx;
let template = "{} scored {score:.1}% in {}";
let result = formatx!(template, "Alice", "maths", score = 95.678).unwrap();
assert_eq!(result, "Alice scored 95.7% in maths");
```
> [!NOTE]
> Extra arguments that aren't referenced by any placeholder are silently ignored in both `formatx!` and `formatxl!`.
### Template Reuse
Parse once, render many times with [`Template`](https://docs.rs/formatx/latest/formatx/struct.Template.html).
```rust
use formatx::Template;
let template = Template::new("{name} has {n} items").unwrap();
let r1 = template.render()
.named("name", &"Alice")
.named("n", &3)
.finish()
.unwrap();
let r2 = template.render()
.named("name", &"Bob")
.named("n", &7)
.finish()
.unwrap();
assert_eq!(r1, "Alice has 3 items");
assert_eq!(r2, "Bob has 7 items");
```
## Supported Syntax
`formatx` supports most of the [`std::fmt`] formatting syntax:
| Implicit positional | `{}` | ✅ |
| Explicit positional | `{0} {1}` | ✅ |
| Named arguments | `{name}` | ✅ |
| Mixed positional | `{1} {} {0} {}` | ✅ |
| Debug | `{:?}`, `{:#?}` | ✅ |
| Debug hex | `{:x?}`, `{:X?}` | ✅ |
| Width | `{:10}` | ✅ |
| Precision | `{:.5}` | ✅ |
| Fill and align | `{:-<10}`, `{:^10}`, `{:*>10}` | ✅ |
| Sign | `{:+}` | ✅ |
| Alternate | `{:#}` | ✅ |
| Zero-pad | `{:05}` | ✅ |
| `$`-parameter width/precision | `{:width$}`, `{:.prec$}` | ✅ |
| Star precision | `{:.*}` | ✅ |
| Escaped braces | `{{` `}}` | ✅ |
| LowerHex | `{:x}` | ❌ |
| UpperHex | `{:X}` | ❌ |
| Octal | `{:o}` | ❌ |
| Binary | `{:b}` | ❌ |
| LowerExp | `{:e}` | ❌ |
| UpperExp | `{:E}` | ❌ |
| Pointer | `{:p}` | ❌ |
> [!NOTE]
> Only types implementing [`Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html) + [`Debug`](https://doc.rust-lang.org/std/fmt/trait.Debug.html) are supported. Other [formatting traits](https://doc.rust-lang.org/std/fmt/#formatting-traits) (`LowerHex`, `Binary`, `Octal`, etc.) are not supported and will return [`Error::UnsupportedTrait`](https://docs.rs/formatx/latest/formatx/enum.Error.html#variant.UnsupportedTrait).
> [!NOTE]
> Local variable interpolation is not supported since template strings are parsed at runtime.
>
> ```rust
> let people = "Rustaceans";
> // This will NOT interpolate `people` - use named args instead:
> formatx!("Hello {people}!", people = people).unwrap();
> ```
## Status
[](https://repology.org/project/rust%3Aformatx/versions)
## License
Dual Licensed
- [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) ([LICENSE-APACHE](LICENSE-APACHE))
- [MIT license](https://opensource.org/licenses/MIT) ([LICENSE-MIT](LICENSE-MIT))
[`std::fmt`]: https://doc.rust-lang.org/std/fmt/#syntax