anstream println field witdth is not aware of color codes
I would expect the following (rather silly minimal case) to align columns properly:
use anstream::println;
use anstyle::AnsiColor;
use anstyle::Reset;
enum MyLogLevel {
Ok,
Warn,
Error,
}
impl std::fmt::Display for MyLogLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MyLogLevel::Ok => write!(f, "{}Ok{}", AnsiColor::Green.render_fg(), Reset.render()),
MyLogLevel::Warn => write!(
f,
"{}Warning{}",
AnsiColor::Yellow.render_fg(),
Reset.render()
),
MyLogLevel::Error => write!(f, "{}Error{}", AnsiColor::Red.render_fg(), Reset.render()),
}
}
}
fn main() {
println!("{:<10} Everything is fine", "Ok");
println!("{:<10} Be careful", "Warning");
println!("{:<10} BAD BAD BAD", "Error");
println!("{:<10} Everything is fine", MyLogLevel::Ok);
println!("{:<10} Be careful", MyLogLevel::Warn);
println!("{:<10} BAD BAD BAD", MyLogLevel::Error);
}
It prints:
Ok Everything is fine
Warning Be careful
Error BAD BAD BAD
Ok Everything is fine
Warning Be careful
Error BAD BAD BAD
This is unexpected. So it seems the anstream println is not properly aware of how wide colour codes are.
I ran into something sort-of similar in env_logger. The way I worked around it is controlling what i used write! on vs what I called .fmt(f) on, see https://github.com/rust-cli/env_logger/commit/303a9c0ed288c5c7c15b6a74e29bfc1467bf9eab
From that experience, I think the problem is that write! doesn't handle any of the format specifiers itself and does not forward them on. I reproduced this with std at https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0409fd1ae8ddd4d6b6e98ec9903dce7e
So to get his to work, you'd need to do something similar to what I did in env_logger, use write! for the styling and .fmt(f) on the text.
@epage Thank you, this does indeed work! Perhaps it should be documented in anstyle somewhere? It seems like a bit of a gotcha.
I'm not sure how to fit this in. This is a problem specifically when you are creating a wrapper type for Display and is a problem independent of whether anstyle is in use or not.
That is a fair point. I would assume it is somewhat common to abstract away and use traits though. The code ends up a lot nicer that way.