I wanted to imitate Python's rjust, ljust, and center functions using the format! macro, but I was only able to work out a solution where you can pass in the string and the width. If you want to pass in the fill-argument it doesn't work.
The documentation tells me that it is possible to provide variables to format! and for the width argument it works just fine. When I try to use a variable for fill, the compiler does not recognize the pattern.
Just the width as a variable works:
fn rjust(text: &str, width: usize, fill: Option<char>) -> String {
format!("{text:>width$}", text = text, width = width)
}
println!("{}", rjust("Hello", 10)); // " Hello"
Providing the fill as a variable does not work:
fn rjust(text: &str, width: usize, fill: char) -> String {
format!(
"{text:fill>width$}",
text = text,
fill = fill,
width = width
)
}
println!("{}", rjust("Hello", 20, '*'));
The error message:
error: invalid format string: expected `'}'`, found `'>'`
--> src/lib.rs:4:24
|
4 | "{text:fill>width$}",
| - ^ expected `}` in format string
| |
| because of this opening brace
|
= note: if you intended to print `{`, you can escape it using `{{`
If I provide a single character instead of the fill-variable, it works fine. Notice the * character:
fn rjust(text: &str, width: usize, fill: char) -> String {
format!("{text:*>width$}", text = text, width = width)
}
println!("{}", rjust("Hello", 20, '_')); // ***************Hello
I expected the fill-variable version to work the same as the hardcoded * character version.
A workaround is to subtract the length of the text from the width and then create a String of that length (fill-length) made of fill-characters and concatenate them:
fn rjust(text: &str, width: usize, fill: char) -> String {
let fill_len = width - text.len();
let fill_str: String = (0..fill_len).map(|_| fill).collect();
String::from(fill_str + text)
}
println!("{}", rjust("Hello", 20, '*')); // ***************Hello