themes: Fix invalid attribute links panic in is_cyclic
Attribute links are not checked for validity in theme validation, and an invalid link would cause a panic in is_cyclic. This commit improves the theme validation errors by printing if the error lies in a theme key or a link.memfd
parent
4930d1b46c
commit
e633434b93
|
@ -323,7 +323,79 @@ pub struct Theme {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Theme {
|
impl Theme {
|
||||||
|
fn validate_keys(
|
||||||
|
name: &str,
|
||||||
|
theme: &HashMap<Cow<'static, str>, ThemeAttributeInner>,
|
||||||
|
hash_set: &HashSet<&'static str>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let keys = theme
|
||||||
|
.keys()
|
||||||
|
.filter_map(|k| {
|
||||||
|
if !hash_set.contains(&k.as_ref()) {
|
||||||
|
Some((None, "key", k.as_ref()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.chain(theme.iter().filter_map(|(key, a)| {
|
||||||
|
if let ThemeValue::Link(ref r) = a.fg {
|
||||||
|
if !hash_set.contains(&r.as_ref()) {
|
||||||
|
Some((Some(key), "fg link", r.as_ref()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.chain(theme.iter().filter_map(|(key, a)| {
|
||||||
|
if let ThemeValue::Link(ref r) = a.bg {
|
||||||
|
if !hash_set.contains(&r.as_ref()) {
|
||||||
|
Some((Some(key), "bg link", r.as_ref()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.chain(theme.iter().filter_map(|(key, a)| {
|
||||||
|
if let ThemeValue::Link(ref r) = a.attrs {
|
||||||
|
if !hash_set.contains(&r.as_ref()) {
|
||||||
|
Some((Some(key), "attrs link", r.as_ref()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.collect::<SmallVec<[(Option<_>, &'_ str, &'_ str); 128]>>();
|
||||||
|
|
||||||
|
if !keys.is_empty() {
|
||||||
|
return Err(format!(
|
||||||
|
"{} theme contains unrecognized theme keywords: {}",
|
||||||
|
name,
|
||||||
|
keys.into_iter()
|
||||||
|
.map(|(key_opt, desc, link)| if let Some(key) = key_opt {
|
||||||
|
format!("{} {}: \"{}\"", key, desc, link)
|
||||||
|
} else {
|
||||||
|
format!("{}: \"{}\"", desc, link)
|
||||||
|
})
|
||||||
|
.collect::<SmallVec<[String; 128]>>()
|
||||||
|
.join(", ")
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
pub fn validate(&self) -> Result<()> {
|
pub fn validate(&self) -> Result<()> {
|
||||||
|
let hash_set: HashSet<&'static str> = DEFAULT_KEYS.into_iter().map(|k| *k).collect();
|
||||||
|
Theme::validate_keys("light", &self.light, &hash_set)?;
|
||||||
|
Theme::validate_keys("dark", &self.dark, &hash_set)?;
|
||||||
|
for (name, t) in self.other_themes.iter() {
|
||||||
|
Theme::validate_keys(name, t, &hash_set)?;
|
||||||
|
}
|
||||||
if let Err(err) = is_cyclic(&self.light) {
|
if let Err(err) = is_cyclic(&self.light) {
|
||||||
return Err(MeliError::new(format!(
|
return Err(MeliError::new(format!(
|
||||||
"light theme contains a cycle: {}",
|
"light theme contains a cycle: {}",
|
||||||
|
@ -344,63 +416,6 @@ impl Theme {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let hash_set: HashSet<&'static str> = DEFAULT_KEYS.into_iter().map(|k| *k).collect();
|
|
||||||
let keys = self
|
|
||||||
.light
|
|
||||||
.keys()
|
|
||||||
.filter_map(|k| {
|
|
||||||
if !hash_set.contains(&k.as_ref()) {
|
|
||||||
Some(k.as_ref())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<SmallVec<[&'_ str; 128]>>();
|
|
||||||
if !keys.is_empty() {
|
|
||||||
return Err(format!(
|
|
||||||
"light theme contains unrecognized theme keywords: {}",
|
|
||||||
keys.join(", ")
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
let keys = self
|
|
||||||
.dark
|
|
||||||
.keys()
|
|
||||||
.filter_map(|k| {
|
|
||||||
if !hash_set.contains(&k.as_ref()) {
|
|
||||||
Some(k.as_ref())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<SmallVec<[&'_ str; 128]>>();
|
|
||||||
if !keys.is_empty() {
|
|
||||||
return Err(format!(
|
|
||||||
"light theme contains unrecognized theme keywords: {}",
|
|
||||||
keys.join(", ")
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
for (name, t) in self.other_themes.iter() {
|
|
||||||
let keys = t
|
|
||||||
.keys()
|
|
||||||
.filter_map(|k| {
|
|
||||||
if !hash_set.contains(&k.as_ref()) {
|
|
||||||
Some(k.as_ref())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<SmallVec<[&'_ str; 128]>>();
|
|
||||||
if !keys.is_empty() {
|
|
||||||
return Err(format!(
|
|
||||||
"`{}` theme contains unrecognized theme keywords: {}",
|
|
||||||
name,
|
|
||||||
keys.join(", ")
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue