1use crate::style::{Color, Style};
2use crate::text::Span;
3
4pub trait Stylize {
15 fn style(self, style: Style) -> Span;
16 fn fg(self, color: Color) -> Span;
17 fn bg(self, color: Color) -> Span;
18
19 fn red(self) -> Span where Self: Sized { self.fg(Color::Red) }
20 fn green(self) -> Span where Self: Sized { self.fg(Color::Green) }
21 fn blue(self) -> Span where Self: Sized { self.fg(Color::Blue) }
22 fn cyan(self) -> Span where Self: Sized { self.fg(Color::Cyan) }
23 fn yellow(self) -> Span where Self: Sized { self.fg(Color::Yellow) }
24 fn magenta(self) -> Span where Self: Sized { self.fg(Color::Magenta) }
25 fn white(self) -> Span where Self: Sized { self.fg(Color::White) }
26 fn gray(self) -> Span where Self: Sized { self.fg(Color::Gray) }
27 fn black(self) -> Span where Self: Sized { self.fg(Color::Black) }
28
29 fn on_red(self) -> Span where Self: Sized { self.bg(Color::Red) }
30 fn on_green(self) -> Span where Self: Sized { self.bg(Color::Green) }
31 fn on_blue(self) -> Span where Self: Sized { self.bg(Color::Blue) }
32 fn on_cyan(self) -> Span where Self: Sized { self.bg(Color::Cyan) }
33 fn on_yellow(self) -> Span where Self: Sized { self.bg(Color::Yellow) }
34 fn on_magenta(self) -> Span where Self: Sized { self.bg(Color::Magenta) }
35 fn on_white(self) -> Span where Self: Sized { self.bg(Color::White) }
36 fn on_gray(self) -> Span where Self: Sized { self.bg(Color::Gray) }
37 fn on_black(self) -> Span where Self: Sized { self.bg(Color::Black) }
38
39 fn rgb(self, r: u8, g: u8, b: u8) -> Span where Self: Sized { self.fg(Color::Rgb(r, g, b)) }
40 fn on_rgb(self, r: u8, g: u8, b: u8) -> Span where Self: Sized { self.bg(Color::Rgb(r, g, b)) }
41 fn hex(self, hex: &str) -> Span where Self: Sized {
42 self.fg(Color::hex(hex).unwrap_or(Color::White))
43 }
44 fn on_hex(self, hex: &str) -> Span where Self: Sized {
45 self.bg(Color::hex(hex).unwrap_or(Color::White))
46 }
47
48 fn bold(self) -> Span where Self: Sized;
49 fn italic(self) -> Span where Self: Sized;
50 fn underline(self) -> Span where Self: Sized;
51}
52
53impl Stylize for &str {
54 fn style(self, style: Style) -> Span { Span { text: self.to_string(), style } }
55 fn fg(self, color: Color) -> Span { Span { text: self.to_string(), style: Style::default().fg(color) } }
56 fn bg(self, color: Color) -> Span { Span { text: self.to_string(), style: Style::default().bg(color) } }
57 fn bold(self) -> Span { Span { text: self.to_string(), style: Style::default().bold() } }
58 fn italic(self) -> Span { Span { text: self.to_string(), style: Style::default().italic() } }
59 fn underline(self) -> Span { Span { text: self.to_string(), style: Style::default().underline() } }
60}
61
62impl Stylize for String {
63 fn style(self, style: Style) -> Span { Span { text: self, style } }
64 fn fg(self, color: Color) -> Span { Span { text: self, style: Style::default().fg(color) } }
65 fn bg(self, color: Color) -> Span { Span { text: self, style: Style::default().bg(color) } }
66 fn bold(self) -> Span { Span { text: self, style: Style::default().bold() } }
67 fn italic(self) -> Span { Span { text: self, style: Style::default().italic() } }
68 fn underline(self) -> Span { Span { text: self, style: Style::default().underline() } }
69}
70
71impl Stylize for Span {
73 fn style(mut self, style: Style) -> Span {
74 self.style = crate::style_parser::merge_styles(self.style, &style);
75 self
76 }
77 fn fg(self, color: Color) -> Span { self.style(Style::default().fg(color)) }
78 fn bg(self, color: Color) -> Span { self.style(Style::default().bg(color)) }
79 fn bold(self) -> Span { self.style(Style::default().bold()) }
80 fn italic(self) -> Span { self.style(Style::default().italic()) }
81 fn underline(self) -> Span { self.style(Style::default().underline()) }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_red() {
90 let s = "hello".red();
91 assert_eq!(s.text, "hello");
92 assert_eq!(s.style.fg, Some(Color::Red));
93 }
94
95 #[test]
96 fn test_red_bold() {
97 let s = "hello".red().bold();
98 assert_eq!(s.text, "hello");
99 assert_eq!(s.style.fg, Some(Color::Red));
100 assert!(s.style.bold);
101 }
102
103 #[test]
104 fn test_on_blue_white() {
105 let s = "text".on_blue().white();
106 assert_eq!(s.style.bg, Some(Color::Blue));
107 assert_eq!(s.style.fg, Some(Color::White));
108 }
109
110 #[test]
111 fn test_chained_style() {
112 let s = "x".red().on_black().bold().italic();
113 assert_eq!(s.style.fg, Some(Color::Red));
114 assert_eq!(s.style.bg, Some(Color::Black));
115 assert!(s.style.bold);
116 assert!(s.style.italic);
117 }
118
119 #[test]
120 fn test_string_impl() {
121 let s = String::from("hi").green();
122 assert_eq!(s.text, "hi");
123 assert_eq!(s.style.fg, Some(Color::Green));
124 }
125
126 #[test]
127 fn test_gray() {
128 let s = "dim".gray();
129 assert_eq!(s.style.fg, Some(Color::Gray));
130 }
131
132 #[test]
133 fn test_bg_methods() {
134 let s = "x".on_red().on_green();
135 assert_eq!(s.style.bg, Some(Color::Green));
136 }
137}