From f787eb75b63858bbc495dd7df1938f7ad52f2699 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Wed, 22 Jan 2020 00:06:14 +0200 Subject: ui/themes: add ThemeValue struct ThemeValue is either a Color or a theme key, meaning the value is linked to another key's value. --- ui/src/conf/themes.rs | 157 ++++++++++--- ui/src/terminal/cells.rs | 595 ++++++++++++++++++++++++----------------------- 2 files changed, 429 insertions(+), 323 deletions(-) diff --git a/ui/src/conf/themes.rs b/ui/src/conf/themes.rs index 956063d6..75788c3b 100644 --- a/ui/src/conf/themes.rs +++ b/ui/src/conf/themes.rs @@ -22,15 +22,30 @@ use crate::terminal::Color; use crate::Context; use melib::Result; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; #[inline(always)] pub fn color(context: &Context, key: &'static str) -> Color { - (match context.settings.terminal.theme.as_str() { + let theme = match context.settings.terminal.theme.as_str() { "light" => &context.settings.terminal.themes.light, "dark" | _ => &context.settings.terminal.themes.dark, - })[key] + }; + unlink(theme, &Cow::from(key)) +} + +#[inline(always)] +fn unlink<'k, 't: 'k>( + theme: &'t HashMap, ThemeValue>, + mut key: &'k Cow<'static, str>, +) -> Color { + loop { + match &theme[key] { + ThemeValue::Link(ref new_key) => key = new_key, + ThemeValue::Value(val) => return *val, + } + } } const DEFAULT_KEYS: &'static [&'static str] = &[ @@ -102,12 +117,48 @@ const DEFAULT_KEYS: &'static [&'static str] = &[ "mail.listing.thread_snooze_flag_fg", "mail.listing.thread_snooze_flag_bg", ]; -#[derive(Debug, Clone, Serialize, Deserialize)] + +#[derive(Debug, Clone)] +pub enum ThemeValue { + Value(Color), + Link(Cow<'static, str>), +} + +impl From for ThemeValue { + fn from(from: Color) -> Self { + ThemeValue::Value(from) + } +} + +impl Default for ThemeValue { + fn default() -> Self { + ThemeValue::Value(Color::Default) + } +} + +impl<'de> Deserialize<'de> for ThemeValue { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + if let Ok(s) = ::deserialize(deserializer) { + if let Ok(c) = Color::from_string_de::<'de, D>(s.clone()) { + Ok(ThemeValue::Value(c)) + } else { + Ok(ThemeValue::Link(s.into())) + } + } else { + Err(de::Error::custom("invalid theme color value")) + } + } +} + +#[derive(Debug, Clone, Deserialize)] pub struct Theme { #[serde(default)] - pub light: HashMap, Color>, + pub light: HashMap, ThemeValue>, #[serde(default)] - pub dark: HashMap, Color>, + pub dark: HashMap, ThemeValue>, } impl Theme { @@ -139,33 +190,46 @@ impl Default for Theme { let mut dark = HashMap::default(); macro_rules! add { + ($key:literal, light=$light:literal, dark=$dark:literal) => { + light.insert($key.into(), ThemeValue::Link($light.into())); + dark.insert($key.into(), ThemeValue::Link($dark.into())); + }; + ($key:literal, dark=$dark:literal, light=$light:literal) => { + light.insert($key.into(), ThemeValue::Link($light.into())); + dark.insert($key.into(), ThemeValue::Link($dark.into())); + }; + ($key:literal, light=$light:literal) => { + light.insert($key.into(), $ThemeValue::Link(light);) + dark.insert($key.into(), ThemeValue::Value(Color::Default)); + }; + ($key:literal, dark=$dark:literal) => { + light.insert($key.into(),ThemeValue::Value(Color::Default)); + dark.insert($key.into(), ThemeValue::Link($dark.into())); + }; ($key:literal, light=$light:expr, dark=$dark:expr) => { - light.insert($key.into(), $light); - dark.insert($key.into(), $dark); + light.insert($key.into(), ThemeValue::Value($light)); + dark.insert($key.into(), ThemeValue::Value($dark)); }; ($key:literal, dark=$dark:expr, light=$light:expr) => { - light.insert($key.into(), $light); - dark.insert($key.into(), $dark); + light.insert($key.into(), ThemeValue::Value($light)); + dark.insert($key.into(), ThemeValue::Value($dark)); }; ($key:literal, light=$light:expr) => { - light.insert($key.into(), $light); - dark.insert($key.into(), Color::Default); + light.insert($key.into(), $ThemeValue::Value(light);) + dark.insert($key.into(), ThemeValue::Value(Color::Default)); }; ($key:literal, dark=$dark:expr) => { - light.insert($key.into(), Color::Default); - dark.insert($key.into(), $dark); + light.insert($key.into(),ThemeValue::Value(Color::Default)); + dark.insert($key.into(), ThemeValue::Value($dark)); }; ($key:literal) => { - light.insert($key.into(), Color::Default); - dark.insert($key.into(), Color::Default); + light.insert($key.into(), ThemeValue::Value(Color::Default)); + dark.insert($key.into(), ThemeValue::Value(Color::Default)); }; } - light.insert("general.background".into(), Color::Default); - light.insert("general.foreground".into(), Color::Default); - - dark.insert("general.background".into(), Color::Default); - dark.insert("general.foreground".into(), Color::Default); + add!("general.background"); + add!("general.foreground"); /* "general.status_bar_fg", "general.status_bar_bg", @@ -188,19 +252,23 @@ impl Default for Theme { add!("mail.sidebar_highlighted_bg", dark = Color::Byte(15)); add!( "mail.sidebar_highlighted_unread_count_fg", - dark = dark["mail.sidebar_highlighted_fg"] + light = "mail.sidebar_highlighted_fg", + dark = "mail.sidebar_highlighted_fg" ); add!( "mail.sidebar_highlighted_unread_count_bg", - dark = dark["mail.sidebar_highlighted_bg"] + light = "mail.sidebar_highlighted_bg", + dark = "mail.sidebar_highlighted_bg" ); add!( "mail.sidebar_highlighted_index_fg", - dark = dark["mail.sidebar_index_fg"] + light = "mail.sidebar_index_fg", + dark = "mail.sidebar_index_fg" ); add!( "mail.sidebar_highlighted_index_bg", - dark = dark["mail.sidebar_highlighted_bg"] + light = "mail.sidebar_highlighted_bg", + dark = "mail.sidebar_highlighted_bg" ); add!( "mail.sidebar_highlighted_account_fg", @@ -212,19 +280,23 @@ impl Default for Theme { ); add!( "mail.sidebar_highlighted_account_unread_count_fg", - dark = dark["mail.sidebar_unread_count_fg"] + light = "mail.sidebar_unread_count_fg", + dark = "mail.sidebar_unread_count_fg" ); add!( "mail.sidebar_highlighted_account_unread_count_bg", - dark = dark["mail.sidebar_highlighted_fg"] + light = "mail.sidebar_highlighted_account_bg", + dark = "mail.sidebar_highlighted_account_bg" ); add!( "mail.sidebar_highlighted_account_index_fg", - dark = dark["mail.sidebar_index_fg"] + light = "mail.sidebar_index_fg", + dark = "mail.sidebar_index_fg" ); add!( "mail.sidebar_highlighted_account_index_bg", - dark = dark["mail.sidebar_highlighted_bg"] + light = "mail.sidebar_highlighted_account_bg", + dark = "mail.sidebar_highlighted_account_bg" ); /* CompactListing */ @@ -353,3 +425,32 @@ impl Default for Theme { Theme { light, dark } } } + +impl Serialize for Theme { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: Serializer, + { + let mut dark: HashMap, Color> = Default::default(); + let mut light: HashMap, Color> = Default::default(); + + for k in self.dark.keys() { + dark.insert(k.clone(), unlink(&self.dark, k)); + } + + for k in self.light.keys() { + light.insert(k.clone(), unlink(&self.light, k)); + } + + #[derive(Serialize)] + struct ThemeSer { + light: HashMap, Color>, + dark: HashMap, Color>, + } + use serde::ser::SerializeStruct; + let mut s = serializer.serialize_struct("ThemeSer", 2)?; + s.serialize_field("light", &light)?; + s.serialize_field("dark", &dark)?; + s.end() + } +} diff --git a/ui/src/terminal/cells.rs b/ui/src/terminal/cells.rs index 3cc54c77..72df2607 100644 --- a/ui/src/terminal/cells.rs +++ b/ui/src/terminal/cells.rs @@ -739,6 +739,303 @@ impl Color { Color::Rgb(_, _, _) => AnsiValue(0), } } + + pub fn from_string_de<'de, D>(s: String) -> std::result::Result + where + D: Deserializer<'de>, + { + let byte = match s.as_str() { + "Aqua" => 14, + "Aquamarine1" => 122, + "Aquamarine2" => 86, + "Aquamarine3" => 79, + "Black" => 0, + "Blue" => 12, + "Blue1" => 21, + "Blue2" => 19, + "Blue3" => 20, + "BlueViolet" => 57, + "CadetBlue" => 72, + "CadetBlue1" => 73, + "Chartreuse1" => 118, + "Chartreuse2" => 112, + "Chartreuse3" => 82, + "Chartreuse4" => 70, + "Chartreuse5" => 76, + "Chartreuse6" => 64, + "CornflowerBlue" => 69, + "Cornsilk1" => 230, + "Cyan1" => 51, + "Cyan2" => 50, + "Cyan3" => 43, + "DarkBlue" => 18, + "DarkCyan" => 36, + "DarkGoldenrod" => 136, + "DarkGreen" => 22, + "DarkKhaki" => 143, + "DarkMagenta" => 90, + "DarkMagenta1" => 91, + "DarkOliveGreen1" => 192, + "DarkOliveGreen2" => 155, + "DarkOliveGreen3" => 191, + "DarkOliveGreen4" => 107, + "DarkOliveGreen5" => 113, + "DarkOliveGreen6" => 149, + "DarkOrange" => 208, + "DarkOrange2" => 130, + "DarkOrange3" => 166, + "DarkRed" => 52, + "DarkRed2" => 88, + "DarkSeaGreen" => 108, + "DarkSeaGreen1" => 158, + "DarkSeaGreen2" => 193, + "DarkSeaGreen3" => 151, + "DarkSeaGreen4" => 157, + "DarkSeaGreen5" => 115, + "DarkSeaGreen6" => 150, + "DarkSeaGreen7" => 65, + "DarkSeaGreen8" => 71, + "DarkSlateGray1" => 123, + "DarkSlateGray2" => 87, + "DarkSlateGray3" => 116, + "DarkTurquoise" => 44, + "DarkViolet" => 128, + "DarkViolet1" => 92, + "DeepPink1" => 199, + "DeepPink2" => 197, + "DeepPink3" => 198, + "DeepPink4" => 125, + "DeepPink6" => 162, + "DeepPink7" => 89, + "DeepPink8" => 53, + "DeepPink9" => 161, + "DeepSkyBlue1" => 39, + "DeepSkyBlue2" => 38, + "DeepSkyBlue3" => 31, + "DeepSkyBlue4" => 32, + "DeepSkyBlue5" => 23, + "DeepSkyBlue6" => 24, + "DeepSkyBlue7" => 25, + "DodgerBlue1" => 33, + "DodgerBlue2" => 27, + "DodgerBlue3" => 26, + "Fuchsia" => 13, + "Gold1" => 220, + "Gold2" => 142, + "Gold3" => 178, + "Green" => 2, + "Green1" => 46, + "Green2" => 34, + "Green3" => 40, + "Green4" => 28, + "GreenYellow" => 154, + "Grey" => 8, + "Grey0" => 16, + "Grey100" => 231, + "Grey11" => 234, + "Grey15" => 235, + "Grey19" => 236, + "Grey23" => 237, + "Grey27" => 238, + "Grey3" => 232, + "Grey30" => 239, + "Grey35" => 240, + "Grey37" => 59, + "Grey39" => 241, + "Grey42" => 242, + "Grey46" => 243, + "Grey50" => 244, + "Grey53" => 102, + "Grey54" => 245, + "Grey58" => 246, + "Grey62" => 247, + "Grey63" => 139, + "Grey66" => 248, + "Grey69" => 145, + "Grey7" => 233, + "Grey70" => 249, + "Grey74" => 250, + "Grey78" => 251, + "Grey82" => 252, + "Grey84" => 188, + "Grey85" => 253, + "Grey89" => 254, + "Grey93" => 255, + "Honeydew2" => 194, + "HotPink" => 205, + "HotPink1" => 206, + "HotPink2" => 169, + "HotPink3" => 132, + "HotPink4" => 168, + "IndianRed" => 131, + "IndianRed1" => 167, + "IndianRed2" => 204, + "IndianRed3" => 203, + "Khaki1" => 228, + "Khaki3" => 185, + "LightCoral" => 210, + "LightCyan2" => 195, + "LightCyan3" => 152, + "LightGoldenrod1" => 227, + "LightGoldenrod2" => 222, + "LightGoldenrod3" => 179, + "LightGoldenrod4" => 221, + "LightGoldenrod5" => 186, + "LightGreen" => 119, + "LightGreen1" => 120, + "LightPink1" => 217, + "LightPink2" => 174, + "LightPink3" => 95, + "LightSalmon1" => 216, + "LightSalmon2" => 137, + "LightSalmon3" => 173, + "LightSeaGreen" => 37, + "LightSkyBlue1" => 153, + "LightSkyBlue2" => 109, + "LightSkyBlue3" => 110, + "LightSlateBlue" => 105, + "LightSlateGrey" => 103, + "LightSteelBlue" => 147, + "LightSteelBlue1" => 189, + "LightSteelBlue3" => 146, + "LightYellow3" => 187, + "Lime" => 10, + "Magenta1" => 201, + "Magenta2" => 165, + "Magenta3" => 200, + "Magenta4" => 127, + "Magenta5" => 163, + "Magenta6" => 164, + "Maroon" => 1, + "MediumOrchid" => 134, + "MediumOrchid1" => 171, + "MediumOrchid2" => 207, + "MediumOrchid3" => 133, + "MediumPurple" => 104, + "MediumPurple1" => 141, + "MediumPurple2" => 135, + "MediumPurple3" => 140, + "MediumPurple4" => 97, + "MediumPurple5" => 98, + "MediumPurple6" => 60, + "MediumSpringGreen" => 49, + "MediumTurquoise" => 80, + "MediumVioletRed" => 126, + "MistyRose1" => 224, + "MistyRose3" => 181, + "NavajoWhite1" => 223, + "NavajoWhite3" => 144, + "Navy" => 4, + "NavyBlue" => 17, + "Olive" => 3, + "Orange1" => 214, + "Orange2" => 172, + "Orange3" => 58, + "Orange4" => 94, + "OrangeRed1" => 202, + "Orchid" => 170, + "Orchid1" => 213, + "Orchid2" => 212, + "PaleGreen1" => 121, + "PaleGreen2" => 156, + "PaleGreen3" => 114, + "PaleGreen4" => 77, + "PaleTurquoise1" => 159, + "PaleTurquoise4" => 66, + "PaleVioletRed1" => 211, + "Pink1" => 218, + "Pink3" => 175, + "Plum1" => 219, + "Plum2" => 183, + "Plum3" => 176, + "Plum4" => 96, + "Purple" => 129, + "Purple1" => 5, + "Purple2" => 93, + "Purple3" => 56, + "Purple4" => 54, + "Purple5" => 55, + "Red" => 9, + "Red1" => 196, + "Red2" => 124, + "Red3" => 160, + "RosyBrown" => 138, + "RoyalBlue1" => 63, + "Salmon1" => 209, + "SandyBrown" => 215, + "SeaGreen1" => 84, + "SeaGreen2" => 85, + "SeaGreen3" => 83, + "SeaGreen4" => 78, + "Silver" => 7, + "SkyBlue1" => 117, + "SkyBlue2" => 111, + "SkyBlue3" => 74, + "SlateBlue1" => 99, + "SlateBlue2" => 61, + "SlateBlue3" => 62, + "SpringGreen1" => 48, + "SpringGreen2" => 42, + "SpringGreen3" => 47, + "SpringGreen4" => 35, + "SpringGreen5" => 41, + "SpringGreen6" => 29, + "SteelBlue" => 67, + "SteelBlue1" => 75, + "SteelBlue2" => 81, + "SteelBlue3" => 68, + "Tan" => 180, + "Teal" => 6, + "Thistle1" => 225, + "Thistle3" => 182, + "Turquoise2" => 45, + "Turquoise4" => 30, + "Violet" => 177, + "Wheat1" => 229, + "Wheat4" => 101, + "White" => 15, + "Yellow" => 11, + "Yellow1" => 226, + "Yellow2" => 190, + "Yellow3" => 184, + "Yellow4" => 100, + "Yellow5" => 106, + "Yellow6" => 148, + s if s.starts_with("#") + && s.len() == 7 + && s[1..].as_bytes().iter().all(|&b| { + (b >= b'0' && b <= b'9') || (b >= b'a' && b <= b'f') || (b >= b'A' && b <= b'F') + }) => + { + return Ok(Color::Rgb( + u8::from_str_radix(&s[1..3], 16) + .map_err(|_| de::Error::custom("invalid `color` value"))?, + u8::from_str_radix(&s[3..5], 16) + .map_err(|_| de::Error::custom("invalid `color` value"))?, + u8::from_str_radix(&s[5..7], 16) + .map_err(|_| de::Error::custom("invalid `color` value"))?, + )) + } + s if s.starts_with("#") + && s.len() == 4 + && s[1..].as_bytes().iter().all(|&b| { + (b >= b'0' && b <= b'9') || (b >= b'a' && b <= b'f') || (b >= b'A' && b <= b'F') + }) => + { + return Ok(Color::Rgb( + 17 * u8::from_str_radix(&s[1..2], 16) + .map_err(|_| de::Error::custom("invalid `color` value"))?, + 17 * u8::from_str_radix(&s[2..3], 16) + .map_err(|_| de::Error::custom("invalid `color` value"))?, + 17 * u8::from_str_radix(&s[3..4], 16) + .map_err(|_| de::Error::custom("invalid `color` value"))?, + )) + } + _ => u8::from_str_radix(&s, 10) + .map_err(|_| de::Error::custom("invalid `color` value"))?, + }; + return Ok(Color::Byte(byte)); + } } impl Default for Color { @@ -753,302 +1050,10 @@ impl<'de> Deserialize<'de> for Color { D: Deserializer<'de>, { if let Ok(s) = ::deserialize(deserializer) { - let byte = match s.as_str() { - "Aqua" => 14, - "Aquamarine1" => 122, - "Aquamarine2" => 86, - "Aquamarine3" => 79, - "Black" => 0, - "Blue" => 12, - "Blue1" => 21, - "Blue2" => 19, - "Blue3" => 20, - "BlueViolet" => 57, - "CadetBlue" => 72, - "CadetBlue1" => 73, - "Chartreuse1" => 118, - "Chartreuse2" => 112, - "Chartreuse3" => 82, - "Chartreuse4" => 70, - "Chartreuse5" => 76, - "Chartreuse6" => 64, - "CornflowerBlue" => 69, - "Cornsilk1" => 230, - "Cyan1" => 51, - "Cyan2" => 50, - "Cyan3" => 43, - "DarkBlue" => 18, - "DarkCyan" => 36, - "DarkGoldenrod" => 136, - "DarkGreen" => 22, - "DarkKhaki" => 143, - "DarkMagenta" => 90, - "DarkMagenta1" => 91, - "DarkOliveGreen1" => 192, - "DarkOliveGreen2" => 155, - "DarkOliveGreen3" => 191, - "DarkOliveGreen4" => 107, - "DarkOliveGreen5" => 113, - "DarkOliveGreen6" => 149, - "DarkOrange" => 208, - "DarkOrange2" => 130, - "DarkOrange3" => 166, - "DarkRed" => 52, - "DarkRed2" => 88, - "DarkSeaGreen" => 108, - "DarkSeaGreen1" => 158, - "DarkSeaGreen2" => 193, - "DarkSeaGreen3" => 151, - "DarkSeaGreen4" => 157, - "DarkSeaGreen5" => 115, - "DarkSeaGreen6" => 150, - "DarkSeaGreen7" => 65, - "DarkSeaGreen8" => 71, - "DarkSlateGray1" => 123, - "DarkSlateGray2" => 87, - "DarkSlateGray3" => 116, - "DarkTurquoise" => 44, - "DarkViolet" => 128, - "DarkViolet1" => 92, - "DeepPink1" => 199, - "DeepPink2" => 197, - "DeepPink3" => 198, - "DeepPink4" => 125, - "DeepPink6" => 162, - "DeepPink7" => 89, - "DeepPink8" => 53, - "DeepPink9" => 161, - "DeepSkyBlue1" => 39, - "DeepSkyBlue2" => 38, - "DeepSkyBlue3" => 31, - "DeepSkyBlue4" => 32, - "DeepSkyBlue5" => 23, - "DeepSkyBlue6" => 24, - "DeepSkyBlue7" => 25, - "DodgerBlue1" => 33, - "DodgerBlue2" => 27, - "DodgerBlue3" => 26, - "Fuchsia" => 13, - "Gold1" => 220, - "Gold2" => 142, - "Gold3" => 178, - "Green" => 2, - "Green1" => 46, - "Green2" => 34, - "Green3" => 40, - "Green4" => 28, - "GreenYellow" => 154, - "Grey" => 8, - "Grey0" => 16, - "Grey100" => 231, - "Grey11" => 234, - "Grey15" => 235, - "Grey19" => 236, - "Grey23" => 237, - "Grey27" => 238, - "Grey3" => 232, - "Grey30" => 239, - "Grey35" => 240, - "Grey37" => 59, - "Grey39" => 241, - "Grey42" => 242, - "Grey46" => 243, - "Grey50" => 244, - "Grey53" => 102, - "Grey54" => 245, - "Grey58" => 246, - "Grey62" => 247, - "Grey63" => 139, - "Grey66" => 248, - "Grey69" => 145, - "Grey7" => 233, - "Grey70" => 249, - "Grey74" => 250, - "Grey78" => 251, - "Grey82" => 252, - "Grey84" => 188, - "Grey85" => 253, - "Grey89" => 254, - "Grey93" => 255, - "Honeydew2" => 194, - "HotPink" => 205, - "HotPink1" => 206, - "HotPink2" => 169, - "HotPink3" => 132, - "HotPink4" => 168, - "IndianRed" => 131, - "IndianRed1" => 167, - "IndianRed2" => 204, - "IndianRed3" => 203, - "Khaki1" => 228, - "Khaki3" => 185, - "LightCoral" => 210, - "LightCyan2" => 195, - "LightCyan3" => 152, - "LightGoldenrod1" => 227, - "LightGoldenrod2" => 222, - "LightGoldenrod3" => 179, - "LightGoldenrod4" => 221, - "LightGoldenrod5" => 186, - "LightGreen" => 119, - "LightGreen1" => 120, - "LightPink1" => 217, - "LightPink2" => 174, - "LightPink3" => 95, - "LightSalmon1" => 216, - "LightSalmon2" => 137, - "LightSalmon3" => 173, - "LightSeaGreen" => 37, - "LightSkyBlue1" => 153, - "LightSkyBlue2" => 109, - "LightSkyBlue3" => 110, - "LightSlateBlue" => 105, - "LightSlateGrey" => 103, - "LightSteelBlue" => 147, - "LightSteelBlue1" => 189, - "LightSteelBlue3" => 146, - "LightYellow3" => 187, - "Lime" => 10, - "Magenta1" => 201, - "Magenta2" => 165, - "Magenta3" => 200, - "Magenta4" => 127, - "Magenta5" => 163, - "Magenta6" => 164, - "Maroon" => 1, - "MediumOrchid" => 134, - "MediumOrchid1" => 171, - "MediumOrchid2" => 207, - "MediumOrchid3" => 133, - "MediumPurple" => 104, - "MediumPurple1" => 141, - "MediumPurple2" => 135, - "MediumPurple3" => 140, - "MediumPurple4" => 97, - "MediumPurple5" => 98, - "MediumPurple6" => 60, - "MediumSpringGreen" => 49, - "MediumTurquoise" => 80, - "MediumVioletRed" => 126, - "MistyRose1" => 224, - "MistyRose3" => 181, - "NavajoWhite1" => 223, - "NavajoWhite3" => 144, - "Navy" => 4, - "NavyBlue" => 17, - "Olive" => 3, - "Orange1" => 214, - "Orange2" => 172, - "Orange3" => 58, - "Orange4" => 94, - "OrangeRed1" => 202, - "Orchid" => 170, - "Orchid1" => 213, - "Orchid2" => 212, - "PaleGreen1" => 121, - "PaleGreen2" => 156, - "PaleGreen3" => 114, - "PaleGreen4" => 77, - "PaleTurquoise1" => 159, - "PaleTurquoise4" => 66, - "PaleVioletRed1" => 211, - "Pink1" => 218, - "Pink3" => 175, - "Plum1" => 219, - "Plum2" => 183, - "Plum3" => 176, - "Plum4" => 96, - "Purple" => 129, - "Purple1" => 5, - "Purple2" => 93, - "Purple3" => 56, - "Purple4" => 54, - "Purple5" => 55, - "Red" => 9, - "Red1" => 196, - "Red2" => 124, - "Red3" => 160, - "RosyBrown" => 138, - "RoyalBlue1" => 63, - "Salmon1" => 209, - "SandyBrown" => 215, - "SeaGreen1" => 84, - "SeaGreen2" => 85, - "SeaGreen3" => 83, - "SeaGreen4" => 78, - "Silver" => 7, - "SkyBlue1" => 117, - "SkyBlue2" => 111, - "SkyBlue3" => 74, - "SlateBlue1" => 99, - "SlateBlue2" => 61, - "SlateBlue3" => 62, - "SpringGreen1" => 48, - "SpringGreen2" => 42, - "SpringGreen3" => 47, - "SpringGreen4" => 35, - "SpringGreen5" => 41, - "SpringGreen6" => 29, - "SteelBlue" => 67, - "SteelBlue1" => 75, - "SteelBlue2" => 81, - "SteelBlue3" => 68, - "Tan" => 180, - "Teal" => 6, - "Thistle1" => 225, - "Thistle3" => 182, - "Turquoise2" => 45, - "Turquoise4" => 30, - "Violet" => 177, - "Wheat1" => 229, - "Wheat4" => 101, - "White" => 15, - "Yellow" => 11, - "Yellow1" => 226, - "Yellow2" => 190, - "Yellow3" => 184, - "Yellow4" => 100, - "Yellow5" => 106, - "Yellow6" => 148, - s if s.starts_with("#") - && s.len() == 7 - && s[1..].as_bytes().iter().all(|&b| { - (b >= b'0' && b <= b'9') - || (b >= b'a' && b <= b'f') - || (b >= b'A' && b <= b'F') - }) => - { - return Ok(Color::Rgb( - u8::from_str_radix(&s[1..3], 16) - .map_err(|_| de::Error::custom("invalid `color` value"))?, - u8::from_str_radix(&s[3..5], 16) - .map_err(|_| de::Error::custom("invalid `color` value"))?, - u8::from_str_radix(&s[5..7], 16) - .map_err(|_| de::Error::custom("invalid `color` value"))?, - )) - } - s if s.starts_with("#") - && s.len() == 4 - && s[1..].as_bytes().iter().all(|&b| { - (b >= b'0' && b <= b'9') - || (b >= b'a' && b <= b'f') - || (b >= b'A' && b <= b'F') - }) => - { - return Ok(Color::Rgb( - 17 * u8::from_str_radix(&s[1..2], 16) - .map_err(|_| de::Error::custom("invalid `color` value"))?, - 17 * u8::from_str_radix(&s[2..3], 16) - .map_err(|_| de::Error::custom("invalid `color` value"))?, - 17 * u8::from_str_radix(&s[3..4], 16) - .map_err(|_| de::Error::custom("invalid `color` value"))?, - )) - } - _ => return Err(de::Error::custom("invalid `color` value")), - }; - return Ok(Color::Byte(byte)); + Color::from_string_de::<'de, D>(s) + } else { + Err(de::Error::custom("invalid `color` value")) } - Err(de::Error::custom("invalid `color` value")) } } -- cgit v1.2.3