anstyle icon indicating copy to clipboard operation
anstyle copied to clipboard

anstream println field witdth is not aware of color codes

Open VorpalBlade opened this issue 2 years ago • 4 comments

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.

VorpalBlade avatar Jan 28 '24 15:01 VorpalBlade

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 avatar Jan 29 '24 17:01 epage

@epage Thank you, this does indeed work! Perhaps it should be documented in anstyle somewhere? It seems like a bit of a gotcha.

VorpalBlade avatar Feb 03 '24 18:02 VorpalBlade

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.

epage avatar Feb 05 '24 17:02 epage

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.

VorpalBlade avatar Feb 05 '24 20:02 VorpalBlade