From 79f096963c75d107cd1f415666fb21a9cfd3cbd6 Mon Sep 17 00:00:00 2001 From: Jakub Bartodziej Date: Wed, 30 Jun 2021 16:24:30 +0200 Subject: Color palettes (#393) * Enable using color palettes in theme files. * Add an example theme defined using a gruvbox color palette. * Fix clippy error. * Small style improvement. * Add documentation for the features to themes.md. * Update runtime/themes/gruvbox.toml Fix the value of purple0. Co-authored-by: DrZingo Co-authored-by: DrZingo --- helix-view/src/theme.rs | 52 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) (limited to 'helix-view/src') diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index ece4fe9a..756e34f6 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -102,12 +102,13 @@ impl<'de> Deserialize<'de> for Theme { { let mut styles = HashMap::new(); - if let Ok(colors) = HashMap::::deserialize(deserializer) { + if let Ok(mut colors) = HashMap::::deserialize(deserializer) { + let palette = parse_palette(colors.remove("palette")); // scopes.reserve(colors.len()); styles.reserve(colors.len()); for (name, style_value) in colors { let mut style = Style::default(); - parse_style(&mut style, style_value); + parse_style(&mut style, style_value, &palette); // scopes.push(name); styles.insert(name, style); } @@ -118,18 +119,31 @@ impl<'de> Deserialize<'de> for Theme { } } -fn parse_style(style: &mut Style, value: Value) { +fn parse_palette(value: Option) -> HashMap { + match value { + Some(Value::Table(entries)) => entries, + _ => return HashMap::default(), + } + .into_iter() + .filter_map(|(name, value)| { + let color = parse_color(value, &HashMap::default())?; + Some((name, color)) + }) + .collect() +} + +fn parse_style(style: &mut Style, value: Value, palette: &HashMap) { //TODO: alert user of parsing failures if let Value::Table(entries) = value { for (name, value) in entries { match name.as_str() { "fg" => { - if let Some(color) = parse_color(value) { + if let Some(color) = parse_color(value, palette) { *style = style.fg(color); } } "bg" => { - if let Some(color) = parse_color(value) { + if let Some(color) = parse_color(value, palette) { *style = style.bg(color); } } @@ -143,7 +157,7 @@ fn parse_style(style: &mut Style, value: Value) { _ => (), } } - } else if let Some(color) = parse_color(value) { + } else if let Some(color) = parse_color(value, palette) { *style = style.fg(color); } } @@ -164,9 +178,11 @@ fn hex_string_to_rgb(s: &str) -> Option<(u8, u8, u8)> { } } -fn parse_color(value: Value) -> Option { +fn parse_color(value: Value, palette: &HashMap) -> Option { if let Value::String(s) = value { - if let Some((red, green, blue)) = hex_string_to_rgb(&s) { + if let Some(color) = palette.get(&s) { + Some(*color) + } else if let Some((red, green, blue)) = hex_string_to_rgb(&s) { Some(Color::Rgb(red, green, blue)) } else { warn!("malformed hexcode in theme: {}", s); @@ -226,7 +242,23 @@ fn test_parse_style_string() { let fg = Value::String("#ffffff".to_string()); let mut style = Style::default(); - parse_style(&mut style, fg); + parse_style(&mut style, fg, &HashMap::default()); + + assert_eq!(style, Style::default().fg(Color::Rgb(255, 255, 255))); +} + +#[test] +fn test_palette() { + let fg = Value::String("my_color".to_string()); + + let mut style = Style::default(); + parse_style( + &mut style, + fg, + &vec![("my_color".to_string(), Color::Rgb(255, 255, 255))] + .into_iter() + .collect(), + ); assert_eq!(style, Style::default().fg(Color::Rgb(255, 255, 255))); } @@ -244,7 +276,7 @@ fn test_parse_style_table() { let mut style = Style::default(); if let Value::Table(entries) = table { for (_name, value) in entries { - parse_style(&mut style, value); + parse_style(&mut style, value, &HashMap::default()); } } -- cgit v1.2.3-70-g09d2