diff options
Diffstat (limited to 'helix-view/src/theme.rs')
-rw-r--r-- | helix-view/src/theme.rs | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index 757316bd..4a2ecbba 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -15,6 +15,10 @@ pub use crate::graphics::{Color, Modifier, Style}; pub static DEFAULT_THEME: Lazy<Theme> = Lazy::new(|| { toml::from_slice(include_bytes!("../../theme.toml")).expect("Failed to parse default theme") }); +pub static BASE16_DEFAULT_THEME: Lazy<Theme> = Lazy::new(|| { + toml::from_slice(include_bytes!("../../base16_theme.toml")) + .expect("Failed to parse base 16 default theme") +}); #[derive(Clone, Debug)] pub struct Loader { @@ -35,6 +39,9 @@ impl Loader { if name == "default" { return Ok(self.default()); } + if name == "base16_default" { + return Ok(self.base16_default()); + } let filename = format!("{}.toml", name); let user_path = self.user_dir.join(&filename); @@ -74,12 +81,20 @@ impl Loader { pub fn default(&self) -> Theme { DEFAULT_THEME.clone() } + + /// Returns the alternative 16-color default theme + pub fn base16_default(&self) -> Theme { + BASE16_DEFAULT_THEME.clone() + } } #[derive(Clone, Debug)] pub struct Theme { - scopes: Vec<String>, + // UI styles are stored in a HashMap styles: HashMap<String, Style>, + // tree-sitter highlight styles are stored in a Vec to optimize lookups + scopes: Vec<String>, + highlights: Vec<Style>, } impl<'de> Deserialize<'de> for Theme { @@ -88,6 +103,8 @@ impl<'de> Deserialize<'de> for Theme { D: Deserializer<'de>, { let mut styles = HashMap::new(); + let mut scopes = Vec::new(); + let mut highlights = Vec::new(); if let Ok(mut colors) = HashMap::<String, Value>::deserialize(deserializer) { // TODO: alert user of parsing failures in editor @@ -102,24 +119,38 @@ impl<'de> Deserialize<'de> for Theme { .unwrap_or_default(); styles.reserve(colors.len()); + scopes.reserve(colors.len()); + highlights.reserve(colors.len()); + for (name, style_value) in colors { let mut style = Style::default(); if let Err(err) = palette.parse_style(&mut style, style_value) { warn!("{}", err); } - styles.insert(name, style); + + // these are used both as UI and as highlights + styles.insert(name.clone(), style); + scopes.push(name); + highlights.push(style); } } - let scopes = styles.keys().map(ToString::to_string).collect(); - Ok(Self { scopes, styles }) + Ok(Self { + scopes, + styles, + highlights, + }) } } impl Theme { + #[inline] + pub fn highlight(&self, index: usize) -> Style { + self.highlights[index] + } + pub fn get(&self, scope: &str) -> Style { - self.try_get(scope) - .unwrap_or_else(|| Style::default().fg(Color::Rgb(0, 0, 255))) + self.try_get(scope).unwrap_or_default() } pub fn try_get(&self, scope: &str) -> Option<Style> { @@ -134,6 +165,14 @@ impl Theme { pub fn find_scope_index(&self, scope: &str) -> Option<usize> { self.scopes().iter().position(|s| s == scope) } + + pub fn is_16_color(&self) -> bool { + self.styles.iter().all(|(_, style)| { + [style.fg, style.bg] + .into_iter() + .all(|color| !matches!(color, Some(Color::Rgb(..)))) + }) + } } struct ThemePalette { |