From 33daeafb77278f965eeeed73890930893bb6ae3d Mon Sep 17 00:00:00 2001 From: Christoph Schmidler Date: Thu, 14 Jul 2022 12:31:13 +0200 Subject: [PATCH 1/8] Add RawTheme to handle inheritance with theme palette --- helix-view/src/theme.rs | 99 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 91 insertions(+), 8 deletions(-) diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index fa5fa702804b..4711c17af1bf 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -42,17 +42,21 @@ impl Loader { if name == "base16_default" { return Ok(self.base16_default()); } - let filename = format!("{}.toml", name); - let user_path = self.user_dir.join(&filename); - let path = if user_path.exists() { - user_path - } else { - self.default_dir.join(filename) - }; + // let mut raw_theme: RawTheme = self.load_raw(name)?; + + // if let Some(parent_theme_name) = &raw_theme.inherits_from { + // //let parent_theme_name = "bogster"; + // let parent_raw_theme = self.load_raw(parent_theme_name)?; + + // raw_theme.inherit(parent_raw_theme); + // } + + let path = self.path(name); let data = std::fs::read(&path)?; - toml::from_slice(data.as_slice()).context("Failed to deserialize theme") + + toml::from_slice(data.as_slice()).context("Faled to deserialize theme") } pub fn read_names(path: &Path) -> Vec { @@ -70,6 +74,28 @@ impl Loader { .unwrap_or_default() } + // Loads the raw theme data first from the user_dir then in default_dir + fn load_raw(&self, name: &str) -> Result { + let path = self.path(name); + let data = std::fs::read(&path)?; + + toml::from_slice(data.as_slice()).context("Faled to deserialize theme") + } + + // Returns the path to the theme name + fn path(&self, name: &str) -> PathBuf { + let filename = format!("{}.toml", name); + + let user_path = self.user_dir.join(&filename); + let path = if user_path.exists() { + user_path + } else { + self.default_dir.join(filename) + }; + + path + } + /// Lists all theme names available in default and user directory pub fn names(&self) -> Vec { let mut names = Self::read_names(&self.user_dir); @@ -96,6 +122,63 @@ impl Loader { } } +struct RawTheme { + // Raw toml values + values: HashMap, + palette: ThemePalette, + inherits_from: Option, +} + +impl RawTheme { + fn inherit(&mut self, parent_theme: RawTheme) { + let palette = ThemePalette::new( + parent_theme + .palette + .palette + .into_iter() + .chain(self.palette.palette.clone()) + .collect(), + ); + self.palette = palette; + + let values = parent_theme + .values + .into_iter() + .chain(self.values.clone()) + .collect(); + self.values = values; + } +} + +impl<'de> Deserialize<'de> for RawTheme { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let mut values = HashMap::::deserialize(deserializer)?; + + let palette = values + .remove("palette") + .map(|value| { + ThemePalette::try_from(value).unwrap_or_else(|err| { + warn!("{}", err); + ThemePalette::default() + }) + }) + .unwrap_or_default(); + + let inherits_from = values + .remove("inherits_from") + .map(|value| value.to_string().replace("\"", "")); + + Ok(Self { + values, + palette, + inherits_from, + }) + } +} + #[derive(Clone, Debug)] pub struct Theme { // UI styles are stored in a HashMap From 3370de826a4182400552f388c17a8e0c57fdab8a Mon Sep 17 00:00:00 2001 From: Christoph Schmidler Date: Thu, 14 Jul 2022 14:19:52 +0200 Subject: [PATCH 2/8] Add a intermediate step in theme loading it uses RawTheme struct to load the original ThemePalette, so we can merge it with the inherited one. --- helix-view/src/theme.rs | 46 +++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index 4711c17af1bf..b49ebf65ac5a 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -43,20 +43,21 @@ impl Loader { return Ok(self.base16_default()); } + let mut raw_theme: RawTheme = self.load_raw(name)?; - // let mut raw_theme: RawTheme = self.load_raw(name)?; + if let Some(parent_theme_name) = &raw_theme.inherits_from { + //let parent_theme_name = "bogster"; + let parent_raw_theme = self.load_raw(parent_theme_name)?; - // if let Some(parent_theme_name) = &raw_theme.inherits_from { - // //let parent_theme_name = "bogster"; - // let parent_raw_theme = self.load_raw(parent_theme_name)?; + raw_theme.inherit(parent_raw_theme); + } - // raw_theme.inherit(parent_raw_theme); - // } + Ok(Theme::from(raw_theme)) - let path = self.path(name); - let data = std::fs::read(&path)?; + // let path = self.path(name); + // let data = std::fs::read(&path)?; - toml::from_slice(data.as_slice()).context("Faled to deserialize theme") + // toml::from_slice(data.as_slice()).context("Faled to deserialize theme") } pub fn read_names(path: &Path) -> Vec { @@ -157,6 +158,7 @@ impl<'de> Deserialize<'de> for RawTheme { { let mut values = HashMap::::deserialize(deserializer)?; + // TODO: alert user of parsing failures in editor let palette = values .remove("palette") .map(|value| { @@ -188,6 +190,32 @@ pub struct Theme { highlights: Vec