Merge remote-tracking branch 'origin/main' into editor-movement

Antonio Scandurra created

Change summary

crates/editor2/src/display_map.rs                | 100 +++---
crates/editor2/src/editor.rs                     | 282 ++++++++---------
crates/editor2/src/element.rs                    |  15 
crates/editor2/src/highlight_matching_bracket.rs |   2 
crates/editor2/src/movement.rs                   |   3 
crates/gpui2/src/action.rs                       |   4 
crates/gpui2/src/window.rs                       |  11 
crates/language2/src/highlight_map.rs            |   2 
crates/theme2/src/colors.rs                      |   4 
crates/theme2/src/default_colors.rs              |   4 
crates/theme2/src/default_theme.rs               |   6 
crates/theme2/src/registry.rs                    |   2 
crates/theme2/src/syntax.rs                      |   4 
crates/theme2/src/theme2.rs                      |  23 +
14 files changed, 240 insertions(+), 222 deletions(-)

Detailed changes

crates/editor2/src/display_map.rs 🔗

@@ -12,7 +12,9 @@ use crate::{
 pub use block_map::{BlockMap, BlockPoint};
 use collections::{BTreeMap, HashMap, HashSet};
 use fold_map::FoldMap;
-use gpui::{Font, FontId, HighlightStyle, Hsla, Line, Model, ModelContext, Pixels, UnderlineStyle};
+use gpui::{
+    Font, FontId, HighlightStyle, Hsla, Line, Model, ModelContext, Pixels, TextRun, UnderlineStyle,
+};
 use inlay_map::InlayMap;
 use language::{
     language_settings::language_settings, OffsetUtf16, Point, Subscription as BufferSubscription,
@@ -21,7 +23,7 @@ use lsp::DiagnosticSeverity;
 use std::{any::TypeId, borrow::Cow, fmt::Debug, num::NonZeroU32, ops::Range, sync::Arc};
 use sum_tree::{Bias, TreeMap};
 use tab_map::TabMap;
-use theme::Theme;
+use theme::{SyntaxTheme, Theme};
 use wrap_map::WrapMap;
 
 pub use block_map::{
@@ -505,18 +507,18 @@ impl DisplaySnapshot {
         &'a self,
         display_rows: Range<u32>,
         language_aware: bool,
-        theme: &'a Theme,
+        editor_style: &'a EditorStyle,
     ) -> impl Iterator<Item = HighlightedChunk<'a>> {
         self.chunks(
             display_rows,
             language_aware,
-            None, // todo!("add inlay highlight style")
-            None, // todo!("add suggestion highlight style")
+            Some(editor_style.syntax.inlay_style),
+            Some(editor_style.syntax.suggestion_style),
         )
         .map(|chunk| {
             let mut highlight_style = chunk
                 .syntax_highlight_id
-                .and_then(|id| id.style(&theme.styles.syntax));
+                .and_then(|id| id.style(&editor_style.syntax));
 
             if let Some(chunk_highlight) = chunk.highlight_style {
                 if let Some(highlight_style) = highlight_style.as_mut() {
@@ -535,7 +537,8 @@ impl DisplaySnapshot {
             if let Some(severity) = chunk.diagnostic_severity {
                 // Omit underlines for HINT/INFO diagnostics on 'unnecessary' code.
                 if severity <= DiagnosticSeverity::WARNING || !chunk.is_unnecessary {
-                    let diagnostic_color = super::diagnostic_style(severity, true, theme);
+                    let diagnostic_color =
+                        super::diagnostic_style(severity, true, &editor_style.diagnostic_style);
                     diagnostic_highlight.underline = Some(UnderlineStyle {
                         color: Some(diagnostic_color),
                         thickness: 1.0.into(),
@@ -564,53 +567,46 @@ impl DisplaySnapshot {
         TextLayoutDetails {
             text_system,
             editor_style,
+            rem_size,
         }: &TextLayoutDetails,
     ) -> Line {
-        todo!()
-        // let mut styles = Vec::new();
-        // let mut line = String::new();
-        // let mut ended_in_newline = false;
-
-        // let range = display_row..display_row + 1;
-        // for chunk in self.highlighted_chunks(range, false, editor_style) {
-        //     line.push_str(chunk.chunk);
-
-        //     let text_style = if let Some(style) = chunk.style {
-        //         editor_style
-        //             .text
-        //             .clone()
-        //             .highlight(style, text_system)
-        //             .map(Cow::Owned)
-        //             .unwrap_or_else(|_| Cow::Borrowed(&editor_style.text))
-        //     } else {
-        //         Cow::Borrowed(&editor_style.text)
-        //     };
-        //     ended_in_newline = chunk.chunk.ends_with("\n");
-
-        //     styles.push(
-        //         todo!(), // len: chunk.chunk.len(),
-        //                  // font_id: text_style.font_id,
-        //                  // color: text_style.color,
-        //                  // underline: text_style.underline,
-        //     );
-        // }
-
-        // // our pixel positioning logic assumes each line ends in \n,
-        // // this is almost always true except for the last line which
-        // // may have no trailing newline.
-        // if !ended_in_newline && display_row == self.max_point().row() {
-        //     line.push_str("\n");
-
-        //     todo!();
-        //     // styles.push(RunStyle {
-        //     //     len: "\n".len(),
-        //     //     font_id: editor_style.text.font_id,
-        //     //     color: editor_style.text_color,
-        //     //     underline: editor_style.text.underline,
-        //     // });
-        // }
-
-        // text_system.layout_text(&line, editor_style.text.font_size, &styles, None)
+        let mut runs = Vec::new();
+        let mut line = String::new();
+        let mut ended_in_newline = false;
+
+        let range = display_row..display_row + 1;
+        for chunk in self.highlighted_chunks(range, false, &editor_style) {
+            line.push_str(chunk.chunk);
+
+            let text_style = if let Some(style) = chunk.style {
+                editor_style
+                    .text
+                    .clone()
+                    .highlight(style)
+                    .map(Cow::Owned)
+                    .unwrap_or_else(|_| Cow::Borrowed(&editor_style.text))
+            } else {
+                Cow::Borrowed(&editor_style.text)
+            };
+            ended_in_newline = chunk.chunk.ends_with("\n");
+
+            runs.push(text_style.to_run(chunk.chunk.len()))
+        }
+
+        // our pixel positioning logic assumes each line ends in \n,
+        // this is almost always true except for the last line which
+        // may have no trailing newline.
+        if !ended_in_newline && display_row == self.max_point().row() {
+            line.push_str("\n");
+            runs.push(editor_style.text.to_run("\n".len()));
+        }
+
+        let font_size = editor_style.text.font_size.to_pixels(*rem_size);
+        text_system
+            .layout_text(&line, font_size, &runs, None)
+            .unwrap()
+            .pop()
+            .unwrap()
     }
 
     pub fn x_for_point(

crates/editor2/src/editor.rs 🔗

@@ -36,9 +36,10 @@ pub use element::{
 use futures::FutureExt;
 use fuzzy::{StringMatch, StringMatchCandidate};
 use gpui::{
-    div, px, AnyElement, AppContext, BackgroundExecutor, Context, DispatchContext, Div, Element,
-    Entity, EventEmitter, FocusHandle, FontStyle, FontWeight, Hsla, Model, Pixels, Render, Styled,
-    Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakView, WindowContext,
+    actions, div, px, AnyElement, AppContext, BackgroundExecutor, Context, DispatchContext, Div,
+    Element, Entity, EventEmitter, FocusHandle, FontStyle, FontWeight, Hsla, Model, Pixels, Render,
+    Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakView,
+    WindowContext,
 };
 use highlight_matching_bracket::refresh_matching_bracket_highlights;
 use hover_popover::{hide_hover, HoverState};
@@ -82,7 +83,9 @@ use std::{
 pub use sum_tree::Bias;
 use sum_tree::TreeMap;
 use text::Rope;
-use theme::{ActiveTheme, PlayerColor, Theme, ThemeColors, ThemeSettings};
+use theme::{
+    ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, Theme, ThemeColors, ThemeSettings,
+};
 use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
 use workspace::{ItemNavHistory, SplitDirection, ViewId, Workspace};
 
@@ -257,118 +260,115 @@ impl InlayId {
     }
 }
 
-// actions!(
-//     editor,
-//     [
-//         Cancel,
-//         Backspace,
-//         Delete,
-//         Newline,
-//         NewlineAbove,
-//         NewlineBelow,
-//         GoToDiagnostic,
-//         GoToPrevDiagnostic,
-//         GoToHunk,
-//         GoToPrevHunk,
-//         Indent,
-//         Outdent,
-//         DeleteLine,
-//         DeleteToPreviousWordStart,
-//         DeleteToPreviousSubwordStart,
-//         DeleteToNextWordEnd,
-//         DeleteToNextSubwordEnd,
-//         DeleteToBeginningOfLine,
-//         DeleteToEndOfLine,
-//         CutToEndOfLine,
-//         DuplicateLine,
-//         MoveLineUp,
-//         MoveLineDown,
-//         JoinLines,
-//         SortLinesCaseSensitive,
-//         SortLinesCaseInsensitive,
-//         ReverseLines,
-//         ShuffleLines,
-//         ConvertToUpperCase,
-//         ConvertToLowerCase,
-//         ConvertToTitleCase,
-//         ConvertToSnakeCase,
-//         ConvertToKebabCase,
-//         ConvertToUpperCamelCase,
-//         ConvertToLowerCamelCase,
-//         Transpose,
-//         Cut,
-//         Copy,
-//         Paste,
-//         Undo,
-//         Redo,
-//         MoveUp,
-//         PageUp,
-//         MoveDown,
-//         PageDown,
-//         MoveLeft,
-//         MoveRight,
-//         MoveToPreviousWordStart,
-//         MoveToPreviousSubwordStart,
-//         MoveToNextWordEnd,
-//         MoveToNextSubwordEnd,
-//         MoveToBeginningOfLine,
-//         MoveToEndOfLine,
-//         MoveToStartOfParagraph,
-//         MoveToEndOfParagraph,
-//         MoveToBeginning,
-//         MoveToEnd,
-//         SelectUp,
-//         SelectDown,
-//         SelectLeft,
-//         SelectRight,
-//         SelectToPreviousWordStart,
-//         SelectToPreviousSubwordStart,
-//         SelectToNextWordEnd,
-//         SelectToNextSubwordEnd,
-//         SelectToStartOfParagraph,
-//         SelectToEndOfParagraph,
-//         SelectToBeginning,
-//         SelectToEnd,
-//         SelectAll,
-//         SelectLine,
-//         SplitSelectionIntoLines,
-//         AddSelectionAbove,
-//         AddSelectionBelow,
-//         Tab,
-//         TabPrev,
-//         ShowCharacterPalette,
-//         SelectLargerSyntaxNode,
-//         SelectSmallerSyntaxNode,
-//         GoToDefinition,
-//         GoToDefinitionSplit,
-//         GoToTypeDefinition,
-//         GoToTypeDefinitionSplit,
-//         MoveToEnclosingBracket,
-//         UndoSelection,
-//         RedoSelection,
-//         FindAllReferences,
-//         Rename,
-//         ConfirmRename,
-//         Fold,
-//         UnfoldLines,
-//         FoldSelectedRanges,
-//         ShowCompletions,
-//         OpenExcerpts,
-//         RestartLanguageServer,
-//         Hover,
-//         Format,
-//         ToggleSoftWrap,
-//         ToggleInlayHints,
-//         RevealInFinder,
-//         CopyPath,
-//         CopyRelativePath,
-//         CopyHighlightJson,
-//         ContextMenuFirst,
-//         ContextMenuPrev,
-//         ContextMenuNext,
-//         ContextMenuLast,
-//     ]
-// );
+actions!(
+    Cancel,
+    Backspace,
+    Delete,
+    Newline,
+    NewlineAbove,
+    NewlineBelow,
+    GoToDiagnostic,
+    GoToPrevDiagnostic,
+    GoToHunk,
+    GoToPrevHunk,
+    Indent,
+    Outdent,
+    DeleteLine,
+    DeleteToPreviousWordStart,
+    DeleteToPreviousSubwordStart,
+    DeleteToNextWordEnd,
+    DeleteToNextSubwordEnd,
+    DeleteToBeginningOfLine,
+    DeleteToEndOfLine,
+    CutToEndOfLine,
+    DuplicateLine,
+    MoveLineUp,
+    MoveLineDown,
+    JoinLines,
+    SortLinesCaseSensitive,
+    SortLinesCaseInsensitive,
+    ReverseLines,
+    ShuffleLines,
+    ConvertToUpperCase,
+    ConvertToLowerCase,
+    ConvertToTitleCase,
+    ConvertToSnakeCase,
+    ConvertToKebabCase,
+    ConvertToUpperCamelCase,
+    ConvertToLowerCamelCase,
+    Transpose,
+    Cut,
+    Copy,
+    Paste,
+    Undo,
+    Redo,
+    MoveUp,
+    PageUp,
+    MoveDown,
+    PageDown,
+    MoveLeft,
+    MoveRight,
+    MoveToPreviousWordStart,
+    MoveToPreviousSubwordStart,
+    MoveToNextWordEnd,
+    MoveToNextSubwordEnd,
+    MoveToBeginningOfLine,
+    MoveToEndOfLine,
+    MoveToStartOfParagraph,
+    MoveToEndOfParagraph,
+    MoveToBeginning,
+    MoveToEnd,
+    SelectUp,
+    SelectDown,
+    SelectLeft,
+    SelectRight,
+    SelectToPreviousWordStart,
+    SelectToPreviousSubwordStart,
+    SelectToNextWordEnd,
+    SelectToNextSubwordEnd,
+    SelectToStartOfParagraph,
+    SelectToEndOfParagraph,
+    SelectToBeginning,
+    SelectToEnd,
+    SelectAll,
+    SelectLine,
+    SplitSelectionIntoLines,
+    AddSelectionAbove,
+    AddSelectionBelow,
+    Tab,
+    TabPrev,
+    ShowCharacterPalette,
+    SelectLargerSyntaxNode,
+    SelectSmallerSyntaxNode,
+    GoToDefinition,
+    GoToDefinitionSplit,
+    GoToTypeDefinition,
+    GoToTypeDefinitionSplit,
+    MoveToEnclosingBracket,
+    UndoSelection,
+    RedoSelection,
+    FindAllReferences,
+    Rename,
+    ConfirmRename,
+    Fold,
+    UnfoldLines,
+    FoldSelectedRanges,
+    ShowCompletions,
+    OpenExcerpts,
+    RestartLanguageServer,
+    Hover,
+    Format,
+    ToggleSoftWrap,
+    ToggleInlayHints,
+    RevealInFinder,
+    CopyPath,
+    CopyRelativePath,
+    CopyHighlightJson,
+    ContextMenuFirst,
+    ContextMenuPrev,
+    ContextMenuNext,
+    ContextMenuLast,
+);
 
 // impl_actions!(
 //     editor,
@@ -390,26 +390,6 @@ impl InlayId {
 //     ]
 // );
 
-// todo!(revisit these actions)
-pub struct ShowCompletions;
-pub struct Rename;
-pub struct GoToDefinition;
-pub struct GoToTypeDefinition;
-pub struct GoToDefinitionSplit;
-pub struct GoToTypeDefinitionSplit;
-
-#[derive(PartialEq, Clone, Default, Deserialize)]
-pub struct MoveLeft;
-
-#[derive(PartialEq, Clone, Default, Deserialize)]
-pub struct MoveRight;
-
-#[derive(PartialEq, Clone, Default, Deserialize)]
-pub struct MoveDown;
-
-#[derive(PartialEq, Clone, Default, Deserialize)]
-pub struct MoveUp;
-
 enum DocumentHighlightRead {}
 enum DocumentHighlightWrite {}
 enum InputComposition {}
@@ -615,6 +595,8 @@ pub struct EditorStyle {
     pub text: TextStyle,
     pub line_height_scalar: f32,
     pub scrollbar_width: Pixels,
+    pub syntax: Arc<SyntaxTheme>,
+    pub diagnostic_style: DiagnosticStyle,
 }
 
 type CompletionId = usize;
@@ -3543,6 +3525,7 @@ impl Editor {
         TextLayoutDetails {
             text_system: cx.text_system().clone(),
             editor_style: self.style.clone().unwrap(),
+            rem_size: cx.rem_size(),
         }
     }
 
@@ -5862,7 +5845,6 @@ impl Editor {
     //     }
 
     pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
-        dbg!("move_down");
         self.take_rename(true, cx);
 
         if self.mode == EditorMode::SingleLine {
@@ -9399,6 +9381,8 @@ impl Render for Editor {
             text: text_style,
             line_height_scalar: settings.buffer_line_height.value(),
             scrollbar_width: px(12.),
+            syntax: cx.theme().syntax().clone(),
+            diagnostic_style: cx.theme().diagnostic_style(),
         })
     }
 }
@@ -9982,17 +9966,21 @@ pub fn highlight_diagnostic_message(
     (message_without_backticks, highlights)
 }
 
-pub fn diagnostic_style(severity: DiagnosticSeverity, valid: bool, theme: &Theme) -> Hsla {
+pub fn diagnostic_style(
+    severity: DiagnosticSeverity,
+    valid: bool,
+    style: &DiagnosticStyle,
+) -> Hsla {
     match (severity, valid) {
-        (DiagnosticSeverity::ERROR, true) => theme.status().error,
-        (DiagnosticSeverity::ERROR, false) => theme.status().error,
-        (DiagnosticSeverity::WARNING, true) => theme.status().warning,
-        (DiagnosticSeverity::WARNING, false) => theme.status().warning,
-        (DiagnosticSeverity::INFORMATION, true) => theme.status().info,
-        (DiagnosticSeverity::INFORMATION, false) => theme.status().info,
-        (DiagnosticSeverity::HINT, true) => theme.status().info,
-        (DiagnosticSeverity::HINT, false) => theme.status().info,
-        _ => theme.status().ignored,
+        (DiagnosticSeverity::ERROR, true) => style.error,
+        (DiagnosticSeverity::ERROR, false) => style.error,
+        (DiagnosticSeverity::WARNING, true) => style.warning,
+        (DiagnosticSeverity::WARNING, false) => style.warning,
+        (DiagnosticSeverity::INFORMATION, true) => style.info,
+        (DiagnosticSeverity::INFORMATION, false) => style.info,
+        (DiagnosticSeverity::HINT, true) => style.info,
+        (DiagnosticSeverity::HINT, false) => style.info,
+        _ => style.ignored,
     }
 }
 

crates/editor2/src/element.rs 🔗

@@ -1577,12 +1577,10 @@ impl EditorElement {
                 })
                 .collect()
         } else {
-            let style = &self.style;
-            let chunks = snapshot.highlighted_chunks(rows.clone(), true, cx.theme());
-
+            let chunks = snapshot.highlighted_chunks(rows.clone(), true, &self.style);
             LineWithInvisibles::from_chunks(
                 chunks,
-                &style.text,
+                &self.style.text,
                 MAX_LINE_LEN,
                 rows.len() as usize,
                 line_number_layouts,
@@ -2560,6 +2558,10 @@ impl Element<Editor> for EditorElement {
             cx.with_key_dispatch_context(dispatch_context, |cx| {
                 cx.with_key_listeners(
                     [
+                        build_action_listener(Editor::move_left),
+                        build_action_listener(Editor::move_right),
+                        build_action_listener(Editor::move_down),
+                        build_action_listener(Editor::move_up),
                         build_key_listener(
                             move |editor, key_down: &KeyDownEvent, dispatch_context, phase, cx| {
                                 if phase == DispatchPhase::Bubble {
@@ -2568,7 +2570,6 @@ impl Element<Editor> for EditorElement {
                                         &key_down.keystroke,
                                         dispatch_context,
                                     ) {
-                                        dbg!(action.as_any());
                                         return Some(action);
                                     }
                                 }
@@ -2576,10 +2577,6 @@ impl Element<Editor> for EditorElement {
                                 None
                             },
                         ),
-                        build_action_listener(Editor::move_left),
-                        build_action_listener(Editor::move_right),
-                        build_action_listener(Editor::move_down),
-                        build_action_listener(Editor::move_up),
                     ],
                     |cx| cx.with_focus(editor.focus_handle.clone(), |_| {}),
                 );

crates/editor2/src/highlight_matching_bracket.rs 🔗

@@ -24,7 +24,7 @@ pub fn refresh_matching_bracket_highlights(editor: &mut Editor, cx: &mut ViewCon
                 opening_range.to_anchors(&snapshot.buffer_snapshot),
                 closing_range.to_anchors(&snapshot.buffer_snapshot),
             ],
-            |theme| todo!("theme.editor.document_highlight_read_background"),
+            |theme| theme.editor_document_highlight_read_background,
             cx,
         )
     }

crates/editor2/src/movement.rs 🔗

@@ -1,6 +1,6 @@
 use super::{Bias, DisplayPoint, DisplaySnapshot, SelectionGoal, ToDisplayPoint};
 use crate::{char_kind, CharKind, EditorStyle, ToOffset, ToPoint};
-use gpui::{px, TextSystem};
+use gpui::{px, Pixels, TextSystem};
 use language::Point;
 use serde::de::IntoDeserializer;
 use std::{ops::Range, sync::Arc};
@@ -16,6 +16,7 @@ pub enum FindRange {
 pub struct TextLayoutDetails {
     pub text_system: Arc<TextSystem>,
     pub editor_style: EditorStyle,
+    pub rem_size: Pixels,
 }
 
 pub fn left(map: &DisplaySnapshot, mut point: DisplayPoint) -> DisplayPoint {

crates/gpui2/src/action.rs 🔗

@@ -24,12 +24,12 @@ macro_rules! actions {
 
     ( $name:ident ) => {
         #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug, ::std::cmp::PartialEq, $crate::serde::Deserialize)]
-        struct $name;
+        pub struct $name;
     };
 
     ( $name:ident { $($token:tt)* } ) => {
         #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug, ::std::cmp::PartialEq, $crate::serde::Deserialize)]
-        struct $name { $($token)* }
+        pub struct $name { $($token)* }
     };
 
     ( $name:ident, $($rest:tt)* ) => {

crates/gpui2/src/window.rs 🔗

@@ -300,7 +300,8 @@ impl Window {
 
 /// When constructing the element tree, we maintain a stack of key dispatch frames until we
 /// find the focused element. We interleave key listeners with dispatch contexts so we can use the
-/// contexts when matching key events against the keymap.
+/// contexts when matching key events against the keymap. A key listener can be either an action
+/// handler or a [KeyDown] / [KeyUp] event listener.
 enum KeyDispatchStackFrame {
     Listener {
         event_type: TypeId,
@@ -1048,6 +1049,10 @@ impl<'a> WindowContext<'a> {
 
     /// Dispatch a mouse or keyboard event on the window.
     pub fn dispatch_event(&mut self, event: InputEvent) -> bool {
+        // Handlers may set this to false by calling `stop_propagation`
+        self.app.propagate_event = true;
+        self.window.default_prevented = false;
+
         let event = match event {
             // Track the mouse position with our own state, since accessing the platform
             // API for the mouse position can only occur on the main thread.
@@ -1101,10 +1106,6 @@ impl<'a> WindowContext<'a> {
         };
 
         if let Some(any_mouse_event) = event.mouse_event() {
-            // Handlers may set this to false by calling `stop_propagation`
-            self.app.propagate_event = true;
-            self.window.default_prevented = false;
-
             if let Some(mut handlers) = self
                 .window
                 .mouse_listeners

crates/language2/src/highlight_map.rs 🔗

@@ -95,6 +95,8 @@ mod tests {
             .iter()
             .map(|(name, color)| (name.to_string(), (*color).into()))
             .collect(),
+            inlay_style: HighlightStyle::default(),
+            suggestion_style: HighlightStyle::default(),
         };
 
         let capture_names = &[

crates/theme2/src/colors.rs 🔗

@@ -1,3 +1,5 @@
+use std::sync::Arc;
+
 use gpui::Hsla;
 use refineable::Refineable;
 
@@ -145,7 +147,7 @@ pub struct ThemeStyles {
     pub status: StatusColors,
     pub git: GitStatusColors,
     pub player: PlayerColors,
-    pub syntax: SyntaxTheme,
+    pub syntax: Arc<SyntaxTheme>,
 }
 
 #[cfg(test)]

crates/theme2/src/default_colors.rs 🔗

@@ -138,6 +138,8 @@ impl SyntaxTheme {
                 ("variable.special".into(), red().light().step_7().into()),
                 ("variant".into(), red().light().step_7().into()),
             ],
+            inlay_style: tomato().light().step_1().into(), // todo!("nate: use a proper style")
+            suggestion_style: orange().light().step_1().into(), // todo!("nate: use proper style")
         }
     }
 
@@ -193,6 +195,8 @@ impl SyntaxTheme {
                 ("variable.special".into(), red().dark().step_7().into()),
                 ("variant".into(), red().dark().step_7().into()),
             ],
+            inlay_style: tomato().dark().step_1().into(), // todo!("nate: use a proper style")
+            suggestion_style: orange().dark().step_1().into(), // todo!("nate: use a proper style")
         }
     }
 }

crates/theme2/src/default_theme.rs 🔗

@@ -1,3 +1,5 @@
+use std::sync::Arc;
+
 use crate::{
     colors::{GitStatusColors, PlayerColors, StatusColors, SystemColors, ThemeColors, ThemeStyles},
     default_color_scales, Appearance, SyntaxTheme, Theme, ThemeFamily,
@@ -14,7 +16,7 @@ fn zed_pro_daylight() -> Theme {
             status: StatusColors::default(),
             git: GitStatusColors::default(),
             player: PlayerColors::default(),
-            syntax: SyntaxTheme::default_light(),
+            syntax: Arc::new(SyntaxTheme::default_light()),
         },
     }
 }
@@ -30,7 +32,7 @@ pub(crate) fn zed_pro_moonlight() -> Theme {
             status: StatusColors::default(),
             git: GitStatusColors::default(),
             player: PlayerColors::default(),
-            syntax: SyntaxTheme::default_dark(),
+            syntax: Arc::new(SyntaxTheme::default_dark()),
         },
     }
 }

crates/theme2/src/registry.rs 🔗

@@ -52,7 +52,7 @@ impl ThemeRegistry {
                     status: StatusColors::default(),
                     git: GitStatusColors::default(),
                     player: PlayerColors::default(),
-                    syntax: SyntaxTheme::default_dark(),
+                    syntax: Arc::new(SyntaxTheme::default_dark()),
                 },
             }
         }));

crates/theme2/src/syntax.rs 🔗

@@ -3,6 +3,8 @@ use gpui::{HighlightStyle, Hsla};
 #[derive(Clone, Default)]
 pub struct SyntaxTheme {
     pub highlights: Vec<(String, HighlightStyle)>,
+    pub inlay_style: HighlightStyle,
+    pub suggestion_style: HighlightStyle,
 }
 
 impl SyntaxTheme {
@@ -21,6 +23,8 @@ impl SyntaxTheme {
                     )
                 })
                 .collect(),
+            inlay_style: HighlightStyle::default(),
+            suggestion_style: HighlightStyle::default(),
         }
     }
 

crates/theme2/src/theme2.rs 🔗

@@ -77,7 +77,7 @@ impl Theme {
 
     /// Returns the [`SyntaxTheme`] for the theme.
     #[inline(always)]
-    pub fn syntax(&self) -> &SyntaxTheme {
+    pub fn syntax(&self) -> &Arc<SyntaxTheme> {
         &self.styles.syntax
     }
 
@@ -98,4 +98,25 @@ impl Theme {
     pub fn syntax_color(&self, name: &str) -> Hsla {
         self.syntax().color(name)
     }
+
+    /// Returns the [`StatusColors`] for the theme.
+    #[inline(always)]
+    pub fn diagnostic_style(&self) -> DiagnosticStyle {
+        DiagnosticStyle {
+            error: self.status().error,
+            warning: self.status().warning,
+            info: self.status().info,
+            hint: self.status().info,
+            ignored: self.status().ignored,
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct DiagnosticStyle {
+    pub error: Hsla,
+    pub warning: Hsla,
+    pub info: Hsla,
+    pub hint: Hsla,
+    pub ignored: Hsla,
 }