Show highlighted symbol in the scrollbar (#7029)

Felix Salazar created

Release Notes:

- Added highlighted symbols to the scrollbar; partially mentioned in:
  - https://github.com/zed-industries/zed/issues/5308
  - https://github.com/zed-industries/zed/issues/4866

Change summary

assets/settings/default.json         |  4 +
crates/editor/src/editor_settings.rs |  5 ++
crates/editor/src/element.rs         | 51 +++++++++++++++++++++++++++--
3 files changed, 55 insertions(+), 5 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -111,7 +111,9 @@
     // Whether to show git diff indicators in the scrollbar.
     "git_diff": true,
     // Whether to show selections in the scrollbar.
-    "selections": true
+    "selections": true,
+    // Whether to show symbols selections in the scrollbar.
+    "symbols_selections": true
   },
   "relative_line_numbers": false,
   // When to populate a new search's query based on the text under the cursor.

crates/editor/src/editor_settings.rs 🔗

@@ -31,6 +31,7 @@ pub struct Scrollbar {
     pub show: ShowScrollbar,
     pub git_diff: bool,
     pub selections: bool,
+    pub symbols_selections: bool,
 }
 
 /// When to show the scrollbar in the editor.
@@ -103,6 +104,10 @@ pub struct ScrollbarContent {
     ///
     /// Default: true
     pub selections: Option<bool>,
+    /// Whether to show symbols highlighted markers in the scrollbar.
+    ///
+    /// Default: true
+    pub symbols_selections: Option<bool>,
 }
 
 impl Settings for EditorSettings {

crates/editor/src/element.rs 🔗

@@ -16,9 +16,10 @@ use crate::{
     },
     mouse_context_menu,
     scroll::scroll_amount::ScrollAmount,
-    CursorShape, DisplayPoint, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle,
-    HalfPageDown, HalfPageUp, HoveredCursor, LineDown, LineUp, OpenExcerpts, PageDown, PageUp,
-    Point, SelectPhase, Selection, SoftWrap, ToPoint, CURSORS_VISIBLE_FOR, MAX_LINE_LEN,
+    CursorShape, DisplayPoint, DocumentHighlightRead, DocumentHighlightWrite, Editor, EditorMode,
+    EditorSettings, EditorSnapshot, EditorStyle, HalfPageDown, HalfPageUp, HoveredCursor, LineDown,
+    LineUp, OpenExcerpts, PageDown, PageUp, Point, SelectPhase, Selection, SoftWrap, ToPoint,
+    CURSORS_VISIBLE_FOR, MAX_LINE_LEN,
 };
 use anyhow::Result;
 use collections::{BTreeMap, HashMap};
@@ -1366,6 +1367,44 @@ impl EditorElement {
                 }
             }
 
+            if layout.is_singleton && scrollbar_settings.symbols_selections {
+                let selection_ranges = self.editor.read(cx).background_highlights_in_range(
+                    Anchor::min()..Anchor::max(),
+                    &layout.position_map.snapshot,
+                    cx.theme().colors(),
+                );
+                for hunk in selection_ranges {
+                    let start_display = Point::new(hunk.0.start.row(), 0)
+                        .to_display_point(&layout.position_map.snapshot.display_snapshot);
+                    let end_display = Point::new(hunk.0.end.row(), 0)
+                        .to_display_point(&layout.position_map.snapshot.display_snapshot);
+                    let start_y = y_for_row(start_display.row() as f32);
+                    let mut end_y = if hunk.0.start == hunk.0.end {
+                        y_for_row((end_display.row() + 1) as f32)
+                    } else {
+                        y_for_row((end_display.row()) as f32)
+                    };
+
+                    if end_y - start_y < px(1.) {
+                        end_y = start_y + px(1.);
+                    }
+                    let bounds = Bounds::from_corners(point(left, start_y), point(right, end_y));
+
+                    cx.paint_quad(quad(
+                        bounds,
+                        Corners::default(),
+                        cx.theme().status().info,
+                        Edges {
+                            top: Pixels::ZERO,
+                            right: px(1.),
+                            bottom: Pixels::ZERO,
+                            left: px(1.),
+                        },
+                        cx.theme().colors().scrollbar_thumb_border,
+                    ));
+                }
+            }
+
             if layout.is_singleton && scrollbar_settings.git_diff {
                 for hunk in layout
                     .position_map
@@ -2032,8 +2071,12 @@ impl EditorElement {
                     ||
                     // Selections
                     (is_singleton && scrollbar_settings.selections && editor.has_background_highlights::<BufferSearchHighlights>())
+                    ||
+                    // Symbols Selections
+                    (is_singleton && scrollbar_settings.symbols_selections && (editor.has_background_highlights::<DocumentHighlightRead>() || editor.has_background_highlights::<DocumentHighlightWrite>()))
+                    ||
                     // Scrollmanager
-                    || editor.scroll_manager.scrollbars_visible()
+                    editor.scroll_manager.scrollbars_visible()
                 }
                 ShowScrollbar::System => editor.scroll_manager.scrollbars_visible(),
                 ShowScrollbar::Always => true,