use std::{borrow::Cow, str::FromStr}; /// The 8 standard colors. #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[allow(missing_docs)] pub enum Color { Black, Red, Green, Yellow, Blue, Magenta, Cyan, White, BrightBlack, BrightRed, BrightGreen, BrightYellow, BrightBlue, BrightMagenta, BrightCyan, BrightWhite, TrueColor { r: u8, g: u8, b: u8 }, } #[allow(missing_docs)] impl Color { pub fn to_fg_str(&self) -> Cow<'static, str> { match *self { Color::Black => "30".into(), Color::Red => "31".into(), Color::Green => "32".into(), Color::Yellow => "33".into(), Color::Blue => "34".into(), Color::Magenta => "35".into(), Color::Cyan => "36".into(), Color::White => "37".into(), Color::BrightBlack => "90".into(), Color::BrightRed => "91".into(), Color::BrightGreen => "92".into(), Color::BrightYellow => "93".into(), Color::BrightBlue => "94".into(), Color::BrightMagenta => "95".into(), Color::BrightCyan => "96".into(), Color::BrightWhite => "97".into(), Color::TrueColor { r, g, b } => format!("38;2;{};{};{}", r, g, b).into(), } } pub fn to_bg_str(&self) -> Cow<'static, str> { match *self { Color::Black => "40".into(), Color::Red => "41".into(), Color::Green => "42".into(), Color::Yellow => "43".into(), Color::Blue => "44".into(), Color::Magenta => "45".into(), Color::Cyan => "46".into(), Color::White => "47".into(), Color::BrightBlack => "100".into(), Color::BrightRed => "101".into(), Color::BrightGreen => "102".into(), Color::BrightYellow => "103".into(), Color::BrightBlue => "104".into(), Color::BrightMagenta => "105".into(), Color::BrightCyan => "106".into(), Color::BrightWhite => "107".into(), Color::TrueColor { r, g, b } => format!("48;2;{};{};{}", r, g, b).into(), } } } impl<'a> From<&'a str> for Color { fn from(src: &str) -> Self { src.parse().unwrap_or(Color::White) } } impl From for Color { fn from(src: String) -> Self { src.parse().unwrap_or(Color::White) } } impl FromStr for Color { type Err = (); fn from_str(src: &str) -> Result { let src = src.to_lowercase(); match src.as_ref() { "black" => Ok(Color::Black), "red" => Ok(Color::Red), "green" => Ok(Color::Green), "yellow" => Ok(Color::Yellow), "blue" => Ok(Color::Blue), "magenta" => Ok(Color::Magenta), "purple" => Ok(Color::Magenta), "cyan" => Ok(Color::Cyan), "white" => Ok(Color::White), "bright black" => Ok(Color::BrightBlack), "bright red" => Ok(Color::BrightRed), "bright green" => Ok(Color::BrightGreen), "bright yellow" => Ok(Color::BrightYellow), "bright blue" => Ok(Color::BrightBlue), "bright magenta" => Ok(Color::BrightMagenta), "bright cyan" => Ok(Color::BrightCyan), "bright white" => Ok(Color::BrightWhite), _ => Err(()), } } } #[cfg(test)] mod tests { pub use super::*; mod from_str { pub use super::*; macro_rules! make_test { ( $( $name:ident: $src:expr => $dst:expr),* ) => { $( #[test] fn $name() { let color : Color = $src.into(); assert_eq!($dst, color) } )* } } make_test!( black: "black" => Color::Black, red: "red" => Color::Red, green: "green" => Color::Green, yellow: "yellow" => Color::Yellow, blue: "blue" => Color::Blue, magenta: "magenta" => Color::Magenta, purple: "purple" => Color::Magenta, cyan: "cyan" => Color::Cyan, white: "white" => Color::White, brightblack: "bright black" => Color::BrightBlack, brightred: "bright red" => Color::BrightRed, brightgreen: "bright green" => Color::BrightGreen, brightyellow: "bright yellow" => Color::BrightYellow, brightblue: "bright blue" => Color::BrightBlue, brightmagenta: "bright magenta" => Color::BrightMagenta, brightcyan: "bright cyan" => Color::BrightCyan, brightwhite: "bright white" => Color::BrightWhite, invalid: "invalid" => Color::White, capitalized: "BLUE" => Color::Blue, mixed_case: "bLuE" => Color::Blue ); } mod from_string { pub use super::*; macro_rules! make_test { ( $( $name:ident: $src:expr => $dst:expr),* ) => { $( #[test] fn $name() { let src = String::from($src); let color : Color = src.into(); assert_eq!($dst, color) } )* } } make_test!( black: "black" => Color::Black, red: "red" => Color::Red, green: "green" => Color::Green, yellow: "yellow" => Color::Yellow, blue: "blue" => Color::Blue, magenta: "magenta" => Color::Magenta, cyan: "cyan" => Color::Cyan, white: "white" => Color::White, brightblack: "bright black" => Color::BrightBlack, brightred: "bright red" => Color::BrightRed, brightgreen: "bright green" => Color::BrightGreen, brightyellow: "bright yellow" => Color::BrightYellow, brightblue: "bright blue" => Color::BrightBlue, brightmagenta: "bright magenta" => Color::BrightMagenta, brightcyan: "bright cyan" => Color::BrightCyan, brightwhite: "bright white" => Color::BrightWhite, invalid: "invalid" => Color::White, capitalized: "BLUE" => Color::Blue, mixed_case: "bLuE" => Color::Blue ); } mod fromstr { pub use super::*; #[test] fn parse() { let color: Result = "blue".parse(); assert_eq!(Ok(Color::Blue), color) } #[test] fn error() { let color: Result = "bloublou".parse(); assert_eq!(Err(()), color) } } }