diff --git a/examples/scrollbar.rs b/examples/scrollbar.rs index 20f34ef1..8b00720f 100644 --- a/examples/scrollbar.rs +++ b/examples/scrollbar.rs @@ -124,7 +124,7 @@ fn ui(f: &mut Frame, app: &mut App) { Line::from("This is a line ".red()), Line::from("This is a line".on_dark_gray()), Line::from("This is a longer line".crossed_out()), - Line::from(long_line.reset()), + Line::from(long_line.clone()), Line::from("This is a line".reset()), Line::from(vec![ Span::raw("Masked text: "), @@ -137,7 +137,7 @@ fn ui(f: &mut Frame, app: &mut App) { Line::from("This is a line ".red()), Line::from("This is a line".on_dark_gray()), Line::from("This is a longer line".crossed_out()), - Line::from(long_line.reset()), + Line::from(long_line.clone()), Line::from("This is a line".reset()), Line::from(vec![ Span::raw("Masked text: "), diff --git a/src/style/stylize.rs b/src/style/stylize.rs index 281532f8..a0f2a08d 100644 --- a/src/style/stylize.rs +++ b/src/style/stylize.rs @@ -179,16 +179,145 @@ impl<'a> Styled for &'a str { } } +impl Styled for String { + type Item = Span<'static>; + + fn style(&self) -> Style { + Style::default() + } + + fn set_style(self, style: Style) -> Self::Item { + Span::styled(self, style) + } +} + #[cfg(test)] mod tests { + use itertools::Itertools; + use super::*; + #[test] + fn str_styled() { + assert_eq!("hello".style(), Style::default()); + assert_eq!( + "hello".set_style(Style::new().cyan()), + Span::styled("hello", Style::new().cyan()) + ); + assert_eq!("hello".black(), Span::from("hello").black()); + assert_eq!("hello".red(), Span::from("hello").red()); + assert_eq!("hello".green(), Span::from("hello").green()); + assert_eq!("hello".yellow(), Span::from("hello").yellow()); + assert_eq!("hello".blue(), Span::from("hello").blue()); + assert_eq!("hello".magenta(), Span::from("hello").magenta()); + assert_eq!("hello".cyan(), Span::from("hello").cyan()); + assert_eq!("hello".gray(), Span::from("hello").gray()); + assert_eq!("hello".dark_gray(), Span::from("hello").dark_gray()); + assert_eq!("hello".light_red(), Span::from("hello").light_red()); + assert_eq!("hello".light_green(), Span::from("hello").light_green()); + assert_eq!("hello".light_yellow(), Span::from("hello").light_yellow()); + assert_eq!("hello".light_blue(), Span::from("hello").light_blue()); + assert_eq!("hello".light_magenta(), Span::from("hello").light_magenta()); + assert_eq!("hello".light_cyan(), Span::from("hello").light_cyan()); + assert_eq!("hello".white(), Span::from("hello").white()); + + assert_eq!("hello".on_black(), Span::from("hello").on_black()); + assert_eq!("hello".on_red(), Span::from("hello").on_red()); + assert_eq!("hello".on_green(), Span::from("hello").on_green()); + assert_eq!("hello".on_yellow(), Span::from("hello").on_yellow()); + assert_eq!("hello".on_blue(), Span::from("hello").on_blue()); + assert_eq!("hello".on_magenta(), Span::from("hello").on_magenta()); + assert_eq!("hello".on_cyan(), Span::from("hello").on_cyan()); + assert_eq!("hello".on_gray(), Span::from("hello").on_gray()); + assert_eq!("hello".on_dark_gray(), Span::from("hello").on_dark_gray()); + assert_eq!("hello".on_light_red(), Span::from("hello").on_light_red()); + assert_eq!( + "hello".on_light_green(), + Span::from("hello").on_light_green() + ); + assert_eq!( + "hello".on_light_yellow(), + Span::from("hello").on_light_yellow() + ); + assert_eq!("hello".on_light_blue(), Span::from("hello").on_light_blue()); + assert_eq!( + "hello".on_light_magenta(), + Span::from("hello").on_light_magenta() + ); + assert_eq!("hello".on_light_cyan(), Span::from("hello").on_light_cyan()); + assert_eq!("hello".on_white(), Span::from("hello").on_white()); + + assert_eq!("hello".bold(), Span::from("hello").bold()); + assert_eq!("hello".dim(), Span::from("hello").dim()); + assert_eq!("hello".italic(), Span::from("hello").italic()); + assert_eq!("hello".underlined(), Span::from("hello").underlined()); + assert_eq!("hello".slow_blink(), Span::from("hello").slow_blink()); + assert_eq!("hello".rapid_blink(), Span::from("hello").rapid_blink()); + assert_eq!("hello".reversed(), Span::from("hello").reversed()); + assert_eq!("hello".hidden(), Span::from("hello").hidden()); + assert_eq!("hello".crossed_out(), Span::from("hello").crossed_out()); + + assert_eq!("hello".not_bold(), Span::from("hello").not_bold()); + assert_eq!("hello".not_dim(), Span::from("hello").not_dim()); + assert_eq!("hello".not_italic(), Span::from("hello").not_italic()); + assert_eq!( + "hello".not_underlined(), + Span::from("hello").not_underlined() + ); + assert_eq!( + "hello".not_slow_blink(), + Span::from("hello").not_slow_blink() + ); + assert_eq!( + "hello".not_rapid_blink(), + Span::from("hello").not_rapid_blink() + ); + assert_eq!("hello".not_reversed(), Span::from("hello").not_reversed()); + assert_eq!("hello".not_hidden(), Span::from("hello").not_hidden()); + assert_eq!( + "hello".not_crossed_out(), + Span::from("hello").not_crossed_out() + ); + + assert_eq!("hello".reset(), Span::from("hello").reset()); + } + + #[test] + fn string_styled() { + let s = String::from("hello"); + assert_eq!(s.style(), Style::default()); + assert_eq!( + s.clone().set_style(Style::new().cyan()), + Span::styled("hello", Style::new().cyan()) + ); + assert_eq!(s.clone().black(), Span::from("hello").black()); + assert_eq!(s.clone().on_black(), Span::from("hello").on_black()); + assert_eq!(s.clone().bold(), Span::from("hello").bold()); + assert_eq!(s.clone().not_bold(), Span::from("hello").not_bold()); + assert_eq!(s.clone().reset(), Span::from("hello").reset()); + } + + #[test] + fn temporary_string_styled() { + // to_string() is used to create a temporary String, which is then styled. Without the + // `Styled` trait impl for `String`, this would fail to compile with the error: "temporary + // value dropped while borrowed" + let s = "hello".to_string().red(); + assert_eq!(s, Span::from("hello").red()); + + // format!() is used to create a temporary String inside a closure, which suffers the same + // issue as above without the `Styled` trait impl for `String` + let items = vec![String::from("a"), String::from("b")]; + let sss = items.iter().map(|s| format!("{s}{s}").red()).collect_vec(); + assert_eq!(sss, vec![Span::from("aa").red(), Span::from("bb").red()]); + } + #[test] fn reset() { assert_eq!( "hello".on_cyan().light_red().bold().underlined().reset(), Span::styled("hello", Style::reset()) - ) + ); } #[test] @@ -211,14 +340,14 @@ mod tests { .fg(Color::Cyan) .add_modifier(Modifier::BOLD); - assert_eq!("hello".cyan().bold(), Span::styled("hello", cyan_bold)) + assert_eq!("hello".cyan().bold(), Span::styled("hello", cyan_bold)); } #[test] fn fg_bg() { let cyan_fg_bg = Style::default().bg(Color::Cyan).fg(Color::Cyan); - assert_eq!("hello".cyan().on_cyan(), Span::styled("hello", cyan_fg_bg)) + assert_eq!("hello".cyan().on_cyan(), Span::styled("hello", cyan_fg_bg)); } #[test]