colored-rs / colored

(Rust) Coloring terminal so simple you already know how to do it !
Mozilla Public License 2.0
1.68k stars 82 forks source link

Is there any way to clean a string which wasn't initially stored as colored #100

Closed zhiburt closed 2 years ago

zhiburt commented 3 years ago

I hope this example will make clear what I mean. Currently this test fails but is there any way to make it work?

        use colored::Colorize;
        let a = "something";
        let b = a.red().to_string();
        let c = a.clear().to_string();
        assert_eq!(a, c);
spenserblack commented 3 years ago

Does the behavior in #99 help answer your question? Basically, to get the initial string, you can dereference the ColoredString.

zhiburt commented 3 years ago

I could believe that you're right according to ColoredString but what if we have a String like on my example. We no longer have that information and as I understand we can't recover this.

This fails.

use std::ops::Deref;
use colored::{ColoredString, Colorize};

fn main() {
    let a = "something";
    let b = a.red().to_string();
    let c = ColoredString::from(b.as_str());
    assert_eq!(a, c.deref());
}
spenserblack commented 3 years ago
#[cfg(test)]
mod tests {
    use colored::Colorize;

    #[test]
    fn deref() {
        let a = "foo";
        let b = a.red();
        assert_eq!(a, &*b);
    }
}

Without more info, I'm not sure why 3 variables is necessary instead of only 2. But when you call to_string, you're converting it to a string with the colorization. If you need 3 variables, I guess you can do this.

#[cfg(test)]
mod tests {
    use colored::Colorize;

    #[test]
    fn deref() {
        let a = "foo";
        let b = a.red();
        let c = &*b;
        let b = b.to_string(); // shadow b to make it a string
        assert_eq!(a, c);
    }
}
mackwic commented 2 years ago

Hi @zhiburt thank you for reporting this edge case. This is non-intuitive, but to be expected as Colored is only adding new color codes characters to an existing string... one of which is named clear and will reset the default terminal coloring settings.

It's a new character in the string, so it's expected that s.clear().to_string() is not the same as s.

We may add a string cleaner in the future if there is demand but right now we don't have any.

Best, Thomas