How to implement a generic function to apply `crossterm` style to any type which can be converted into a string

119 Views Asked by At

I would like to implement a generic function to apply style red and attribute bold to any type which can be converted into a string.

This function works, but only for &str arguments:

use crossterm::style::Stylize;

fn red(str: &str) -> <&str as Stylize>::Styled {
    str.red().bold()
}

I would like this function to work for instance in the following cases:

println!("{}", red("test"));
println!("{}", red("test".to_owned()));
println!("{}", red(1+1));

In all three cases, red text should be printed to the terminal. I tried the following implementation:

fn red<T: Stylize>(str: T) -> <T as Stylize>::Styled {
    str.red().bold()
}

but it does not compile, with message:

error[E0599]: no method named `bold` found for associated type `<T as Stylize>::Styled` in the current scope
  --> src\bin\orphanext-cli.rs:92:15
   |
92 |     str.red().bold()
   |               ^^^^ method not found in `<T as Stylize>::Styled`

I understand the meaning of the compiler message, but I cannot find a proper solution that works in all three cases listed above. Of course I would like the function to call to_string() only when necessary, so only for instance if I pass a i32, not if I pass a &str or a String.

In other words:

  • When I provide a &str the function should behave as the following one:
fn red(str: &str) -> <&str as Stylize>::Styled {
    str.red().bold()
}
  • When I provide a String the function should behave as the following one:
fn red(str: String) -> <String as Stylize>::Styled {
    str.red().bold()
}
  • When I provide a i32 (or any other type implementing trait Display) the function should behave as the following one:
fn red(num: i32) -> <String as Stylize>::Styled {
    num.to_string().red().bold()
}
0

There are 0 best solutions below