Skip to main content

crossterm/style/types/
colors.rs

1use crate::style::{Color, Colored};
2
3/// Represents, optionally, a foreground and/or a background color.
4///
5/// It can be applied using the `SetColors` command.
6///
7/// It can also be created from a [Colored](enum.Colored.html) value or a tuple of
8/// `(Color, Color)` in the order `(foreground, background)`.
9///
10/// The [then](#method.then) method can be used to combine `Colors` values.
11///
12/// For example:
13/// ```no_run
14/// use crossterm::style::{Color, Colors, Colored};
15///
16/// // An example color, loaded from a config, file in ANSI format.
17/// let config_color = "38;2;23;147;209";
18///
19/// // Default to green text on a black background.
20/// let default_colors = Colors::new(Color::Green, Color::Black);
21/// // Load a colored value from a config and override the default colors
22/// let colors = match Colored::parse_ansi(config_color) {
23///     Some(colored) => default_colors.then(&colored.into()),
24///     None => default_colors,
25/// };
26/// ```
27///
28/// See [Color](enum.Color.html).
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub struct Colors {
31    pub foreground: Option<Color>,
32    pub background: Option<Color>,
33}
34
35impl Colors {
36    /// Returns a new `Color` which, when applied, has the same effect as applying `self` and *then*
37    /// `other`.
38    pub fn then(&self, other: &Colors) -> Colors {
39        Colors {
40            foreground: other.foreground.or(self.foreground),
41            background: other.background.or(self.background),
42        }
43    }
44}
45
46impl Colors {
47    pub fn new(foreground: Color, background: Color) -> Colors {
48        Colors {
49            foreground: Some(foreground),
50            background: Some(background),
51        }
52    }
53}
54
55impl From<Colored> for Colors {
56    fn from(colored: Colored) -> Colors {
57        match colored {
58            Colored::ForegroundColor(color) => Colors {
59                foreground: Some(color),
60                background: None,
61            },
62            Colored::BackgroundColor(color) => Colors {
63                foreground: None,
64                background: Some(color),
65            },
66            Colored::UnderlineColor(color) => Colors {
67                foreground: None,
68                background: Some(color),
69            },
70        }
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use crate::style::{Color, Colors};
77
78    #[test]
79    fn test_colors_then() {
80        use Color::*;
81
82        assert_eq!(
83            Colors {
84                foreground: None,
85                background: None,
86            }
87            .then(&Colors {
88                foreground: None,
89                background: None,
90            }),
91            Colors {
92                foreground: None,
93                background: None,
94            }
95        );
96
97        assert_eq!(
98            Colors {
99                foreground: None,
100                background: None,
101            }
102            .then(&Colors {
103                foreground: Some(Black),
104                background: None,
105            }),
106            Colors {
107                foreground: Some(Black),
108                background: None,
109            }
110        );
111
112        assert_eq!(
113            Colors {
114                foreground: None,
115                background: None,
116            }
117            .then(&Colors {
118                foreground: None,
119                background: Some(Grey),
120            }),
121            Colors {
122                foreground: None,
123                background: Some(Grey),
124            }
125        );
126
127        assert_eq!(
128            Colors {
129                foreground: None,
130                background: None,
131            }
132            .then(&Colors::new(White, Grey)),
133            Colors::new(White, Grey),
134        );
135
136        assert_eq!(
137            Colors {
138                foreground: None,
139                background: Some(Blue),
140            }
141            .then(&Colors::new(White, Grey)),
142            Colors::new(White, Grey),
143        );
144
145        assert_eq!(
146            Colors {
147                foreground: Some(Blue),
148                background: None,
149            }
150            .then(&Colors::new(White, Grey)),
151            Colors::new(White, Grey),
152        );
153
154        assert_eq!(
155            Colors::new(Blue, Green).then(&Colors::new(White, Grey)),
156            Colors::new(White, Grey),
157        );
158
159        assert_eq!(
160            Colors {
161                foreground: Some(Blue),
162                background: Some(Green),
163            }
164            .then(&Colors {
165                foreground: None,
166                background: Some(Grey),
167            }),
168            Colors {
169                foreground: Some(Blue),
170                background: Some(Grey),
171            }
172        );
173
174        assert_eq!(
175            Colors {
176                foreground: Some(Blue),
177                background: Some(Green),
178            }
179            .then(&Colors {
180                foreground: Some(White),
181                background: None,
182            }),
183            Colors {
184                foreground: Some(White),
185                background: Some(Green),
186            }
187        );
188
189        assert_eq!(
190            Colors {
191                foreground: Some(Blue),
192                background: Some(Green),
193            }
194            .then(&Colors {
195                foreground: None,
196                background: None,
197            }),
198            Colors {
199                foreground: Some(Blue),
200                background: Some(Green),
201            }
202        );
203
204        assert_eq!(
205            Colors {
206                foreground: None,
207                background: Some(Green),
208            }
209            .then(&Colors {
210                foreground: None,
211                background: None,
212            }),
213            Colors {
214                foreground: None,
215                background: Some(Green),
216            }
217        );
218
219        assert_eq!(
220            Colors {
221                foreground: Some(Blue),
222                background: None,
223            }
224            .then(&Colors {
225                foreground: None,
226                background: None,
227            }),
228            Colors {
229                foreground: Some(Blue),
230                background: None,
231            }
232        );
233    }
234}