summaryrefslogtreecommitdiffstats
path: root/ui/src/conf/themes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ui/src/conf/themes.rs')
-rw-r--r--ui/src/conf/themes.rs157
1 files changed, 129 insertions, 28 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<Cow<'static, str>, 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<Color> 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<D>(deserializer: D) -> std::result::Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ if let Ok(s) = <String>::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<Cow<'static, str>, Color>,
+ pub light: HashMap<Cow<'static, str>, ThemeValue>,
#[serde(default)]
- pub dark: HashMap<Cow<'static, str>, Color>,
+ pub dark: HashMap<Cow<'static, str>, 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<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ let mut dark: HashMap<Cow<'static, str>, Color> = Default::default();
+ let mut light: HashMap<Cow<'static, str>, 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<Cow<'static, str>, Color>,
+ dark: HashMap<Cow<'static, str>, 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()
+ }
+}