From d580b2541532a075402285c636462100366ff580 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Fri, 10 Apr 2020 11:41:00 +0300 Subject: [PATCH] themes: overwrite only explicit key attributes If user config file overwrites a single attribute and not the others, for example only bg: "mail.listing.tag_default" = { bg = "Blue" } The other attributes, in this case fg and attrs revert to the default values of ThemeAttributeInner and not the default value for the key "mail.listing.tag_default". As a result the above expands to: "mail.listing.tag_default" = { fg = Color::Default, bg = "Blue", attrs = Attr::Default } This commit keeps the key value defaults, so the above should expand to: "mail.listing.tag_default" = { fg = default_theme["mail.listing.tag_default"].fg, bg = "Blue", attrs = default_theme["mail.listing.tag_default"].attrs } --- src/conf/themes.rs | 89 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/src/conf/themes.rs b/src/conf/themes.rs index a7db9d8b..ecd6eff7 100644 --- a/src/conf/themes.rs +++ b/src/conf/themes.rs @@ -318,16 +318,97 @@ impl<'de> Deserialize<'de> for ThemeValue { } } -#[derive(Debug, Clone, Deserialize)] +#[derive(Debug, Clone)] pub struct Theme { - #[serde(default)] pub light: HashMap, ThemeAttributeInner>, - #[serde(default)] pub dark: HashMap, ThemeAttributeInner>, - #[serde(flatten, default)] pub other_themes: HashMap, ThemeAttributeInner>>, } +impl<'de> Deserialize<'de> for Theme { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + struct ThemeOptions { + #[serde(default)] + light: HashMap, ThemeAttributeInnerOptions>, + #[serde(default)] + dark: HashMap, ThemeAttributeInnerOptions>, + #[serde(flatten, default)] + other_themes: HashMap, ThemeAttributeInnerOptions>>, + } + #[derive(Deserialize)] + struct ThemeAttributeInnerOptions { + #[serde(default)] + fg: Option>, + #[serde(default)] + bg: Option>, + #[serde(default)] + attrs: Option>, + } + + let mut ret = Theme::default(); + let mut s = ::deserialize(deserializer)?; + for tk in s.other_themes.keys() { + ret.other_themes.insert(tk.clone(), ret.dark.clone()); + } + + for (k, v) in ret.light.iter_mut() { + if let Some(att) = s.light.get_mut(k).and_then(|att| att.fg.take()) { + v.fg = att; + } + if let Some(att) = s.light.get_mut(k).and_then(|att| att.bg.take()) { + v.bg = att; + } + if let Some(att) = s.light.get_mut(k).and_then(|att| att.attrs.take()) { + v.attrs = att; + } + } + for (k, v) in ret.dark.iter_mut() { + if let Some(att) = s.dark.get_mut(k).and_then(|att| att.fg.take()) { + v.fg = att; + } + if let Some(att) = s.dark.get_mut(k).and_then(|att| att.bg.take()) { + v.bg = att; + } + if let Some(att) = s.dark.get_mut(k).and_then(|att| att.attrs.take()) { + v.attrs = att; + } + } + for (tk, t) in ret.other_themes.iter_mut() { + for (k, v) in t.iter_mut() { + if let Some(att) = s + .other_themes + .get_mut(tk) + .and_then(|theme| theme.get_mut(k)) + .and_then(|att| att.fg.take()) + { + v.fg = att; + } + if let Some(att) = s + .other_themes + .get_mut(tk) + .and_then(|theme| theme.get_mut(k)) + .and_then(|att| att.bg.take()) + { + v.bg = att; + } + if let Some(att) = s + .other_themes + .get_mut(tk) + .and_then(|theme| theme.get_mut(k)) + .and_then(|att| att.attrs.take()) + { + v.attrs = att; + } + } + } + Ok(ret) + } +} + impl Theme { fn validate_keys( name: &str,