This PR enables required documentation for the `theme` crate starts on documenting it. The end goal is to have all meaningful documentation in the crate filled out – However I'm not sure that just adding `#![deny(missing_docs)]` to the whole crate is the right approach. I don't know that having 200+ "The color of the _ color" field docs is useful however–In the short term I've excluded some of the modules that contain structs with a ton of fields (`colors, `status`, etc.) until we decide what the right solution here is. Next steps are to clean up the crate, removing unused modules or those with low usage in favor of other approaches. Changes in this PR: - Enable the `deny(missing_docs)` lint for the `theme` crate - Start documenting a subset of the crate. - Enable `#![allow(missing_docs)]` for some modules. Release Notes: - N/A
198 lines
6.1 KiB
Rust
198 lines
6.1 KiB
Rust
#![allow(missing_docs)]
|
|
|
|
use std::sync::Arc;
|
|
|
|
use gpui::{HighlightStyle, Hsla};
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
|
pub struct SyntaxTheme {
|
|
pub highlights: Vec<(String, HighlightStyle)>,
|
|
}
|
|
|
|
impl SyntaxTheme {
|
|
#[cfg(any(test, feature = "test-support"))]
|
|
pub fn new_test(colors: impl IntoIterator<Item = (&'static str, Hsla)>) -> Self {
|
|
Self::new_test_styles(colors.into_iter().map(|(key, color)| {
|
|
(
|
|
key,
|
|
HighlightStyle {
|
|
color: Some(color),
|
|
..Default::default()
|
|
},
|
|
)
|
|
}))
|
|
}
|
|
|
|
#[cfg(any(test, feature = "test-support"))]
|
|
pub fn new_test_styles(
|
|
colors: impl IntoIterator<Item = (&'static str, HighlightStyle)>,
|
|
) -> Self {
|
|
Self {
|
|
highlights: colors
|
|
.into_iter()
|
|
.map(|(key, style)| (key.to_owned(), style))
|
|
.collect(),
|
|
}
|
|
}
|
|
|
|
pub fn get(&self, name: &str) -> HighlightStyle {
|
|
self.highlights
|
|
.iter()
|
|
.find_map(|entry| if entry.0 == name { Some(entry.1) } else { None })
|
|
.unwrap_or_default()
|
|
}
|
|
|
|
pub fn color(&self, name: &str) -> Hsla {
|
|
self.get(name).color.unwrap_or_default()
|
|
}
|
|
|
|
pub fn highlight_id(&self, name: &str) -> Option<u32> {
|
|
let ix = self.highlights.iter().position(|entry| entry.0 == name)?;
|
|
Some(ix as u32)
|
|
}
|
|
|
|
/// Returns a new [`Arc<SyntaxTheme>`] with the given syntax styles merged in.
|
|
pub fn merge(base: Arc<Self>, user_syntax_styles: Vec<(String, HighlightStyle)>) -> Arc<Self> {
|
|
if user_syntax_styles.is_empty() {
|
|
return base;
|
|
}
|
|
|
|
let mut merged_highlights = base.highlights.clone();
|
|
|
|
for (name, highlight) in user_syntax_styles {
|
|
if let Some((_, existing_highlight)) = merged_highlights
|
|
.iter_mut()
|
|
.find(|(existing_name, _)| existing_name == &name)
|
|
{
|
|
existing_highlight.color = highlight.color.or(existing_highlight.color);
|
|
existing_highlight.font_weight =
|
|
highlight.font_weight.or(existing_highlight.font_weight);
|
|
existing_highlight.font_style =
|
|
highlight.font_style.or(existing_highlight.font_style);
|
|
existing_highlight.background_color = highlight
|
|
.background_color
|
|
.or(existing_highlight.background_color);
|
|
existing_highlight.underline = highlight.underline.or(existing_highlight.underline);
|
|
existing_highlight.strikethrough =
|
|
highlight.strikethrough.or(existing_highlight.strikethrough);
|
|
existing_highlight.fade_out = highlight.fade_out.or(existing_highlight.fade_out);
|
|
} else {
|
|
merged_highlights.push((name, highlight));
|
|
}
|
|
}
|
|
|
|
Arc::new(Self {
|
|
highlights: merged_highlights,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use gpui::FontStyle;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_syntax_theme_merge() {
|
|
// Merging into an empty `SyntaxTheme` keeps all the user-defined styles.
|
|
let syntax_theme = SyntaxTheme::merge(
|
|
Arc::new(SyntaxTheme::new_test([])),
|
|
vec![
|
|
(
|
|
"foo".to_string(),
|
|
HighlightStyle {
|
|
color: Some(gpui::red()),
|
|
..Default::default()
|
|
},
|
|
),
|
|
(
|
|
"foo.bar".to_string(),
|
|
HighlightStyle {
|
|
color: Some(gpui::green()),
|
|
..Default::default()
|
|
},
|
|
),
|
|
],
|
|
);
|
|
assert_eq!(
|
|
syntax_theme,
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::red()),
|
|
("foo.bar", gpui::green())
|
|
]))
|
|
);
|
|
|
|
// Merging empty user-defined styles keeps all the base styles.
|
|
let syntax_theme = SyntaxTheme::merge(
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::blue()),
|
|
("foo.bar", gpui::red()),
|
|
])),
|
|
Vec::new(),
|
|
);
|
|
assert_eq!(
|
|
syntax_theme,
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::blue()),
|
|
("foo.bar", gpui::red())
|
|
]))
|
|
);
|
|
|
|
let syntax_theme = SyntaxTheme::merge(
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::red()),
|
|
("foo.bar", gpui::green()),
|
|
])),
|
|
vec![(
|
|
"foo.bar".to_string(),
|
|
HighlightStyle {
|
|
color: Some(gpui::yellow()),
|
|
..Default::default()
|
|
},
|
|
)],
|
|
);
|
|
assert_eq!(
|
|
syntax_theme,
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::red()),
|
|
("foo.bar", gpui::yellow())
|
|
]))
|
|
);
|
|
|
|
let syntax_theme = SyntaxTheme::merge(
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::red()),
|
|
("foo.bar", gpui::green()),
|
|
])),
|
|
vec![(
|
|
"foo.bar".to_string(),
|
|
HighlightStyle {
|
|
font_style: Some(FontStyle::Italic),
|
|
..Default::default()
|
|
},
|
|
)],
|
|
);
|
|
assert_eq!(
|
|
syntax_theme,
|
|
Arc::new(SyntaxTheme::new_test_styles([
|
|
(
|
|
"foo",
|
|
HighlightStyle {
|
|
color: Some(gpui::red()),
|
|
..Default::default()
|
|
}
|
|
),
|
|
(
|
|
"foo.bar",
|
|
HighlightStyle {
|
|
color: Some(gpui::green()),
|
|
font_style: Some(FontStyle::Italic),
|
|
..Default::default()
|
|
}
|
|
)
|
|
]))
|
|
);
|
|
}
|
|
}
|