From fb19db00ca15085a3363ce21dbe2e5cfa68dc687 Mon Sep 17 00:00:00 2001 From: smit <0xtimsb@gmail.com> Date: Wed, 19 Feb 2025 17:43:36 +0530 Subject: [PATCH] editor: Do not highlight selected text + Clear highlight preemptively when new selection is detected (#25149) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When selecting text, it highlights all matching occurences along with selected text itself. This causes highlight overlap, which looks bit odd. This PR fixes it. Bonus: Context: We have an edge case (which we already cover) where we don’t want to clear `SelectedTextHighlight` every time the selection changes. This happens when you are dragging the selection across some word, if you clear it directly on selection change, due to debounce wait, the highlight take some time to appear, which causes flickering for the user. We solve this by not clearing it directly but only clearing it when a new selection is found. This avoids the flicker. However, we also need to clear the selection even before the debounce wait if we detect early on that the selection is different from previous ones. Otherwise, the user will have to wait until the debounce time to see it cleared on the screen. The code for this is a little repetitive because we check the buffer state both before and after the debounce. But this is necessary. --- Before: Notice overlapping corners and selected text is bit darker in this case. ![image](https://github.com/user-attachments/assets/ec371079-b513-4216-9f6e-73d1aff99250) After: ![image](https://github.com/user-attachments/assets/0fb9cd58-5d4b-49e8-91cb-78999c3a54a8) Release Notes: - N/A --- crates/editor/src/editor.rs | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index dc4ded40db..38e4b23801 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -4782,6 +4782,15 @@ impl Editor { self.clear_background_highlights::(cx); return; } + if self.selections.count() != 1 || self.selections.line_mode { + self.clear_background_highlights::(cx); + return; + } + let selection = self.selections.newest::(cx); + if selection.is_empty() || selection.start.row != selection.end.row { + self.clear_background_highlights::(cx); + return; + } let debounce = EditorSettings::get_global(cx).selection_highlight_debounce; self.selection_highlight_task = Some(cx.spawn_in(window, |editor, mut cx| async move { cx.background_executor() @@ -4802,6 +4811,7 @@ impl Editor { Some(cx.background_spawn(async move { let mut ranges = Vec::new(); let query = buffer.text_for_range(selection.range()).collect::(); + let selection_anchors = selection.range().to_anchors(&buffer); for range in [buffer.anchor_before(0)..buffer.anchor_after(buffer.len())] { for (search_buffer, search_range, excerpt_id) in buffer.range_to_buffer_ranges(range) @@ -4820,17 +4830,22 @@ impl Editor { .search(search_buffer, Some(search_range.clone())) .await .into_iter() - .map(|match_range| { - let start = search_buffer - .anchor_after(search_range.start + match_range.start); - let end = search_buffer - .anchor_before(search_range.start + match_range.end); - Anchor::range_in_buffer( - excerpt_id, - search_buffer.remote_id(), - start..end, - ) - }), + .filter_map( + |match_range| { + let start = search_buffer.anchor_after( + search_range.start + match_range.start, + ); + let end = search_buffer.anchor_before( + search_range.start + match_range.end, + ); + let range = Anchor::range_in_buffer( + excerpt_id, + search_buffer.remote_id(), + start..end, + ); + (range != selection_anchors).then_some(range) + }, + ), ); } }