1 use 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)] 30 pub struct Colors { 31 pub foreground: Option<Color>, 32 pub background: Option<Color>, 33 } 34 35 impl Colors { 36 /// Returns a new `Color` which, when applied, has the same effect as applying `self` and *then* 37 /// `other`. then(&self, other: &Colors) -> Colors38 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 46 impl Colors { new(foreground: Color, background: Color) -> Colors47 pub fn new(foreground: Color, background: Color) -> Colors { 48 Colors { 49 foreground: Some(foreground), 50 background: Some(background), 51 } 52 } 53 } 54 55 impl From<Colored> for Colors { from(colored: Colored) -> Colors56 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 } 67 } 68 } 69 70 #[cfg(test)] 71 mod tests { 72 use crate::style::{Color, Colors}; 73 74 #[test] test_colors_then()75 fn test_colors_then() { 76 use Color::*; 77 78 assert_eq!( 79 Colors { 80 foreground: None, 81 background: None, 82 } 83 .then(&Colors { 84 foreground: None, 85 background: None, 86 }), 87 Colors { 88 foreground: None, 89 background: None, 90 } 91 ); 92 93 assert_eq!( 94 Colors { 95 foreground: None, 96 background: None, 97 } 98 .then(&Colors { 99 foreground: Some(Black), 100 background: None, 101 }), 102 Colors { 103 foreground: Some(Black), 104 background: None, 105 } 106 ); 107 108 assert_eq!( 109 Colors { 110 foreground: None, 111 background: None, 112 } 113 .then(&Colors { 114 foreground: None, 115 background: Some(Grey), 116 }), 117 Colors { 118 foreground: None, 119 background: Some(Grey), 120 } 121 ); 122 123 assert_eq!( 124 Colors { 125 foreground: None, 126 background: None, 127 } 128 .then(&Colors::new(White, Grey)), 129 Colors::new(White, Grey), 130 ); 131 132 assert_eq!( 133 Colors { 134 foreground: None, 135 background: Some(Blue), 136 } 137 .then(&Colors::new(White, Grey)), 138 Colors::new(White, Grey), 139 ); 140 141 assert_eq!( 142 Colors { 143 foreground: Some(Blue), 144 background: None, 145 } 146 .then(&Colors::new(White, Grey)), 147 Colors::new(White, Grey), 148 ); 149 150 assert_eq!( 151 Colors::new(Blue, Green).then(&Colors::new(White, Grey)), 152 Colors::new(White, Grey), 153 ); 154 155 assert_eq!( 156 Colors { 157 foreground: Some(Blue), 158 background: Some(Green), 159 } 160 .then(&Colors { 161 foreground: None, 162 background: Some(Grey), 163 }), 164 Colors { 165 foreground: Some(Blue), 166 background: Some(Grey), 167 } 168 ); 169 170 assert_eq!( 171 Colors { 172 foreground: Some(Blue), 173 background: Some(Green), 174 } 175 .then(&Colors { 176 foreground: Some(White), 177 background: None, 178 }), 179 Colors { 180 foreground: Some(White), 181 background: Some(Green), 182 } 183 ); 184 185 assert_eq!( 186 Colors { 187 foreground: Some(Blue), 188 background: Some(Green), 189 } 190 .then(&Colors { 191 foreground: None, 192 background: None, 193 }), 194 Colors { 195 foreground: Some(Blue), 196 background: Some(Green), 197 } 198 ); 199 200 assert_eq!( 201 Colors { 202 foreground: None, 203 background: Some(Green), 204 } 205 .then(&Colors { 206 foreground: None, 207 background: None, 208 }), 209 Colors { 210 foreground: None, 211 background: Some(Green), 212 } 213 ); 214 215 assert_eq!( 216 Colors { 217 foreground: Some(Blue), 218 background: None, 219 } 220 .then(&Colors { 221 foreground: None, 222 background: None, 223 }), 224 Colors { 225 foreground: Some(Blue), 226 background: None, 227 } 228 ); 229 } 230 } 231