editor: Add active match highlight for buffer and project search (#44098)

Closes #28617

<img width="400" alt="image"
src="https://github.com/user-attachments/assets/b1c2880c-5744-4bed-a687-5c5e7aa7fef5"
/>

Release Notes:

- Improved visibility of the currently active match when browsing
results in buffer or project search.

---------

Co-authored-by: DarkMatter-999 <darkmatter999official@gmail.com>
This commit is contained in:
Smit Barmase
2025-12-04 03:55:04 +05:30
committed by GitHub
co-authored by DarkMatter-999
parent 87976e91cf
commit 8ad3a150c8
23 changed files with 342 additions and 149 deletions
+16 -13
View File
@@ -726,7 +726,10 @@ impl EditorActionId {
// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
type BackgroundHighlight = (fn(&Theme) -> Hsla, Arc<[Range<Anchor>]>);
type BackgroundHighlight = (
Arc<dyn Fn(&usize, &Theme) -> Hsla + Send + Sync>,
Arc<[Range<Anchor>]>,
);
type GutterHighlight = (fn(&App) -> Hsla, Vec<Range<Anchor>>);
#[derive(Default)]
@@ -6610,7 +6613,7 @@ impl Editor {
editor.update(cx, |editor, cx| {
editor.highlight_background::<Self>(
&ranges_to_highlight,
|theme| theme.colors().editor_highlighted_line_background,
|_, theme| theme.colors().editor_highlighted_line_background,
cx,
);
});
@@ -7012,12 +7015,12 @@ impl Editor {
this.highlight_background::<DocumentHighlightRead>(
&read_ranges,
|theme| theme.colors().editor_document_highlight_read_background,
|_, theme| theme.colors().editor_document_highlight_read_background,
cx,
);
this.highlight_background::<DocumentHighlightWrite>(
&write_ranges,
|theme| theme.colors().editor_document_highlight_write_background,
|_, theme| theme.colors().editor_document_highlight_write_background,
cx,
);
cx.notify();
@@ -7125,7 +7128,7 @@ impl Editor {
if !match_ranges.is_empty() {
editor.highlight_background::<SelectedTextHighlight>(
&match_ranges,
|theme| theme.colors().editor_document_highlight_bracket_background,
|_, theme| theme.colors().editor_document_highlight_bracket_background,
cx,
)
}
@@ -17519,7 +17522,7 @@ impl Editor {
}
editor.highlight_background::<Self>(
&ranges,
|theme| theme.colors().editor_highlighted_line_background,
|_, theme| theme.colors().editor_highlighted_line_background,
cx,
);
}
@@ -20989,7 +20992,7 @@ impl Editor {
pub fn set_search_within_ranges(&mut self, ranges: &[Range<Anchor>], cx: &mut Context<Self>) {
self.highlight_background::<SearchWithinRange>(
ranges,
|colors| colors.colors().editor_document_highlight_read_background,
|_, colors| colors.colors().editor_document_highlight_read_background,
cx,
)
}
@@ -21005,12 +21008,12 @@ impl Editor {
pub fn highlight_background<T: 'static>(
&mut self,
ranges: &[Range<Anchor>],
color_fetcher: fn(&Theme) -> Hsla,
color_fetcher: impl Fn(&usize, &Theme) -> Hsla + Send + Sync + 'static,
cx: &mut Context<Self>,
) {
self.background_highlights.insert(
HighlightKey::Type(TypeId::of::<T>()),
(color_fetcher, Arc::from(ranges)),
(Arc::new(color_fetcher), Arc::from(ranges)),
);
self.scrollbar_marker_state.dirty = true;
cx.notify();
@@ -21020,12 +21023,12 @@ impl Editor {
&mut self,
key: usize,
ranges: &[Range<Anchor>],
color_fetcher: fn(&Theme) -> Hsla,
color_fetcher: impl Fn(&usize, &Theme) -> Hsla + Send + Sync + 'static,
cx: &mut Context<Self>,
) {
self.background_highlights.insert(
HighlightKey::TypePlus(TypeId::of::<T>(), key),
(color_fetcher, Arc::from(ranges)),
(Arc::new(color_fetcher), Arc::from(ranges)),
);
self.scrollbar_marker_state.dirty = true;
cx.notify();
@@ -21250,7 +21253,6 @@ impl Editor {
) -> Vec<(Range<DisplayPoint>, Hsla)> {
let mut results = Vec::new();
for (color_fetcher, ranges) in self.background_highlights.values() {
let color = color_fetcher(theme);
let start_ix = match ranges.binary_search_by(|probe| {
let cmp = probe
.end
@@ -21263,7 +21265,7 @@ impl Editor {
}) {
Ok(i) | Err(i) => i,
};
for range in &ranges[start_ix..] {
for (index, range) in ranges[start_ix..].iter().enumerate() {
if range
.start
.cmp(&search_range.end, &display_snapshot.buffer_snapshot())
@@ -21272,6 +21274,7 @@ impl Editor {
break;
}
let color = color_fetcher(&(start_ix + index), theme);
let start = range.start.to_display_point(display_snapshot);
let end = range.end.to_display_point(display_snapshot);
results.push((start..end, color))
+5 -5
View File
@@ -16978,7 +16978,7 @@ fn test_highlighted_ranges(cx: &mut TestAppContext) {
anchor_range(Point::new(6, 3)..Point::new(6, 5)),
anchor_range(Point::new(8, 4)..Point::new(8, 6)),
],
|_| Hsla::red(),
|_, _| Hsla::red(),
cx,
);
editor.highlight_background::<Type2>(
@@ -16988,7 +16988,7 @@ fn test_highlighted_ranges(cx: &mut TestAppContext) {
anchor_range(Point::new(7, 4)..Point::new(7, 7)),
anchor_range(Point::new(9, 5)..Point::new(9, 8)),
],
|_| Hsla::green(),
|_, _| Hsla::green(),
cx,
);
@@ -23973,7 +23973,7 @@ async fn test_rename_with_duplicate_edits(cx: &mut TestAppContext) {
let highlight_range = highlight_range.to_anchors(&editor.buffer().read(cx).snapshot(cx));
editor.highlight_background::<DocumentHighlightRead>(
&[highlight_range],
|theme| theme.colors().editor_document_highlight_read_background,
|_, theme| theme.colors().editor_document_highlight_read_background,
cx,
);
});
@@ -24051,7 +24051,7 @@ async fn test_rename_without_prepare(cx: &mut TestAppContext) {
let highlight_range = highlight_range.to_anchors(&editor.buffer().read(cx).snapshot(cx));
editor.highlight_background::<DocumentHighlightRead>(
&[highlight_range],
|theme| theme.colors().editor_document_highlight_read_background,
|_, theme| theme.colors().editor_document_highlight_read_background,
cx,
);
});
@@ -27299,7 +27299,7 @@ let result = variable * 2;",
editor.highlight_background::<DocumentHighlightRead>(
&anchor_ranges,
|theme| theme.colors().editor_document_highlight_read_background,
|_, theme| theme.colors().editor_document_highlight_read_background,
cx,
);
});
+1 -1
View File
@@ -518,7 +518,7 @@ fn show_hover(
// Highlight the selected symbol using a background highlight
editor.highlight_background::<HoverState>(
&hover_highlights,
|theme| theme.colors().element_hover, // todo update theme
|_, theme| theme.colors().element_hover, // todo update theme
cx,
);
}
+8 -1
View File
@@ -1487,6 +1487,7 @@ impl SearchableItem for Editor {
fn update_matches(
&mut self,
matches: &[Range<Anchor>],
active_match_index: Option<usize>,
_: &mut Window,
cx: &mut Context<Self>,
) {
@@ -1497,7 +1498,13 @@ impl SearchableItem for Editor {
let updated = existing_range != Some(matches);
self.highlight_background::<BufferSearchHighlights>(
matches,
|theme| theme.colors().search_match_background,
move |index, theme| {
if active_match_index == Some(*index) {
theme.colors().search_active_match_background
} else {
theme.colors().search_match_background
}
},
cx,
);
if updated {