Add support for theme family-specific syntax mapping overrides (#3551)

This PR adds support for adding a specific set of mappings from Zed
syntax tokens to VS Code scopes for a particular theme family.

We can use this as a fallback when we aren't otherwise able to rely on
the mappings in the theme importer, as sometimes it isn't possible to
make a specific enough matcher that works across all of the themes.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2023-12-07 23:37:49 -05:00 committed by GitHub
parent 5b96ffbbd1
commit 7a9f764aa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 11 deletions

View File

@ -17,5 +17,8 @@
"file_name": "rose-pine-dawn.json",
"appearance": "light"
}
]
],
"syntax": {
"function": ["entity.name"]
}
}

View File

@ -106,7 +106,7 @@ pub fn rose_pine() -> UserThemeFamily {
(
"function".into(),
UserHighlightStyle {
color: Some(rgba(0xe0def4ff).into()),
color: Some(rgba(0xebbcbaff).into()),
..Default::default()
},
),
@ -283,7 +283,7 @@ pub fn rose_pine() -> UserThemeFamily {
(
"function".into(),
UserHighlightStyle {
color: Some(rgba(0xe0def4ff).into()),
color: Some(rgba(0xea9a97ff).into()),
..Default::default()
},
),
@ -460,7 +460,7 @@ pub fn rose_pine() -> UserThemeFamily {
(
"function".into(),
UserHighlightStyle {
color: Some(rgba(0x575279ff).into()),
color: Some(rgba(0xd7827eff).into()),
..Default::default()
},
),

View File

@ -10,7 +10,7 @@ publish = false
anyhow.workspace = true
convert_case = "0.6.0"
gpui = { package = "gpui2", path = "../gpui2" }
indexmap = "1.6.2"
indexmap = { version = "1.6.2", features = ["serde"] }
json_comments = "0.2.2"
log.workspace = true
palette = { version = "0.7.3", default-features = false, features = ["std"] }

View File

@ -12,6 +12,7 @@ use std::str::FromStr;
use anyhow::{anyhow, Context, Result};
use convert_case::{Case, Casing};
use gpui::serde_json;
use indexmap::IndexMap;
use json_comments::StripComments;
use log::LevelFilter;
use serde::Deserialize;
@ -27,6 +28,14 @@ struct FamilyMetadata {
pub name: String,
pub author: String,
pub themes: Vec<ThemeMetadata>,
/// Overrides for specific syntax tokens.
///
/// Use this to ensure certain Zed syntax tokens are matched
/// to an exact set of scopes when it is not otherwise possible
/// to rely on the default mappings in the theme importer.
#[serde(default)]
pub syntax: IndexMap<String, Vec<String>>,
}
#[derive(Debug, Clone, Copy, Deserialize)]
@ -127,7 +136,11 @@ fn main() -> Result<()> {
let vscode_theme: VsCodeTheme = serde_json::from_reader(theme_without_comments)
.context(format!("failed to parse theme {theme_file_path:?}"))?;
let converter = VsCodeThemeConverter::new(vscode_theme, theme_metadata);
let converter = VsCodeThemeConverter::new(
vscode_theme,
theme_metadata,
family_metadata.syntax.clone(),
);
let theme = converter.convert()?;

View File

@ -9,7 +9,7 @@ use theme::{
use crate::color::try_parse_color;
use crate::util::Traverse;
use crate::vscode::VsCodeTheme;
use crate::vscode::{VsCodeTheme, VsCodeTokenScope};
use crate::ThemeMetadata;
use super::ZedSyntaxToken;
@ -32,13 +32,19 @@ pub(crate) fn try_parse_font_style(font_style: &str) -> Option<UserFontStyle> {
pub struct VsCodeThemeConverter {
theme: VsCodeTheme,
theme_metadata: ThemeMetadata,
syntax_overrides: IndexMap<String, Vec<String>>,
}
impl VsCodeThemeConverter {
pub fn new(theme: VsCodeTheme, theme_metadata: ThemeMetadata) -> Self {
pub fn new(
theme: VsCodeTheme,
theme_metadata: ThemeMetadata,
syntax_overrides: IndexMap<String, Vec<String>>,
) -> Self {
Self {
theme,
theme_metadata,
syntax_overrides,
}
}
@ -291,8 +297,17 @@ impl VsCodeThemeConverter {
let mut highlight_styles = IndexMap::new();
for syntax_token in ZedSyntaxToken::iter() {
let best_match = syntax_token
.find_best_token_color_match(&self.theme.token_colors)
let override_match = self
.syntax_overrides
.get(&syntax_token.to_string())
.and_then(|scope| {
self.theme.token_colors.iter().find(|token_color| {
token_color.scope == Some(VsCodeTokenScope::Many(scope.clone()))
})
});
let best_match = override_match
.or_else(|| syntax_token.find_best_token_color_match(&self.theme.token_colors))
.or_else(|| {
syntax_token.fallbacks().iter().find_map(|fallback| {
fallback.find_best_token_color_match(&self.theme.token_colors)

View File

@ -2,7 +2,7 @@ use indexmap::IndexMap;
use serde::Deserialize;
use strum::EnumIter;
#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(untagged)]
pub enum VsCodeTokenScope {
One(String),