Extend UserSyntax to allow font_style and font_weight to be specified

Nate Butler and Marshall Bowers created

Co-Authored-By: Marshall Bowers <1486634+maxdeviant@users.noreply.github.com>

Change summary

crates/theme2/src/themes/ayu.rs               |  3 +
crates/theme2/src/themes/gruvbox.rs           |  6 +++
crates/theme2/src/themes/night_owl.rs         |  2 +
crates/theme2/src/themes/palenight.rs         |  3 +
crates/theme2/src/themes/rose_pine.rs         |  6 +++
crates/theme2/src/themes/solarized.rs         |  3 +
crates/theme2/src/themes/synthwave_84.rs      |  1 
crates/theme2/src/user_theme.rs               | 35 +++++++++++++++++++
crates/theme_importer/src/theme_printer.rs    | 36 ++++++++++++++------
crates/theme_importer/src/vscode/converter.rs | 19 +++++++++-
crates/theme_importer/src/vscode/syntax.rs    | 12 ++++++
11 files changed, 111 insertions(+), 15 deletions(-)

Detailed changes

crates/theme2/src/themes/ayu.rs 🔗

@@ -69,6 +69,7 @@ pub fn ayu() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x787b8099).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -146,6 +147,7 @@ pub fn ayu() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0xb8cfe680).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -223,6 +225,7 @@ pub fn ayu() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0xabb5be8c).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),

crates/theme2/src/themes/gruvbox.rs 🔗

@@ -68,6 +68,7 @@ pub fn gruvbox() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x928374ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -144,6 +145,7 @@ pub fn gruvbox() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x928374ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -220,6 +222,7 @@ pub fn gruvbox() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x928374ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -296,6 +299,7 @@ pub fn gruvbox() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x928374ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -372,6 +376,7 @@ pub fn gruvbox() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x928374ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -448,6 +453,7 @@ pub fn gruvbox() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x928374ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),

crates/theme2/src/themes/night_owl.rs 🔗

@@ -69,6 +69,7 @@ pub fn night_owl() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x637777ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -147,6 +148,7 @@ pub fn night_owl() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x989fb1ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),

crates/theme2/src/themes/palenight.rs 🔗

@@ -69,6 +69,7 @@ pub fn palenight() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x687097ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -146,6 +147,7 @@ pub fn palenight() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x687097ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -223,6 +225,7 @@ pub fn palenight() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x687097ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),

crates/theme2/src/themes/rose_pine.rs 🔗

@@ -70,6 +70,7 @@ pub fn rose_pine() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x6e6a86ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -77,6 +78,7 @@ pub fn rose_pine() -> UserThemeFamily {
                                 "something".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0xebbcbaff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -148,6 +150,7 @@ pub fn rose_pine() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x6e6a86ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -155,6 +158,7 @@ pub fn rose_pine() -> UserThemeFamily {
                                 "something".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0xea9a97ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -226,6 +230,7 @@ pub fn rose_pine() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x9893a5ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -233,6 +238,7 @@ pub fn rose_pine() -> UserThemeFamily {
                                 "something".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0xd7827dff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),

crates/theme2/src/themes/solarized.rs 🔗

@@ -65,6 +65,7 @@ pub fn solarized() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x657b83ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),
@@ -72,6 +73,7 @@ pub fn solarized() -> UserThemeFamily {
                                 "something".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x93a1a1ff).into()),
+                                    font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
                             ),
@@ -135,6 +137,7 @@ pub fn solarized() -> UserThemeFamily {
                                 "comment".into(),
                                 UserHighlightStyle {
                                     color: Some(rgba(0x93a1a1ff).into()),
+                                    font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
                             ),

crates/theme2/src/themes/synthwave_84.rs 🔗

@@ -55,6 +55,7 @@ pub fn synthwave_84() -> UserThemeFamily {
                             "comment".into(),
                             UserHighlightStyle {
                                 color: Some(rgba(0x848bbdff).into()),
+                                font_style: Some(UserFontStyle::Italic),
                                 ..Default::default()
                             },
                         ),

crates/theme2/src/user_theme.rs 🔗

@@ -1,4 +1,4 @@
-use gpui::Hsla;
+use gpui::{FontWeight, Hsla};
 use refineable::Refineable;
 use serde::Deserialize;
 
@@ -36,6 +36,39 @@ pub struct UserSyntaxTheme {
 #[derive(Clone, Default, Deserialize)]
 pub struct UserHighlightStyle {
     pub color: Option<Hsla>,
+    pub font_style: Option<UserFontStyle>,
+    pub font_weight: Option<UserFontWeight>,
+}
+
+#[derive(Clone, Default, Deserialize)]
+pub struct UserFontWeight(pub f32);
+
+impl UserFontWeight {
+    /// Thin weight (100), the thinnest value.
+    pub const THIN: Self = Self(FontWeight::THIN.0);
+    /// Extra light weight (200).
+    pub const EXTRA_LIGHT: Self = Self(FontWeight::EXTRA_LIGHT.0);
+    /// Light weight (300).
+    pub const LIGHT: Self = Self(FontWeight::LIGHT.0);
+    /// Normal (400).
+    pub const NORMAL: Self = Self(FontWeight::NORMAL.0);
+    /// Medium weight (500, higher than normal).
+    pub const MEDIUM: Self = Self(FontWeight::MEDIUM.0);
+    /// Semibold weight (600).
+    pub const SEMIBOLD: Self = Self(FontWeight::SEMIBOLD.0);
+    /// Bold weight (700).
+    pub const BOLD: Self = Self(FontWeight::BOLD.0);
+    /// Extra-bold weight (800).
+    pub const EXTRA_BOLD: Self = Self(FontWeight::EXTRA_BOLD.0);
+    /// Black weight (900), the thickest value.
+    pub const BLACK: Self = Self(FontWeight::BLACK.0);
+}
+
+#[derive(Debug, Clone, Copy, Deserialize)]
+pub enum UserFontStyle {
+    Normal,
+    Italic,
+    Oblique,
 }
 
 impl UserHighlightStyle {

crates/theme_importer/src/theme_printer.rs 🔗

@@ -364,19 +364,33 @@ pub struct UserHighlightStylePrinter<'a>(&'a UserHighlightStyle);
 
 impl<'a> Debug for UserHighlightStylePrinter<'a> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let fields = vec![("color", self.0.color)];
-
         f.write_str("UserHighlightStyle {")?;
 
-        for (field_name, value) in fields {
-            if let Some(color) = value {
-                f.write_str(field_name)?;
-                f.write_str(": ")?;
-                f.write_str("Some(")?;
-                HslaPrinter(color).fmt(f)?;
-                f.write_str(")")?;
-                f.write_str(",")?;
-            }
+        if let Some(color) = self.0.color {
+            f.write_str("color")?;
+            f.write_str(": ")?;
+            f.write_str("Some(")?;
+            HslaPrinter(color).fmt(f)?;
+            f.write_str(")")?;
+            f.write_str(",")?;
+        }
+
+        if let Some(font_style) = self.0.font_style {
+            f.write_str("font_style")?;
+            f.write_str(": ")?;
+            f.write_str("Some(")?;
+            write!(f, "UserFontStyle::{:?}", font_style)?;
+            f.write_str(")")?;
+            f.write_str(",")?;
+        }
+
+        if let Some(font_weight) = self.0.font_weight.as_ref() {
+            f.write_str("font_weight")?;
+            f.write_str(": ")?;
+            f.write_str("Some(")?;
+            write!(f, "UserFontWeight({:?})", font_weight.0)?;
+            f.write_str(")")?;
+            f.write_str(",")?;
         }
 
         f.write_str("..Default::default()")?;

crates/theme_importer/src/vscode/converter.rs 🔗

@@ -2,8 +2,8 @@ use anyhow::Result;
 use gpui::{Hsla, Rgba};
 use indexmap::IndexMap;
 use theme::{
-    StatusColorsRefinement, ThemeColorsRefinement, UserSyntaxTheme, UserTheme,
-    UserThemeStylesRefinement,
+    StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, UserSyntaxTheme,
+    UserTheme, UserThemeStylesRefinement,
 };
 
 use crate::util::Traverse;
@@ -14,6 +14,21 @@ pub(crate) fn try_parse_color(color: &str) -> Result<Hsla> {
     Ok(Rgba::try_from(color)?.into())
 }
 
+pub(crate) fn try_parse_font_weight(font_style: &str) -> Option<UserFontWeight> {
+    match font_style {
+        style if style.contains("bold") => Some(UserFontWeight::BOLD),
+        _ => None,
+    }
+}
+
+pub(crate) fn try_parse_font_style(font_style: &str) -> Option<UserFontStyle> {
+    match font_style {
+        style if style.contains("italic") => Some(UserFontStyle::Italic),
+        style if style.contains("oblique") => Some(UserFontStyle::Oblique),
+        _ => None,
+    }
+}
+
 pub struct VsCodeThemeConverter {
     theme: VsCodeTheme,
     theme_metadata: ThemeMetadata,

crates/theme_importer/src/vscode/syntax.rs 🔗

@@ -8,7 +8,7 @@ use serde::Deserialize;
 use theme::UserHighlightStyle;
 
 use crate::util::Traverse;
-use crate::vscode::try_parse_color;
+use crate::vscode::{try_parse_color, try_parse_font_style, try_parse_font_weight};
 
 #[derive(Debug, Deserialize)]
 #[serde(untagged)]
@@ -52,6 +52,16 @@ impl VsCodeTokenColor {
                     .foreground
                     .as_ref()
                     .traverse(|color| try_parse_color(&color))?,
+                font_style: self
+                    .settings
+                    .font_style
+                    .as_ref()
+                    .and_then(|style| try_parse_font_style(&style)),
+                font_weight: self
+                    .settings
+                    .font_style
+                    .as_ref()
+                    .and_then(|style| try_parse_font_weight(&style)),
             };
 
             if highlight_style.is_empty() {