1use std::convert::From;
2use std::str::FromStr;
3
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6#[allow(missing_docs)]
7pub enum Color {
8 Black,
9 Red,
10 Green,
11 Yellow,
12 Blue,
13 Magenta,
14 Cyan,
15 White,
16 BrightBlack,
17 BrightRed,
18 BrightGreen,
19 BrightYellow,
20 BrightBlue,
21 BrightMagenta,
22 BrightCyan,
23 BrightWhite,
24 Palette(u8),
25 True(u8, u8, u8),
26}
27
28#[allow(missing_docs)]
29impl Color {
30 pub fn to_fg_str(&self) -> String {
31 match *self {
32 Color::Black => "30".to_owned(),
33 Color::Red => "31".to_owned(),
34 Color::Green => "32".to_owned(),
35 Color::Yellow => "33".to_owned(),
36 Color::Blue => "34".to_owned(),
37 Color::Magenta => "35".to_owned(),
38 Color::Cyan => "36".to_owned(),
39 Color::White => "37".to_owned(),
40 Color::BrightBlack => "90".to_owned(),
41 Color::BrightRed => "91".to_owned(),
42 Color::BrightGreen => "92".to_owned(),
43 Color::BrightYellow => "93".to_owned(),
44 Color::BrightBlue => "94".to_owned(),
45 Color::BrightMagenta => "95".to_owned(),
46 Color::BrightCyan => "96".to_owned(),
47 Color::BrightWhite => "97".to_owned(),
48 Color::Palette(code) => format!("38;5;{}", code),
49 Color::True(r, g, b) => format!("38;2;{};{};{}", r, g, b),
50 }
51 }
52
53 pub fn to_bg_str(&self) -> String {
54 match *self {
55 Color::Black => "40".to_owned(),
56 Color::Red => "41".to_owned(),
57 Color::Green => "42".to_owned(),
58 Color::Yellow => "43".to_owned(),
59 Color::Blue => "44".to_owned(),
60 Color::Magenta => "45".to_owned(),
61 Color::Cyan => "46".to_owned(),
62 Color::White => "47".to_owned(),
63 Color::BrightBlack => "100".to_owned(),
64 Color::BrightRed => "101".to_owned(),
65 Color::BrightGreen => "102".to_owned(),
66 Color::BrightYellow => "103".to_owned(),
67 Color::BrightBlue => "104".to_owned(),
68 Color::BrightMagenta => "105".to_owned(),
69 Color::BrightCyan => "106".to_owned(),
70 Color::BrightWhite => "107".to_owned(),
71 Color::Palette(code) => format!("48;5;{}", code),
72 Color::True(r, g, b) => format!("48;2;{};{};{}", r, g, b),
73 }
74 }
75}
76
77impl<'a> From<&'a str> for Color {
78 fn from(src: &str) -> Self {
79 src.parse().unwrap_or(Color::White)
80 }
81}
82
83impl From<String> for Color {
84 fn from(src: String) -> Self {
85 src.parse().unwrap_or(Color::White)
86 }
87}
88
89impl FromStr for Color {
90 type Err = ();
91
92 fn from_str(src: &str) -> Result<Self, Self::Err> {
93 let src = src.to_lowercase();
94
95 match src.as_ref() {
96 "black" => Ok(Color::Black),
97 "red" => Ok(Color::Red),
98 "green" => Ok(Color::Green),
99 "yellow" => Ok(Color::Yellow),
100 "blue" => Ok(Color::Blue),
101 "magenta" => Ok(Color::Magenta),
102 "purple" => Ok(Color::Magenta),
103 "cyan" => Ok(Color::Cyan),
104 "white" => Ok(Color::White),
105 "bright black" => Ok(Color::BrightBlack),
106 "bright red" => Ok(Color::BrightRed),
107 "bright green" => Ok(Color::BrightGreen),
108 "bright yellow" => Ok(Color::BrightYellow),
109 "bright blue" => Ok(Color::BrightBlue),
110 "bright magenta" => Ok(Color::BrightMagenta),
111 "bright cyan" => Ok(Color::BrightCyan),
112 "bright white" => Ok(Color::BrightWhite),
113 _ => Err(()),
114 }
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 pub use super::*;
121
122 mod from_str {
123 pub use super::*;
124
125 macro_rules! make_test {
126 ( $( $name:ident: $src:expr => $dst:expr),* ) => {
127
128 $(
129 #[test]
130 fn $name() {
131 let color : Color = $src.into();
132 assert_eq!($dst, color)
133 }
134 )*
135 }
136 }
137
138 make_test!(
139 black: "black" => Color::Black,
140 red: "red" => Color::Red,
141 green: "green" => Color::Green,
142 yellow: "yellow" => Color::Yellow,
143 blue: "blue" => Color::Blue,
144 magenta: "magenta" => Color::Magenta,
145 purple: "purple" => Color::Magenta,
146 cyan: "cyan" => Color::Cyan,
147 white: "white" => Color::White,
148 brightblack: "bright black" => Color::BrightBlack,
149 brightred: "bright red" => Color::BrightRed,
150 brightgreen: "bright green" => Color::BrightGreen,
151 brightyellow: "bright yellow" => Color::BrightYellow,
152 brightblue: "bright blue" => Color::BrightBlue,
153 brightmagenta: "bright magenta" => Color::BrightMagenta,
154 brightcyan: "bright cyan" => Color::BrightCyan,
155 brightwhite: "bright white" => Color::BrightWhite,
156
157 invalid: "invalid" => Color::White,
158 capitalized: "BLUE" => Color::Blue,
159 mixed_case: "bLuE" => Color::Blue
160 );
161 }
162
163 mod from_string {
164 pub use super::*;
165
166 macro_rules! make_test {
167 ( $( $name:ident: $src:expr => $dst:expr),* ) => {
168
169 $(
170 #[test]
171 fn $name() {
172 let src = String::from($src);
173 let color : Color = src.into();
174 assert_eq!($dst, color)
175 }
176 )*
177 }
178 }
179
180 make_test!(
181 black: "black" => Color::Black,
182 red: "red" => Color::Red,
183 green: "green" => Color::Green,
184 yellow: "yellow" => Color::Yellow,
185 blue: "blue" => Color::Blue,
186 magenta: "magenta" => Color::Magenta,
187 cyan: "cyan" => Color::Cyan,
188 white: "white" => Color::White,
189 brightblack: "bright black" => Color::BrightBlack,
190 brightred: "bright red" => Color::BrightRed,
191 brightgreen: "bright green" => Color::BrightGreen,
192 brightyellow: "bright yellow" => Color::BrightYellow,
193 brightblue: "bright blue" => Color::BrightBlue,
194 brightmagenta: "bright magenta" => Color::BrightMagenta,
195 brightcyan: "bright cyan" => Color::BrightCyan,
196 brightwhite: "bright white" => Color::BrightWhite,
197
198 invalid: "invalid" => Color::White,
199 capitalized: "BLUE" => Color::Blue,
200 mixed_case: "bLuE" => Color::Blue
201 );
202 }
203
204 mod fromstr {
205 pub use super::*;
206
207 #[test]
208 fn parse() {
209 let color: Result<Color, _> = "blue".parse();
210 assert_eq!(Ok(Color::Blue), color)
211 }
212
213 #[test]
214 fn error() {
215 let color: Result<Color, ()> = "bloublou".parse();
216 assert_eq!(Err(()), color)
217 }
218 }
219}