Theme hints and suggestions differently

Kirill Bulatov created

Change summary

crates/editor/src/display_map.rs           | 18 ++++++--
crates/editor/src/display_map/block_map.rs | 19 +++++++--
crates/editor/src/display_map/fold_map.rs  | 12 +++--
crates/editor/src/display_map/inlay_map.rs | 47 ++++++++++++++++-------
crates/editor/src/display_map/tab_map.rs   | 17 +++++---
crates/editor/src/display_map/wrap_map.rs  | 19 +++++++--
crates/editor/src/editor.rs                | 13 +++---
crates/editor/src/element.rs               |  7 +++
crates/editor/src/inlay_hint_cache.rs      |  2 
9 files changed, 105 insertions(+), 49 deletions(-)

Detailed changes

crates/editor/src/display_map.rs 🔗

@@ -392,7 +392,13 @@ impl DisplaySnapshot {
     /// Returns text chunks starting at the given display row until the end of the file
     pub fn text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> {
         self.block_snapshot
-            .chunks(display_row..self.max_point().row() + 1, false, None, None)
+            .chunks(
+                display_row..self.max_point().row() + 1,
+                false,
+                None,
+                None,
+                None,
+            )
             .map(|h| h.text)
     }
 
@@ -400,7 +406,7 @@ impl DisplaySnapshot {
     pub fn reverse_text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> {
         (0..=display_row).into_iter().rev().flat_map(|row| {
             self.block_snapshot
-                .chunks(row..row + 1, false, None, None)
+                .chunks(row..row + 1, false, None, None, None)
                 .map(|h| h.text)
                 .collect::<Vec<_>>()
                 .into_iter()
@@ -412,13 +418,15 @@ impl DisplaySnapshot {
         &self,
         display_rows: Range<u32>,
         language_aware: bool,
-        inlay_highlights: Option<HighlightStyle>,
+        hint_highlights: Option<HighlightStyle>,
+        suggestion_highlights: Option<HighlightStyle>,
     ) -> DisplayChunks<'_> {
         self.block_snapshot.chunks(
             display_rows,
             language_aware,
             Some(&self.text_highlights),
-            inlay_highlights,
+            hint_highlights,
+            suggestion_highlights,
         )
     }
 
@@ -1711,7 +1719,7 @@ pub mod tests {
     ) -> Vec<(String, Option<Color>, Option<Color>)> {
         let snapshot = map.update(cx, |map, cx| map.snapshot(cx));
         let mut chunks: Vec<(String, Option<Color>, Option<Color>)> = Vec::new();
-        for chunk in snapshot.chunks(rows, true, None) {
+        for chunk in snapshot.chunks(rows, true, None, None) {
             let syntax_color = chunk
                 .syntax_highlight_id
                 .and_then(|id| id.style(theme)?.color);

crates/editor/src/display_map/block_map.rs 🔗

@@ -573,9 +573,15 @@ impl<'a> BlockMapWriter<'a> {
 impl BlockSnapshot {
     #[cfg(test)]
     pub fn text(&self) -> String {
-        self.chunks(0..self.transforms.summary().output_rows, false, None, None)
-            .map(|chunk| chunk.text)
-            .collect()
+        self.chunks(
+            0..self.transforms.summary().output_rows,
+            false,
+            None,
+            None,
+            None,
+        )
+        .map(|chunk| chunk.text)
+        .collect()
     }
 
     pub fn chunks<'a>(
@@ -583,7 +589,8 @@ impl BlockSnapshot {
         rows: Range<u32>,
         language_aware: bool,
         text_highlights: Option<&'a TextHighlights>,
-        inlay_highlights: Option<HighlightStyle>,
+        hint_highlights: Option<HighlightStyle>,
+        suggestion_highlights: Option<HighlightStyle>,
     ) -> BlockChunks<'a> {
         let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows);
         let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
@@ -616,7 +623,8 @@ impl BlockSnapshot {
                 input_start..input_end,
                 language_aware,
                 text_highlights,
-                inlay_highlights,
+                hint_highlights,
+                suggestion_highlights,
             ),
             input_chunk: Default::default(),
             transforms: cursor,
@@ -1495,6 +1503,7 @@ mod tests {
                         false,
                         None,
                         None,
+                        None,
                     )
                     .map(|chunk| chunk.text)
                     .collect::<String>();

crates/editor/src/display_map/fold_map.rs 🔗

@@ -475,7 +475,7 @@ pub struct FoldSnapshot {
 impl FoldSnapshot {
     #[cfg(test)]
     pub fn text(&self) -> String {
-        self.chunks(FoldOffset(0)..self.len(), false, None, None)
+        self.chunks(FoldOffset(0)..self.len(), false, None, None, None)
             .map(|c| c.text)
             .collect()
     }
@@ -652,7 +652,8 @@ impl FoldSnapshot {
         range: Range<FoldOffset>,
         language_aware: bool,
         text_highlights: Option<&'a TextHighlights>,
-        inlay_highlights: Option<HighlightStyle>,
+        hint_highlights: Option<HighlightStyle>,
+        suggestion_highlights: Option<HighlightStyle>,
     ) -> FoldChunks<'a> {
         let mut transform_cursor = self.transforms.cursor::<(FoldOffset, InlayOffset)>();
 
@@ -674,7 +675,8 @@ impl FoldSnapshot {
                 inlay_start..inlay_end,
                 language_aware,
                 text_highlights,
-                inlay_highlights,
+                hint_highlights,
+                suggestion_highlights,
             ),
             inlay_chunk: None,
             inlay_offset: inlay_start,
@@ -685,7 +687,7 @@ impl FoldSnapshot {
     }
 
     pub fn chars_at(&self, start: FoldPoint) -> impl '_ + Iterator<Item = char> {
-        self.chunks(start.to_offset(self)..self.len(), false, None, None)
+        self.chunks(start.to_offset(self)..self.len(), false, None, None, None)
             .flat_map(|chunk| chunk.text.chars())
     }
 
@@ -1514,7 +1516,7 @@ mod tests {
                 let text = &expected_text[start.0..end.0];
                 assert_eq!(
                     snapshot
-                        .chunks(start..end, false, Some(&highlights), None)
+                        .chunks(start..end, false, Some(&highlights), None, None)
                         .map(|c| c.text)
                         .collect::<String>(),
                     text,

crates/editor/src/display_map/inlay_map.rs 🔗

@@ -194,7 +194,8 @@ pub struct InlayChunks<'a> {
     inlay_chunks: Option<text::Chunks<'a>>,
     output_offset: InlayOffset,
     max_output_offset: InlayOffset,
-    highlight_style: Option<HighlightStyle>,
+    hint_highlight_style: Option<HighlightStyle>,
+    suggestion_highlight_style: Option<HighlightStyle>,
     highlight_endpoints: Peekable<vec::IntoIter<HighlightEndpoint>>,
     active_highlights: BTreeMap<Option<TypeId>, HighlightStyle>,
     snapshot: &'a InlaySnapshot,
@@ -281,9 +282,13 @@ impl<'a> Iterator for InlayChunks<'a> {
 
                 let chunk = inlay_chunks.next().unwrap();
                 self.output_offset.0 += chunk.len();
+                let highlight_style = match inlay.id {
+                    InlayId::Suggestion(_) => self.suggestion_highlight_style,
+                    InlayId::Hint(_) => self.hint_highlight_style,
+                };
                 Chunk {
                     text: chunk,
-                    highlight_style: self.highlight_style,
+                    highlight_style,
                     ..Default::default()
                 }
             }
@@ -576,7 +581,7 @@ impl InlayMap {
         let mut to_remove = Vec::new();
         let mut to_insert = Vec::new();
         let snapshot = &mut self.snapshot;
-        for _ in 0..rng.gen_range(1..=5) {
+        for i in 0..rng.gen_range(1..=5) {
             if self.inlays.is_empty() || rng.gen() {
                 let position = snapshot.buffer.random_byte_range(0, rng).start;
                 let bias = if rng.gen() { Bias::Left } else { Bias::Right };
@@ -595,8 +600,14 @@ impl InlayMap {
                     bias,
                     text
                 );
+
+                let inlay_id = if i % 2 == 0 {
+                    InlayId::Hint(post_inc(next_inlay_id))
+                } else {
+                    InlayId::Suggestion(post_inc(next_inlay_id))
+                };
                 to_insert.push((
-                    InlayId(post_inc(next_inlay_id)),
+                    inlay_id,
                     InlayProperties {
                         position: snapshot.buffer.anchor_at(position, bias),
                         text,
@@ -927,7 +938,8 @@ impl InlaySnapshot {
         range: Range<InlayOffset>,
         language_aware: bool,
         text_highlights: Option<&'a TextHighlights>,
-        inlay_highlight_style: Option<HighlightStyle>,
+        hint_highlights: Option<HighlightStyle>,
+        suggestion_highlights: Option<HighlightStyle>,
     ) -> InlayChunks<'a> {
         let mut cursor = self.transforms.cursor::<(InlayOffset, usize)>();
         cursor.seek(&range.start, Bias::Right, &());
@@ -1002,7 +1014,8 @@ impl InlaySnapshot {
             buffer_chunk: None,
             output_offset: range.start,
             max_output_offset: range.end,
-            highlight_style: inlay_highlight_style,
+            hint_highlight_style: hint_highlights,
+            suggestion_highlight_style: suggestion_highlights,
             highlight_endpoints: highlight_endpoints.into_iter().peekable(),
             active_highlights: Default::default(),
             snapshot: self,
@@ -1011,7 +1024,7 @@ impl InlaySnapshot {
 
     #[cfg(test)]
     pub fn text(&self) -> String {
-        self.chunks(Default::default()..self.len(), false, None, None)
+        self.chunks(Default::default()..self.len(), false, None, None, None)
             .map(|chunk| chunk.text)
             .collect()
     }
@@ -1078,7 +1091,7 @@ mod tests {
         let (inlay_snapshot, _) = inlay_map.splice(
             Vec::new(),
             vec![(
-                InlayId(post_inc(&mut next_inlay_id)),
+                InlayId::Hint(post_inc(&mut next_inlay_id)),
                 InlayProperties {
                     position: buffer.read(cx).snapshot(cx).anchor_after(3),
                     text: "|123|",
@@ -1157,14 +1170,14 @@ mod tests {
             Vec::new(),
             vec![
                 (
-                    InlayId(post_inc(&mut next_inlay_id)),
+                    InlayId::Hint(post_inc(&mut next_inlay_id)),
                     InlayProperties {
                         position: buffer.read(cx).snapshot(cx).anchor_before(3),
                         text: "|123|",
                     },
                 ),
                 (
-                    InlayId(post_inc(&mut next_inlay_id)),
+                    InlayId::Suggestion(post_inc(&mut next_inlay_id)),
                     InlayProperties {
                         position: buffer.read(cx).snapshot(cx).anchor_after(3),
                         text: "|456|",
@@ -1370,21 +1383,21 @@ mod tests {
             Vec::new(),
             vec![
                 (
-                    InlayId(post_inc(&mut next_inlay_id)),
+                    InlayId::Hint(post_inc(&mut next_inlay_id)),
                     InlayProperties {
                         position: buffer.read(cx).snapshot(cx).anchor_before(0),
                         text: "|123|\n",
                     },
                 ),
                 (
-                    InlayId(post_inc(&mut next_inlay_id)),
+                    InlayId::Hint(post_inc(&mut next_inlay_id)),
                     InlayProperties {
                         position: buffer.read(cx).snapshot(cx).anchor_before(4),
                         text: "|456|",
                     },
                 ),
                 (
-                    InlayId(post_inc(&mut next_inlay_id)),
+                    InlayId::Suggestion(post_inc(&mut next_inlay_id)),
                     InlayProperties {
                         position: buffer.read(cx).snapshot(cx).anchor_before(7),
                         text: "\n|567|\n",
@@ -1489,7 +1502,13 @@ mod tests {
                 start = expected_text.clip_offset(start, Bias::Right);
 
                 let actual_text = inlay_snapshot
-                    .chunks(InlayOffset(start)..InlayOffset(end), false, None, None)
+                    .chunks(
+                        InlayOffset(start)..InlayOffset(end),
+                        false,
+                        None,
+                        None,
+                        None,
+                    )
                     .map(|chunk| chunk.text)
                     .collect::<String>();
                 assert_eq!(

crates/editor/src/display_map/tab_map.rs 🔗

@@ -70,6 +70,7 @@ impl TabMap {
                     false,
                     None,
                     None,
+                    None,
                 ) {
                     for (ix, _) in chunk.text.match_indices('\t') {
                         let offset_from_edit = offset_from_edit + (ix as u32);
@@ -182,7 +183,7 @@ impl TabSnapshot {
             self.max_point()
         };
         for c in self
-            .chunks(range.start..line_end, false, None, None)
+            .chunks(range.start..line_end, false, None, None, None)
             .flat_map(|chunk| chunk.text.chars())
         {
             if c == '\n' {
@@ -201,6 +202,7 @@ impl TabSnapshot {
                     false,
                     None,
                     None,
+                    None,
                 )
                 .flat_map(|chunk| chunk.text.chars())
             {
@@ -222,7 +224,8 @@ impl TabSnapshot {
         range: Range<TabPoint>,
         language_aware: bool,
         text_highlights: Option<&'a TextHighlights>,
-        inlay_highlights: Option<HighlightStyle>,
+        hint_highlights: Option<HighlightStyle>,
+        suggestion_highlights: Option<HighlightStyle>,
     ) -> TabChunks<'a> {
         let (input_start, expanded_char_column, to_next_stop) =
             self.to_fold_point(range.start, Bias::Left);
@@ -243,7 +246,8 @@ impl TabSnapshot {
                 input_start..input_end,
                 language_aware,
                 text_highlights,
-                inlay_highlights,
+                hint_highlights,
+                suggestion_highlights,
             ),
             input_column,
             column: expanded_char_column,
@@ -266,7 +270,7 @@ impl TabSnapshot {
 
     #[cfg(test)]
     pub fn text(&self) -> String {
-        self.chunks(TabPoint::zero()..self.max_point(), false, None, None)
+        self.chunks(TabPoint::zero()..self.max_point(), false, None, None, None)
             .map(|chunk| chunk.text)
             .collect()
     }
@@ -595,6 +599,7 @@ mod tests {
                         false,
                         None,
                         None,
+                        None,
                     )
                     .map(|c| c.text)
                     .collect::<String>(),
@@ -669,7 +674,7 @@ mod tests {
             let mut chunks = Vec::new();
             let mut was_tab = false;
             let mut text = String::new();
-            for chunk in snapshot.chunks(start..snapshot.max_point(), false, None, None) {
+            for chunk in snapshot.chunks(start..snapshot.max_point(), false, None, None, None) {
                 if chunk.is_tab != was_tab {
                     if !text.is_empty() {
                         chunks.push((mem::take(&mut text), was_tab));
@@ -738,7 +743,7 @@ mod tests {
             let expected_summary = TextSummary::from(expected_text.as_str());
             assert_eq!(
                 tabs_snapshot
-                    .chunks(start..end, false, None, None)
+                    .chunks(start..end, false, None, None, None)
                     .map(|c| c.text)
                     .collect::<String>(),
                 expected_text,

crates/editor/src/display_map/wrap_map.rs 🔗

@@ -446,6 +446,7 @@ impl WrapSnapshot {
                     false,
                     None,
                     None,
+                    None,
                 );
                 let mut edit_transforms = Vec::<Transform>::new();
                 for _ in edit.new_rows.start..edit.new_rows.end {
@@ -575,7 +576,8 @@ impl WrapSnapshot {
         rows: Range<u32>,
         language_aware: bool,
         text_highlights: Option<&'a TextHighlights>,
-        inlay_highlights: Option<HighlightStyle>,
+        hint_highlights: Option<HighlightStyle>,
+        suggestion_highlights: Option<HighlightStyle>,
     ) -> WrapChunks<'a> {
         let output_start = WrapPoint::new(rows.start, 0);
         let output_end = WrapPoint::new(rows.end, 0);
@@ -593,7 +595,8 @@ impl WrapSnapshot {
                 input_start..input_end,
                 language_aware,
                 text_highlights,
-                inlay_highlights,
+                hint_highlights,
+                suggestion_highlights,
             ),
             input_chunk: Default::default(),
             output_position: output_start,
@@ -1324,8 +1327,14 @@ mod tests {
         }
 
         pub fn text_chunks(&self, wrap_row: u32) -> impl Iterator<Item = &str> {
-            self.chunks(wrap_row..self.max_point().row() + 1, false, None, None)
-                .map(|h| h.text)
+            self.chunks(
+                wrap_row..self.max_point().row() + 1,
+                false,
+                None,
+                None,
+                None,
+            )
+            .map(|h| h.text)
         }
 
         fn verify_chunks(&mut self, rng: &mut impl Rng) {
@@ -1348,7 +1357,7 @@ mod tests {
                 }
 
                 let actual_text = self
-                    .chunks(start_row..end_row, true, None, None)
+                    .chunks(start_row..end_row, true, None, None, None)
                     .map(|c| c.text)
                     .collect::<String>();
                 assert_eq!(

crates/editor/src/editor.rs 🔗

@@ -184,8 +184,11 @@ pub struct GutterHover {
     pub hovered: bool,
 }
 
-#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct InlayId(usize);
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum InlayId {
+    Suggestion(usize),
+    Hint(usize),
+}
 
 actions!(
     editor,
@@ -3449,7 +3452,7 @@ impl Editor {
                 to_remove.push(suggestion.id);
             }
 
-            let suggestion_inlay_id = self.next_inlay_id();
+            let suggestion_inlay_id = InlayId::Suggestion(post_inc(&mut self.next_inlay_id));
             let to_insert = vec![(
                 suggestion_inlay_id,
                 InlayProperties {
@@ -7588,10 +7591,6 @@ impl Editor {
         cx.write_to_clipboard(ClipboardItem::new(lines));
     }
 
-    pub fn next_inlay_id(&mut self) -> InlayId {
-        InlayId(post_inc(&mut self.next_inlay_id))
-    }
-
     pub fn inlay_hint_cache(&self) -> &InlayHintCache {
         &self.inlay_hint_cache
     }

crates/editor/src/element.rs 🔗

@@ -1392,7 +1392,12 @@ impl EditorElement {
         } else {
             let style = &self.style;
             let chunks = snapshot
-                .chunks(rows.clone(), true, Some(style.theme.hint))
+                .chunks(
+                    rows.clone(),
+                    true,
+                    Some(style.theme.hint),
+                    Some(style.theme.suggestion),
+                )
                 .map(|chunk| {
                     let mut highlight_style = chunk
                         .syntax_highlight_id

crates/editor/src/inlay_hint_cache.rs 🔗

@@ -616,7 +616,7 @@ async fn fetch_and_update_hints(
                 for new_hint in new_update.add_to_cache {
                     let new_hint_position = multi_buffer_snapshot
                         .anchor_in_excerpt(query.excerpt_id, new_hint.position);
-                    let new_inlay_id = InlayId(post_inc(&mut editor.next_inlay_id));
+                    let new_inlay_id = InlayId::Hint(post_inc(&mut editor.next_inlay_id));
                     if editor
                         .inlay_hint_cache
                         .allowed_hint_kinds