mirror of https://github.com/helix-editor/helix
Refactor toml::Value->Theme conversion
The `From<Value>` implementation for `Theme` converted the Value to a string and re-parsed the string to convert it to `HashMap<String, Value>` which feels a bit wasteful. This change uses the underlying `toml::map::Map` directly when the value is a table and warns about the unexpected `Value` shape otherwise. This is necessary because toml 0.6.0 changes the Display implementation for Value::Table so that the `to_string` no longer encodes the value as a Document, just a Value. So the parse of the Value fails to be decoded as a HashMap. The behavior for returning `Default::default` matches the previous code's behavior except that it did not warn when the input Value was failed to parse.pull/5185/head
parent
b3e9f6233a
commit
70887b7378
|
@ -4,7 +4,7 @@ use std::{
|
||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use helix_core::hashmap;
|
use helix_core::hashmap;
|
||||||
use helix_loader::merge_toml_values;
|
use helix_loader::merge_toml_values;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
@ -209,16 +209,18 @@ pub struct Theme {
|
||||||
|
|
||||||
impl From<Value> for Theme {
|
impl From<Value> for Theme {
|
||||||
fn from(value: Value) -> Self {
|
fn from(value: Value) -> Self {
|
||||||
let values: Result<HashMap<String, Value>> =
|
if let Value::Table(table) = value {
|
||||||
toml::from_str(&value.to_string()).context("Failed to load theme");
|
let (styles, scopes, highlights) = build_theme_values(table);
|
||||||
|
|
||||||
let (styles, scopes, highlights) = build_theme_values(values);
|
Self {
|
||||||
|
styles,
|
||||||
Self {
|
scopes,
|
||||||
styles,
|
highlights,
|
||||||
scopes,
|
..Default::default()
|
||||||
highlights,
|
}
|
||||||
..Default::default()
|
} else {
|
||||||
|
warn!("Expected theme TOML value to be a table, found {:?}", value);
|
||||||
|
Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,9 +230,9 @@ impl<'de> Deserialize<'de> for Theme {
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let values = HashMap::<String, Value>::deserialize(deserializer)?;
|
let values = Map::<String, Value>::deserialize(deserializer)?;
|
||||||
|
|
||||||
let (styles, scopes, highlights) = build_theme_values(Ok(values));
|
let (styles, scopes, highlights) = build_theme_values(values);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
styles,
|
styles,
|
||||||
|
@ -242,39 +244,37 @@ impl<'de> Deserialize<'de> for Theme {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_theme_values(
|
fn build_theme_values(
|
||||||
values: Result<HashMap<String, Value>>,
|
mut values: Map<String, Value>,
|
||||||
) -> (HashMap<String, Style>, Vec<String>, Vec<Style>) {
|
) -> (HashMap<String, Style>, Vec<String>, Vec<Style>) {
|
||||||
let mut styles = HashMap::new();
|
let mut styles = HashMap::new();
|
||||||
let mut scopes = Vec::new();
|
let mut scopes = Vec::new();
|
||||||
let mut highlights = Vec::new();
|
let mut highlights = Vec::new();
|
||||||
|
|
||||||
if let Ok(mut colors) = values {
|
// TODO: alert user of parsing failures in editor
|
||||||
// TODO: alert user of parsing failures in editor
|
let palette = values
|
||||||
let palette = colors
|
.remove("palette")
|
||||||
.remove("palette")
|
.map(|value| {
|
||||||
.map(|value| {
|
ThemePalette::try_from(value).unwrap_or_else(|err| {
|
||||||
ThemePalette::try_from(value).unwrap_or_else(|err| {
|
|
||||||
warn!("{}", err);
|
|
||||||
ThemePalette::default()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.unwrap_or_default();
|
|
||||||
// remove inherits from value to prevent errors
|
|
||||||
let _ = colors.remove("inherits");
|
|
||||||
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);
|
warn!("{}", err);
|
||||||
}
|
ThemePalette::default()
|
||||||
|
})
|
||||||
// these are used both as UI and as highlights
|
})
|
||||||
styles.insert(name.clone(), style);
|
.unwrap_or_default();
|
||||||
scopes.push(name);
|
// remove inherits from value to prevent errors
|
||||||
highlights.push(style);
|
let _ = values.remove("inherits");
|
||||||
|
styles.reserve(values.len());
|
||||||
|
scopes.reserve(values.len());
|
||||||
|
highlights.reserve(values.len());
|
||||||
|
for (name, style_value) in values {
|
||||||
|
let mut style = Style::default();
|
||||||
|
if let Err(err) = palette.parse_style(&mut style, style_value) {
|
||||||
|
warn!("{}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// these are used both as UI and as highlights
|
||||||
|
styles.insert(name.clone(), style);
|
||||||
|
scopes.push(name);
|
||||||
|
highlights.push(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
(styles, scopes, highlights)
|
(styles, scopes, highlights)
|
||||||
|
|
Loading…
Reference in New Issue