1pub mod no_color;
2pub mod styles;
3pub mod color;
4
5use std::borrow::{Cow};
6use std::error::Error;
7use std::fmt::{Debug, Display, Formatter};
8pub use crate::color::{DefaultColor, Color, DisplayColor, EightBitColor, TrueColor};
9pub use styles::{Styles, Style};
10
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14#[derive(Debug, Clone, Default)]
15pub struct StylesContainer {
16 pub text_color: Option<Color>,
17 pub background_color: Option<Color>,
18 #[cfg_attr(feature = "serde", serde(default))]
19 pub styles: Vec<Style>,
20}
21
22
23#[derive(Debug)]
24pub struct InvalidStyleError;
25
26impl Display for InvalidStyleError {
27 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
28 writeln!(f, "The Value provided is not compatible with ANSI escape code standards")
29 }
30}
31
32impl Error for InvalidStyleError {}
33
34#[derive(Debug, Clone)]
37pub struct StyledString<'content> {
38 content: &'content str,
40 styles: Cow<'content, StylesContainer>,
41}
42
43impl<'content> Display for StyledString<'content> {
44 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
45 if !no_color::show_styles() {
46 return Display::fmt(&self.content, f);
47 }
48 for style in &self.styles.styles {
49 Display::fmt(&style, f)?;
50 }
51 if let Some(background) = self.styles.background_color.as_ref() {
52 background.fmt_background(f)?;
53 }
54 if let Some(color) = self.styles.text_color.as_ref() {
55 color.fmt_color(f)?;
56 }
57 write!(f, "{}{}", self.content, styles::RESET)
58 }
59}
60
61impl<'content> StyledString<'content> {
62 pub(crate) fn new(content: &'content str) -> StyledString {
63 StyledString {
64 content,
65 styles: Cow::Owned(StylesContainer::default()),
66 }
67 }
68 pub fn text_color<C: Into<Color>>(mut self, text: C) -> Self {
69 self.styles.to_mut().text_color = Some(text.into());
70 self
71 }
72 pub fn background_color<C: Into<Color>>(mut self, text: C) -> Self {
73 self.styles.to_mut().background_color = Some(text.into());
74 self
75 }
76
77 pub fn add_style<S: Into<Style>>(mut self, style: S) -> Self {
78 self.styles.to_mut().styles.push(style.into());
79 self
80 }
81}
82
83pub trait StyleString {
85 fn style(&self) -> StyledString;
87
88 fn apply_styles<'content>(&'content self, styles: &'content StylesContainer) -> StyledString<'content> {
90 let mut styled = self.style();
91 styled.styles = Cow::Borrowed(styles);
92 styled
93 }
94}
95
96impl StyleString for String {
97 fn style(&self) -> StyledString {
98 StyledString::new(self.as_str())
99 }
100}
101
102impl<'content> StyleString for &'content String {
103 fn style(&self) -> StyledString<'content> {
104 StyledString::new(self.as_str())
105 }
106}
107
108impl<'content> StyleString for &'content str {
109 fn style(&self) -> StyledString {
110 StyledString::new(self)
111 }
112}
113
114
115#[cfg(test)]
116pub mod test {
117 use std::fs::File;
118 use std::io::Write;
119 use crate::{Color, DefaultColor, EightBitColor, StyleString, TrueColor};
120 use crate::color::FourBitColor;
121 use crate::styles::Styles;
122
123 #[test]
124 pub fn general_test() {
125 println!("{}", "Bright Blue BG: Black Bold".style().text_color(DefaultColor::BrightBlue).background_color(FourBitColor::Black).add_style(Styles::Bold));
126 println!("{}", "Bright Blue BG: Black Italic".style().text_color(DefaultColor::BrightBlue).background_color(FourBitColor::Black).add_style(Styles::Italic));
127 println!("{}", "Bright Blue BG: Black Reset".style().text_color(DefaultColor::BrightBlue).background_color(FourBitColor::Black).add_style(Styles::Reset));
128 println!("{}", "Bright Blue BG: Black Underline".style().text_color(DefaultColor::BrightBlue).background_color(FourBitColor::Black).add_style(Styles::Underline));
129 println!("{}", "Bright Blue BG: Black".style().text_color(DefaultColor::BrightBlue).background_color(FourBitColor::Black));
130 }
131
132 #[test]
133 pub fn serde_test() {
134 let true_color = Color::TrueColor(TrueColor::from((5, 5, 5)));
135 let eight_bit_color = Color::EightBitColor(EightBitColor::from(5));
136 let four_bit_color = Color::FourBitColor(FourBitColor::Black);
137 println!("true_color: {}", serde_json::to_string_pretty(&true_color).unwrap());
138 println!("eight_bit_color: {}", serde_json::to_string_pretty(&eight_bit_color).unwrap());
139 println!("for_bit_color: {}", serde_json::to_string_pretty(&four_bit_color).unwrap());
140 }
141}