colored-rs / colored

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

Blanket implementation for `T: ToString`? #91

Open aldanor opened 3 years ago

aldanor commented 3 years ago

Why not implement this?

impl<T: ToString> Colorize for T {
    fn foo(&self) -> ColoredString { Colorize::foo(&self.to_string()) }
}

Note that this will also automatically cover all types that implement Display due to ToString's blanket implementation.

This way, you can, e.g.

println!("{} + {} = {}", 1.blue(), 2.red(), 3.green());

(and many other types)

kurtlawrence commented 3 years ago

Hi @aldanor,

I assume you meant ColoredString::from(&self.to_string()).

Without specialisation, implementing Colorize on any T precludes having more specified implementations that avoid allocation overheads. There is also the question of how does one implement Colorzie on a String or &str type? Should it be directed through the ToString implementation which does another allocation?

I can see the use case of have an implementation for types implementing ToString, an even better option would be to implement Colorize for types implementing AsRef<str> as this avoids unnecessary allocations.

If the use case is specific to Rust primitives, we could extend implementations of Colorize onto things likes floats and integers.

murlakatamenka commented 3 years ago

https://github.com/SergioBenitez/yansi#why:

Unlike ansi_term or colored, any type implementing Display or Debug can be stylized, not only strings.

Probably its source can help this issue.


For now

println!("{}", 42.to_string().green());

is the way to go with colored, right?

dbeckwith commented 3 years ago

I just found myself wanting to be able to apply colors to usize and std::path::Display, and realized I had to use .to_string() first. It would be great if the Colorize trait could be implemented for all types that implement Display, or at least provide a wrapper that can implement it like Colorable(42).green().

mainrs commented 3 years ago

Maybe as a workaround until specialized traits hit stable, a specific implementation for all primitives could be added to make this work for example:

println!("{}", 42.red());

Thoughts?

murlakatamenka commented 3 years ago

I'm sorry to mention another crate but I do it with the best intentions :smiley:

owo-colors | docs | github

owo-colors is also more-or-less a drop-in replacement for colored, allowing colored to work in a no_std environment. No allocations, unsafe, or dependencies required because embedded systems deserve to be pretty too uwu.

Just found it, exactly what I was looking for, so maybe it's what you need too?

mackwic commented 2 years ago

Thank you @murlakatamenka for prividing links to owo-colors and yansi, that's very interesting. It seems there's at least 2 forks that mimic colored, I wonder if we can unify that. I own my share of responsibility on that, as I've been unresponsive for 2 years.

There's no reason we can't have the best of all these worlds.

hwittenborn commented 1 year ago

Hey! I've recently joined the team for the project, and I'd like to start looking at getting this tackled.

I've thought about what might be best way to impl this (i.e. T: ToString, T: Display, etc.), and I think anything that implements Display would be the best target for this. From everything I've thought of, anything that implements Display should be terminal-friendly to look at, and likewise should have no problem having terminal coloring.

Without specialisation, implementing Colorize on any T precludes having more specified implementations that avoid allocation overheads. There is also the question of how does one implement Colorzie on a String or &str type? Should it be directed through the ToString implementation which does another allocation?

I can see the use case of have an implementation for types implementing ToString, an even better option would be to implement Colorize for types implementing AsRef<str> as this avoids unnecessary allocations.

From what I've read formatters don't necessarily do any allocations in themselves, but I'd have to look into what specific scenarios they end up doing so. Is there any places you'd know of where they for sure allocate?

If there's any way you were wanting to get this done as well @mackwic I'm definitely all ears for it. Really glad to just get this project going on it's feet!

mackwic commented 1 year ago

Considering my current available time, I'm not able to help on this, sorry.

hwittenborn commented 1 year ago

That sounds good @mackwic, I'll probably end up doing an impl Display solution solution then. If any of y'all got any other views on how to do it feel free to send them.

hwittenborn commented 1 year ago

What I'm thinking of doing is just having #139 be how anything can be formatted. It would be a breaking API change due to how items would have to be stored internally, but there's some other changes that I think could be good for the project (like implementing Add for ColoredStrings) that I think would merit a new v3 as well.

kurtlawrence commented 1 year ago

I think go with #139 and that will add this kind of functionality.