Casper

Reinventing Rust formatting syntax

In this post I’m announcing my crate fmtools, some links if you prefer those: github, crates.io, docs.rs.

Formatting large blocks of text interspersed with formatted values has always been really awkward in Rust (and other programming languages, really):

let values = [1, 2, 0, 4, 5];
let separator = "------------";

let s = format!("\
	First value: {}\n\
	Second value: {}\n\
	Third value: {}\n\
	{}\n\
	Fourth value: {}\n\
	Fifth value: {}\n",
	values[0], values[1], values[2],
	separator,
	values[3], values[4]);

Maintaining such code is hard enough, it becomes even more tricky if you only want to emit part of the formatting on some condition. Eg. only display the third line if the third value is non-zero.

There have been various attempts at making this use case work better in Rust but I haven’t been following any of the discussion and set out to do my own thing. I heard you can now use implicit identifiers in format arguments? Rookie stuff.

While formatting expressions in format strings has been implemented in other languages they tend to come with various restrictions:

Here’s an example of how control flow may come up expressed with consecutive print!:

let power = 0.5;

print!("At ");
if power >= 1.0 {
	print!("full");
}
else {
	print!("{:.0}%", power * 100.0);
}
print!(" power");

How would you express this simple task in an elegant format string?

I present to you my solution to these problems for both examples:

let values = [1, 2, 0, 4, 5];
let separator = "------------";

let s = fmtools::format! {
	"First value: "{values[0]}"\n"
	"Second value: "{values[1]}"\n"
	if values[2] != 0 {
		"Third value: "{values[2]}"\n"
	}
	{separator}"\n"
	"Fourth value: "{values[3]}"\n"
	"Fifth value: "{values[4]}"\n"
};
let power = 0.5;

fmtools::println!("At "
	if power >= 1.0 { "full" }
	else { {power * 100.0:.0}"%" }
	" power");

Implemented in a single, no_std compatible, zero dependencies crate: github, crates.io, docs.rs.

Features: