Detailed changes
@@ -154,6 +154,10 @@
// 4. Highlight the full line (default):
// "all"
"current_line_highlight": "all",
+ // Whether to highlight all occurrences of the selected text in an editor.
+ "selection_highlight": true,
+ // The debounce delay before querying highlights based on the selected text.
+ "selection_highlight_debounce": 50,
// The debounce delay before querying highlights from the language
// server based on the current cursor location.
"lsp_highlight_debounce": 75,
@@ -259,6 +263,8 @@
"git_diff": true,
// Whether to show buffer search results in the scrollbar.
"search_results": true,
+ // Whether to show selected text occurrences in the scrollbar.
+ "selected_text": true,
// Whether to show selected symbol occurrences in the scrollbar.
"selected_symbol": true,
// Which diagnostic indicators to show in the scrollbar:
@@ -283,6 +283,7 @@ impl InlayId {
enum DocumentHighlightRead {}
enum DocumentHighlightWrite {}
enum InputComposition {}
+enum SelectedTextHighlight {}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Navigated {
@@ -681,6 +682,7 @@ pub struct Editor {
next_completion_id: CompletionId,
available_code_actions: Option<(Location, Rc<[AvailableCodeAction]>)>,
code_actions_task: Option<Task<Result<()>>>,
+ selection_highlight_task: Option<Task<()>>,
document_highlights_task: Option<Task<()>>,
linked_editing_range_task: Option<Task<Option<()>>>,
linked_edit_ranges: linked_editing_ranges::LinkedEditingRanges,
@@ -1384,6 +1386,7 @@ impl Editor {
code_action_providers,
available_code_actions: Default::default(),
code_actions_task: Default::default(),
+ selection_highlight_task: Default::default(),
document_highlights_task: Default::default(),
linked_editing_range_task: Default::default(),
pending_rename: Default::default(),
@@ -2165,6 +2168,7 @@ impl Editor {
}
self.refresh_code_actions(window, cx);
self.refresh_document_highlights(cx);
+ self.refresh_selected_text_highlights(window, cx);
refresh_matching_bracket_highlights(self, window, cx);
self.update_visible_inline_completion(window, cx);
self.edit_prediction_requires_modifier_in_leading_space = true;
@@ -4722,6 +4726,93 @@ impl Editor {
None
}
+ pub fn refresh_selected_text_highlights(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+ ) {
+ self.selection_highlight_task.take();
+ if !EditorSettings::get_global(cx).selection_highlight {
+ self.clear_background_highlights::<SelectedTextHighlight>(cx);
+ return;
+ }
+ if self.selections.count() != 1 || self.selections.line_mode {
+ self.clear_background_highlights::<SelectedTextHighlight>(cx);
+ return;
+ }
+ let selection = self.selections.newest::<Point>(cx);
+ if selection.is_empty() || selection.start.row != selection.end.row {
+ self.clear_background_highlights::<SelectedTextHighlight>(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()
+ .timer(Duration::from_millis(debounce))
+ .await;
+ let Some(matches_task) = editor
+ .read_with(&mut cx, |editor, cx| {
+ let buffer = editor.buffer().read(cx).snapshot(cx);
+ cx.background_executor().spawn(async move {
+ let mut ranges = Vec::new();
+ let buffer_ranges =
+ vec![buffer.anchor_before(0)..buffer.anchor_after(buffer.len())];
+ let query = buffer.text_for_range(selection.range()).collect::<String>();
+ for range in buffer_ranges {
+ for (search_buffer, search_range, excerpt_id) in
+ buffer.range_to_buffer_ranges(range)
+ {
+ ranges.extend(
+ project::search::SearchQuery::text(
+ query.clone(),
+ false,
+ false,
+ false,
+ Default::default(),
+ Default::default(),
+ None,
+ )
+ .unwrap()
+ .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,
+ )
+ }),
+ );
+ }
+ }
+ ranges
+ })
+ })
+ .log_err()
+ else {
+ return;
+ };
+ let matches = matches_task.await;
+ editor
+ .update_in(&mut cx, |editor, _, cx| {
+ editor.clear_background_highlights::<SelectedTextHighlight>(cx);
+ if !matches.is_empty() {
+ editor.highlight_background::<SelectedTextHighlight>(
+ &matches,
+ |theme| theme.editor_document_highlight_bracket_background,
+ cx,
+ )
+ }
+ })
+ .log_err();
+ }));
+ }
+
pub fn refresh_inline_completion(
&mut self,
debounce: bool,
@@ -9,6 +9,8 @@ pub struct EditorSettings {
pub cursor_blink: bool,
pub cursor_shape: Option<CursorShape>,
pub current_line_highlight: CurrentLineHighlight,
+ pub selection_highlight: bool,
+ pub selection_highlight_debounce: u64,
pub lsp_highlight_debounce: u64,
pub hover_popover_enabled: bool,
pub hover_popover_delay: u64,
@@ -102,6 +104,7 @@ pub struct Toolbar {
pub struct Scrollbar {
pub show: ShowScrollbar,
pub git_diff: bool,
+ pub selected_text: bool,
pub selected_symbol: bool,
pub search_results: bool,
pub diagnostics: ScrollbarDiagnostics,
@@ -271,6 +274,14 @@ pub struct EditorSettingsContent {
///
/// Default: all
pub current_line_highlight: Option<CurrentLineHighlight>,
+ /// Whether to highlight all occurrences of the selected text in an editor.
+ ///
+ /// Default: true
+ pub selection_highlight: Option<bool>,
+ /// The debounce delay before querying highlights based on the selected text.
+ ///
+ /// Default: 75
+ pub selection_highlight_debounce: Option<u64>,
/// The debounce delay before querying highlights from the language
/// server based on the current cursor location.
///
@@ -404,6 +415,10 @@ pub struct ScrollbarContent {
///
/// Default: true
pub search_results: Option<bool>,
+ /// Whether to show selected text occurrences in the scrollbar.
+ ///
+ /// Default: true
+ pub selected_text: Option<bool>,
/// Whether to show selected symbol occurrences in the scrollbar.
///
/// Default: true
@@ -20,8 +20,8 @@ use crate::{
EditorSettings, EditorSnapshot, EditorStyle, ExpandExcerpts, FocusedBlock, GoToHunk,
GutterDimensions, HalfPageDown, HalfPageUp, HandleInput, HoveredCursor, InlineCompletion,
JumpData, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point, RevertSelectedHunks, RowExt,
- RowRangeExt, SelectPhase, Selection, SoftWrap, StickyHeaderExcerpt, ToPoint, ToggleFold,
- ToggleStagedSelectedDiffHunks, CURSORS_VISIBLE_FOR, FILE_HEADER_HEIGHT,
+ RowRangeExt, SelectPhase, SelectedTextHighlight, Selection, SoftWrap, StickyHeaderExcerpt,
+ ToPoint, ToggleFold, ToggleStagedSelectedDiffHunks, CURSORS_VISIBLE_FOR, FILE_HEADER_HEIGHT,
GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED, MAX_LINE_LEN, MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
};
use buffer_diff::{DiffHunkSecondaryStatus, DiffHunkStatus};
@@ -1296,6 +1296,9 @@ impl EditorElement {
// Buffer Search Results
(is_singleton && scrollbar_settings.search_results && editor.has_background_highlights::<BufferSearchHighlights>())
||
+ // Selected Text Occurrences
+ (is_singleton && scrollbar_settings.selected_text && editor.has_background_highlights::<SelectedTextHighlight>())
+ ||
// Selected Symbol Occurrences
(is_singleton && scrollbar_settings.selected_symbol && (editor.has_background_highlights::<DocumentHighlightRead>() || editor.has_background_highlights::<DocumentHighlightWrite>()))
||
@@ -5439,11 +5442,14 @@ impl EditorElement {
{
let is_search_highlights = *background_highlight_id
== TypeId::of::<BufferSearchHighlights>();
+ let is_text_highlights = *background_highlight_id
+ == TypeId::of::<SelectedTextHighlight>();
let is_symbol_occurrences = *background_highlight_id
== TypeId::of::<DocumentHighlightRead>()
|| *background_highlight_id
== TypeId::of::<DocumentHighlightWrite>();
if (is_search_highlights && scrollbar_settings.search_results)
+ || (is_text_highlights && scrollbar_settings.selected_text)
|| (is_symbol_occurrences && scrollbar_settings.selected_symbol)
{
let mut color = theme.status().info;
@@ -472,6 +472,19 @@ List of `string` values
"current_line_highlight": "all"
```
+## Selection Highlight
+
+- Description: Whether to highlight all occurrences of the selected text in an editor.
+- Setting: `selection_highlight`
+- Default: `true`
+
+## Selection Highlight Debounce
+
+- Description: The debounce delay before querying highlights based on the selected text.
+
+- Setting: `selection_highlight_debounce`
+- Default: `75`
+
## LSP Highlight Debounce
- Description: The debounce delay before querying highlights from the language server based on the current cursor location.
@@ -532,6 +545,7 @@ List of `string` values
"cursors": true,
"git_diff": true,
"search_results": true,
+ "selected_text": true,
"selected_symbol": true,
"diagnostics": "all",
"axes": {
@@ -611,6 +625,16 @@ List of `string` values
`boolean` values
+### Selected Text Indicators
+
+- Description: Whether to show selected text occurrences in the scrollbar.
+- Setting: `selected_text`
+- Default: `true`
+
+**Options**
+
+`boolean` values
+
### Selected Symbols Indicators
- Description: Whether to show selected symbol occurrences in the scrollbar.