diff --git a/assets/themes/ayu/ayu.json b/assets/themes/ayu/ayu.json index 7c84c603bda7fd7590067ec9f566f3582ba6aefd..e2b7c3c91fca46ab0e4064719bea5c8793faaccc 100644 --- a/assets/themes/ayu/ayu.json +++ b/assets/themes/ayu/ayu.json @@ -45,6 +45,7 @@ "tab.inactive_background": "#1f2127ff", "tab.active_background": "#0d1016ff", "search.match_background": "#5ac2fe66", + "search.active_match_background": "#ea570166", "panel.background": "#1f2127ff", "panel.focused_border": "#5ac1feff", "pane.focused_border": null, @@ -436,6 +437,7 @@ "tab.inactive_background": "#ececedff", "tab.active_background": "#fcfcfcff", "search.match_background": "#3b9ee566", + "search.active_match_background": "#f88b3666", "panel.background": "#ececedff", "panel.focused_border": "#3b9ee5ff", "pane.focused_border": null, @@ -827,6 +829,7 @@ "tab.inactive_background": "#353944ff", "tab.active_background": "#242835ff", "search.match_background": "#73cffe66", + "search.active_match_background": "#fd722b66", "panel.background": "#353944ff", "panel.focused_border": null, "pane.focused_border": null, diff --git a/assets/themes/gruvbox/gruvbox.json b/assets/themes/gruvbox/gruvbox.json index a0f0a3ad637a4d212c8bf38f95f2e8424919d6bf..90973fd6c3469a1ef0e698d629376dfaaf3b5a76 100644 --- a/assets/themes/gruvbox/gruvbox.json +++ b/assets/themes/gruvbox/gruvbox.json @@ -46,6 +46,7 @@ "tab.inactive_background": "#3a3735ff", "tab.active_background": "#282828ff", "search.match_background": "#83a59866", + "search.active_match_background": "#c09f3f66", "panel.background": "#3a3735ff", "panel.focused_border": "#83a598ff", "pane.focused_border": null, @@ -452,6 +453,7 @@ "tab.inactive_background": "#393634ff", "tab.active_background": "#1d2021ff", "search.match_background": "#83a59866", + "search.active_match_background": "#c9653666", "panel.background": "#393634ff", "panel.focused_border": "#83a598ff", "pane.focused_border": null, @@ -858,6 +860,7 @@ "tab.inactive_background": "#3b3735ff", "tab.active_background": "#32302fff", "search.match_background": "#83a59866", + "search.active_match_background": "#aea85166", "panel.background": "#3b3735ff", "panel.focused_border": null, "pane.focused_border": null, @@ -1264,6 +1267,7 @@ "tab.inactive_background": "#ecddb4ff", "tab.active_background": "#fbf1c7ff", "search.match_background": "#0b667866", + "search.active_match_background": "#ba2d1166", "panel.background": "#ecddb4ff", "panel.focused_border": null, "pane.focused_border": null, @@ -1670,6 +1674,7 @@ "tab.inactive_background": "#ecddb5ff", "tab.active_background": "#f9f5d7ff", "search.match_background": "#0b667866", + "search.active_match_background": "#dc351466", "panel.background": "#ecddb5ff", "panel.focused_border": null, "pane.focused_border": null, @@ -2076,6 +2081,7 @@ "tab.inactive_background": "#ecdcb3ff", "tab.active_background": "#f2e5bcff", "search.match_background": "#0b667866", + "search.active_match_background": "#d7331466", "panel.background": "#ecdcb3ff", "panel.focused_border": null, "pane.focused_border": null, diff --git a/assets/themes/one/one.json b/assets/themes/one/one.json index d9d7a37e996053d6f7c6cb28ec7f0d3f92e3b394..c72c92471761c473bea05edc37b1f96f18b2f683 100644 --- a/assets/themes/one/one.json +++ b/assets/themes/one/one.json @@ -45,6 +45,7 @@ "tab.inactive_background": "#2f343eff", "tab.active_background": "#282c33ff", "search.match_background": "#74ade866", + "search.active_match_background": "#e8af7466", "panel.background": "#2f343eff", "panel.focused_border": null, "pane.focused_border": null, @@ -448,6 +449,7 @@ "tab.inactive_background": "#ebebecff", "tab.active_background": "#fafafaff", "search.match_background": "#5c79e266", + "search.active_match_background": "#d0a92366", "panel.background": "#ebebecff", "panel.focused_border": null, "pane.focused_border": null, diff --git a/crates/agent_ui/src/text_thread_editor.rs b/crates/agent_ui/src/text_thread_editor.rs index 6d5e226b6a5f1ae441314d45f2546a57c84ca664..161fad95e68c015f720df825b1f0ca32f5d79124 100644 --- a/crates/agent_ui/src/text_thread_editor.rs +++ b/crates/agent_ui/src/text_thread_editor.rs @@ -2622,11 +2622,13 @@ impl SearchableItem for TextThreadEditor { fn update_matches( &mut self, matches: &[Self::Match], + active_match_index: Option, window: &mut Window, cx: &mut Context, ) { - self.editor - .update(cx, |editor, cx| editor.update_matches(matches, window, cx)); + self.editor.update(cx, |editor, cx| { + editor.update_matches(matches, active_match_index, window, cx) + }); } fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context) -> String { diff --git a/crates/debugger_tools/src/dap_log.rs b/crates/debugger_tools/src/dap_log.rs index 8841a3744a4452355e2b02c9dca969cab493796e..317ce8b4c65e441f1fc4041706989532aa150204 100644 --- a/crates/debugger_tools/src/dap_log.rs +++ b/crates/debugger_tools/src/dap_log.rs @@ -1017,11 +1017,13 @@ impl SearchableItem for DapLogView { fn update_matches( &mut self, matches: &[Self::Match], + active_match_index: Option, window: &mut Window, cx: &mut Context, ) { - self.editor - .update(cx, |e, cx| e.update_matches(matches, window, cx)) + self.editor.update(cx, |e, cx| { + e.update_matches(matches, active_match_index, window, cx) + }) } fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context) -> String { diff --git a/crates/debugger_ui/src/session/running/console.rs b/crates/debugger_ui/src/session/running/console.rs index d20108b61205bacd3ea09af0ea34fabbec621c20..927a57dc8bdf956eb7f7ff63d3ea058500abf6c3 100644 --- a/crates/debugger_ui/src/session/running/console.rs +++ b/crates/debugger_ui/src/session/running/console.rs @@ -252,10 +252,11 @@ impl Console { let start_offset = range.start; let range = buffer.anchor_after(MultiBufferOffset(range.start)) ..buffer.anchor_before(MultiBufferOffset(range.end)); + let color_fn = color_fetcher(color); console.highlight_background_key::( start_offset, &[range], - color_fetcher(color), + move |_, theme| color_fn(theme), cx, ); } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index f2d6e168fc9ed47cd3c490f3449bc856f90e79fd..f90400b2b1e07b14959d5b532c5926f7c3224dbe 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -726,7 +726,10 @@ impl EditorActionId { // type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor; // type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option; -type BackgroundHighlight = (fn(&Theme) -> Hsla, Arc<[Range]>); +type BackgroundHighlight = ( + Arc Hsla + Send + Sync>, + Arc<[Range]>, +); type GutterHighlight = (fn(&App) -> Hsla, Vec>); #[derive(Default)] @@ -6610,7 +6613,7 @@ impl Editor { editor.update(cx, |editor, cx| { editor.highlight_background::( &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::( &read_ranges, - |theme| theme.colors().editor_document_highlight_read_background, + |_, theme| theme.colors().editor_document_highlight_read_background, cx, ); this.highlight_background::( &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::( &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::( &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], cx: &mut Context) { self.highlight_background::( 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( &mut self, ranges: &[Range], - color_fetcher: fn(&Theme) -> Hsla, + color_fetcher: impl Fn(&usize, &Theme) -> Hsla + Send + Sync + 'static, cx: &mut Context, ) { self.background_highlights.insert( HighlightKey::Type(TypeId::of::()), - (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], - color_fetcher: fn(&Theme) -> Hsla, + color_fetcher: impl Fn(&usize, &Theme) -> Hsla + Send + Sync + 'static, cx: &mut Context, ) { self.background_highlights.insert( HighlightKey::TypePlus(TypeId::of::(), 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, 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)) diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index d95f0f78bf8acea8703bb7780ca842f037850d64..011715804665563b9588da28bad3137120f9c4c3 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -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::( @@ -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::( &[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::( &[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::( &anchor_ranges, - |theme| theme.colors().editor_document_highlight_read_background, + |_, theme| theme.colors().editor_document_highlight_read_background, cx, ); }); diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index 0b9a25d3ee0fcb1cb67497bf51fe41ed73a3692e..caabe6e6f5ab6ae80b3ead9d72fdcbec59937ff6 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -518,7 +518,7 @@ fn show_hover( // Highlight the selected symbol using a background highlight editor.highlight_background::( &hover_highlights, - |theme| theme.colors().element_hover, // todo update theme + |_, theme| theme.colors().element_hover, // todo update theme cx, ); } diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 4e1305866ee9e4219295c02bdc519b4bc857cddf..ca8937bebe3d3578c7fe2fdec2c6252bdd395e6d 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -1487,6 +1487,7 @@ impl SearchableItem for Editor { fn update_matches( &mut self, matches: &[Range], + active_match_index: Option, _: &mut Window, cx: &mut Context, ) { @@ -1497,7 +1498,13 @@ impl SearchableItem for Editor { let updated = existing_range != Some(matches); self.highlight_background::( 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 { diff --git a/crates/language_tools/src/lsp_log_view.rs b/crates/language_tools/src/lsp_log_view.rs index 4295985b5f846cbf1ff87a1012042ee6b6608945..314dcc0b9bde998a0fec65b2847ae13641f0d011 100644 --- a/crates/language_tools/src/lsp_log_view.rs +++ b/crates/language_tools/src/lsp_log_view.rs @@ -805,11 +805,13 @@ impl SearchableItem for LspLogView { fn update_matches( &mut self, matches: &[Self::Match], + active_match_index: Option, window: &mut Window, cx: &mut Context, ) { - self.editor - .update(cx, |e, cx| e.update_matches(matches, window, cx)) + self.editor.update(cx, |e, cx| { + e.update_matches(matches, active_match_index, window, cx) + }) } fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context) -> String { diff --git a/crates/language_tools/src/syntax_tree_view.rs b/crates/language_tools/src/syntax_tree_view.rs index c06ecd21e7f2eb86b4114ec2671f38297fd5fa25..0fbcdcca5eca80a01738888266389db5a678f3e8 100644 --- a/crates/language_tools/src/syntax_tree_view.rs +++ b/crates/language_tools/src/syntax_tree_view.rs @@ -459,7 +459,7 @@ impl SyntaxTreeView { editor.clear_background_highlights::(cx); editor.highlight_background::( &[range], - |theme| { + |_, theme| { theme .colors() .editor_document_highlight_write_background diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index d17efa635074f7898ab3ea829f3418e2ddd09934..a9c26ac9bad0f524acdb47d6f09c2bd67cb8dfc6 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -1031,7 +1031,7 @@ impl BufferSearchBar { let new_match_index = searchable_item .match_index_for_direction(matches, index, direction, count, window, cx); - searchable_item.update_matches(matches, window, cx); + searchable_item.update_matches(matches, Some(new_match_index), window, cx); searchable_item.activate_match(new_match_index, matches, window, cx); } } @@ -1045,7 +1045,7 @@ impl BufferSearchBar { if matches.is_empty() { return; } - searchable_item.update_matches(matches, window, cx); + searchable_item.update_matches(matches, Some(0), window, cx); searchable_item.activate_match(0, matches, window, cx); } } @@ -1060,7 +1060,7 @@ impl BufferSearchBar { return; } let new_match_index = matches.len() - 1; - searchable_item.update_matches(matches, window, cx); + searchable_item.update_matches(matches, Some(new_match_index), window, cx); searchable_item.activate_match(new_match_index, matches, window, cx); } } @@ -1300,7 +1300,12 @@ impl BufferSearchBar { if matches.is_empty() { active_searchable_item.clear_matches(window, cx); } else { - active_searchable_item.update_matches(matches, window, cx); + active_searchable_item.update_matches( + matches, + this.active_match_index, + window, + cx, + ); } let _ = done_tx.send(()); } @@ -1335,6 +1340,18 @@ impl BufferSearchBar { }); if new_index != self.active_match_index { self.active_match_index = new_index; + if !self.dismissed { + if let Some(searchable_item) = self.active_searchable_item.as_ref() { + if let Some(matches) = self + .searchable_items_with_matches + .get(&searchable_item.downgrade()) + { + if !matches.is_empty() { + searchable_item.update_matches(matches, new_index, window, cx); + } + } + } + } cx.notify(); } } diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 2bd994754aa50ed01d4808455e40b5248bb11e19..41de3246532d6fcfe781f9c5c1d2c250f0cae93e 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -1444,6 +1444,7 @@ impl ProjectSearchView { s.select_ranges([range_to_select]) }); }); + self.highlight_matches(&match_ranges, Some(new_index), cx); } } @@ -1518,11 +1519,6 @@ impl ProjectSearchView { }); editor.scroll(Point::default(), Some(Axis::Vertical), window, cx); } - editor.highlight_background::( - &match_ranges, - |theme| theme.colors().search_match_background, - cx, - ); }); if is_new_search && self.query_editor.focus_handle(cx).is_focused(window) { self.focus_results_editor(window, cx); @@ -1535,18 +1531,41 @@ impl ProjectSearchView { fn update_match_index(&mut self, cx: &mut Context) { let results_editor = self.results_editor.read(cx); + let match_ranges = self.entity.read(cx).match_ranges.clone(); let new_index = active_match_index( Direction::Next, - &self.entity.read(cx).match_ranges, + &match_ranges, &results_editor.selections.newest_anchor().head(), &results_editor.buffer().read(cx).snapshot(cx), ); + self.highlight_matches(&match_ranges, new_index, cx); if self.active_match_index != new_index { self.active_match_index = new_index; cx.notify(); } } + fn highlight_matches( + &self, + match_ranges: &[Range], + active_index: Option, + cx: &mut Context, + ) { + self.results_editor.update(cx, |editor, cx| { + editor.highlight_background::( + match_ranges, + move |index, theme| { + if active_index == Some(*index) { + theme.colors().search_active_match_background + } else { + theme.colors().search_match_background + } + }, + cx, + ); + }); + } + pub fn has_matches(&self) -> bool { self.active_match_index.is_some() } @@ -2456,7 +2475,9 @@ pub mod tests { use pretty_assertions::assert_eq; use project::FakeFs; use serde_json::json; - use settings::{InlayHintSettingsContent, SettingsStore}; + use settings::{ + InlayHintSettingsContent, SettingsStore, ThemeColorsContent, ThemeStyleContent, + }; use util::{path, paths::PathStyle, rel_path::rel_path}; use util_macros::perf; use workspace::DeploySearch; @@ -2464,8 +2485,105 @@ pub mod tests { #[perf] #[gpui::test] async fn test_project_search(cx: &mut TestAppContext) { + fn dp(row: u32, col: u32) -> DisplayPoint { + DisplayPoint::new(DisplayRow(row), col) + } + + fn assert_active_match_index( + search_view: &WindowHandle, + cx: &mut TestAppContext, + expected_index: usize, + ) { + search_view + .update(cx, |search_view, _window, _cx| { + assert_eq!(search_view.active_match_index, Some(expected_index)); + }) + .unwrap(); + } + + fn assert_selection_range( + search_view: &WindowHandle, + cx: &mut TestAppContext, + expected_range: Range, + ) { + search_view + .update(cx, |search_view, _window, cx| { + assert_eq!( + search_view.results_editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), + [expected_range] + ); + }) + .unwrap(); + } + + fn assert_highlights( + search_view: &WindowHandle, + cx: &mut TestAppContext, + expected_highlights: Vec<(Range, &str)>, + ) { + search_view + .update(cx, |search_view, window, cx| { + let match_bg = cx.theme().colors().search_match_background; + let active_match_bg = cx.theme().colors().search_active_match_background; + let selection_bg = cx + .theme() + .colors() + .editor_document_highlight_bracket_background; + + let highlights: Vec<_> = expected_highlights + .into_iter() + .map(|(range, color_type)| { + let color = match color_type { + "active" => active_match_bg, + "match" => match_bg, + "selection" => selection_bg, + _ => panic!("Unknown color type"), + }; + (range, color) + }) + .collect(); + + assert_eq!( + search_view.results_editor.update(cx, |editor, cx| editor + .all_text_background_highlights(window, cx)), + highlights.as_slice() + ); + }) + .unwrap(); + } + + fn select_match( + search_view: &WindowHandle, + cx: &mut TestAppContext, + direction: Direction, + ) { + search_view + .update(cx, |search_view, window, cx| { + search_view.select_match(direction, window, cx); + }) + .unwrap(); + } + init_test(cx); + // Override active search match color since the fallback theme uses the same color + // for normal search match and active one, which can make this test less robust. + cx.update(|cx| { + SettingsStore::update_global(cx, |settings, cx| { + settings.update_user_settings(cx, |settings| { + settings.theme.experimental_theme_overrides = Some(ThemeStyleContent { + colors: ThemeColorsContent { + search_active_match_background: Some("#ff0000ff".to_string()), + ..Default::default() + }, + ..Default::default() + }); + }); + }); + }); + let fs = FakeFs::new(cx.background_executor.clone()); fs.insert_tree( path!("/dir"), @@ -2486,113 +2604,113 @@ pub mod tests { }); perform_search(search_view, "TWO", cx); - search_view.update(cx, |search_view, window, cx| { - assert_eq!( - search_view - .results_editor - .update(cx, |editor, cx| editor.display_text(cx)), - "\n\nconst THREE: usize = one::ONE + two::TWO;\n\n\nconst TWO: usize = one::ONE + one::ONE;" - ); - let match_background_color = cx.theme().colors().search_match_background; - let selection_background_color = cx.theme().colors().editor_document_highlight_bracket_background; - assert_eq!( - search_view - .results_editor - .update(cx, |editor, cx| editor.all_text_background_highlights(window, cx)), - &[ - ( - DisplayPoint::new(DisplayRow(2), 32)..DisplayPoint::new(DisplayRow(2), 35), - match_background_color - ), - ( - DisplayPoint::new(DisplayRow(2), 37)..DisplayPoint::new(DisplayRow(2), 40), - selection_background_color - ), - ( - DisplayPoint::new(DisplayRow(2), 37)..DisplayPoint::new(DisplayRow(2), 40), - match_background_color - ), - ( - DisplayPoint::new(DisplayRow(5), 6)..DisplayPoint::new(DisplayRow(5), 9), - match_background_color - ), - - ] - ); - assert_eq!(search_view.active_match_index, Some(0)); - assert_eq!( - search_view - .results_editor - .update(cx, |editor, cx| editor.selections.display_ranges(&editor.display_snapshot(cx))), - [DisplayPoint::new(DisplayRow(2), 32)..DisplayPoint::new(DisplayRow(2), 35)] - ); - - search_view.select_match(Direction::Next, window, cx); - }).unwrap(); + cx.run_until_parked(); search_view - .update(cx, |search_view, window, cx| { - assert_eq!(search_view.active_match_index, Some(1)); + .update(cx, |search_view, _window, cx| { assert_eq!( - search_view.results_editor.update(cx, |editor, cx| editor - .selections - .display_ranges(&editor.display_snapshot(cx))), - [DisplayPoint::new(DisplayRow(2), 37)..DisplayPoint::new(DisplayRow(2), 40)] + search_view + .results_editor + .update(cx, |editor, cx| editor.display_text(cx)), + "\n\nconst THREE: usize = one::ONE + two::TWO;\n\n\nconst TWO: usize = one::ONE + one::ONE;" ); - search_view.select_match(Direction::Next, window, cx); }) .unwrap(); - search_view - .update(cx, |search_view, window, cx| { - assert_eq!(search_view.active_match_index, Some(2)); - assert_eq!( - search_view.results_editor.update(cx, |editor, cx| editor - .selections - .display_ranges(&editor.display_snapshot(cx))), - [DisplayPoint::new(DisplayRow(5), 6)..DisplayPoint::new(DisplayRow(5), 9)] - ); - search_view.select_match(Direction::Next, window, cx); - }) - .unwrap(); + assert_active_match_index(&search_view, cx, 0); + assert_selection_range(&search_view, cx, dp(2, 32)..dp(2, 35)); + assert_highlights( + &search_view, + cx, + vec![ + (dp(2, 32)..dp(2, 35), "active"), + (dp(2, 37)..dp(2, 40), "selection"), + (dp(2, 37)..dp(2, 40), "match"), + (dp(5, 6)..dp(5, 9), "match"), + // TODO: we should be getting selection highlight here after project search + // but for some reason we are not getting it here + ], + ); + select_match(&search_view, cx, Direction::Next); + cx.run_until_parked(); - search_view - .update(cx, |search_view, window, cx| { - assert_eq!(search_view.active_match_index, Some(0)); - assert_eq!( - search_view.results_editor.update(cx, |editor, cx| editor - .selections - .display_ranges(&editor.display_snapshot(cx))), - [DisplayPoint::new(DisplayRow(2), 32)..DisplayPoint::new(DisplayRow(2), 35)] - ); - search_view.select_match(Direction::Prev, window, cx); - }) - .unwrap(); + assert_active_match_index(&search_view, cx, 1); + assert_selection_range(&search_view, cx, dp(2, 37)..dp(2, 40)); + assert_highlights( + &search_view, + cx, + vec![ + (dp(2, 32)..dp(2, 35), "selection"), + (dp(2, 32)..dp(2, 35), "match"), + (dp(2, 37)..dp(2, 40), "active"), + (dp(5, 6)..dp(5, 9), "selection"), + (dp(5, 6)..dp(5, 9), "match"), + ], + ); + select_match(&search_view, cx, Direction::Next); + cx.run_until_parked(); - search_view - .update(cx, |search_view, window, cx| { - assert_eq!(search_view.active_match_index, Some(2)); - assert_eq!( - search_view.results_editor.update(cx, |editor, cx| editor - .selections - .display_ranges(&editor.display_snapshot(cx))), - [DisplayPoint::new(DisplayRow(5), 6)..DisplayPoint::new(DisplayRow(5), 9)] - ); - search_view.select_match(Direction::Prev, window, cx); - }) - .unwrap(); + assert_active_match_index(&search_view, cx, 2); + assert_selection_range(&search_view, cx, dp(5, 6)..dp(5, 9)); + assert_highlights( + &search_view, + cx, + vec![ + (dp(2, 32)..dp(2, 35), "selection"), + (dp(2, 32)..dp(2, 35), "match"), + (dp(2, 37)..dp(2, 40), "selection"), + (dp(2, 37)..dp(2, 40), "match"), + (dp(5, 6)..dp(5, 9), "active"), + ], + ); + select_match(&search_view, cx, Direction::Next); + cx.run_until_parked(); - search_view - .update(cx, |search_view, _, cx| { - assert_eq!(search_view.active_match_index, Some(1)); - assert_eq!( - search_view.results_editor.update(cx, |editor, cx| editor - .selections - .display_ranges(&editor.display_snapshot(cx))), - [DisplayPoint::new(DisplayRow(2), 37)..DisplayPoint::new(DisplayRow(2), 40)] - ); - }) - .unwrap(); + assert_active_match_index(&search_view, cx, 0); + assert_selection_range(&search_view, cx, dp(2, 32)..dp(2, 35)); + assert_highlights( + &search_view, + cx, + vec![ + (dp(2, 32)..dp(2, 35), "active"), + (dp(2, 37)..dp(2, 40), "selection"), + (dp(2, 37)..dp(2, 40), "match"), + (dp(5, 6)..dp(5, 9), "selection"), + (dp(5, 6)..dp(5, 9), "match"), + ], + ); + select_match(&search_view, cx, Direction::Prev); + cx.run_until_parked(); + + assert_active_match_index(&search_view, cx, 2); + assert_selection_range(&search_view, cx, dp(5, 6)..dp(5, 9)); + assert_highlights( + &search_view, + cx, + vec![ + (dp(2, 32)..dp(2, 35), "selection"), + (dp(2, 32)..dp(2, 35), "match"), + (dp(2, 37)..dp(2, 40), "selection"), + (dp(2, 37)..dp(2, 40), "match"), + (dp(5, 6)..dp(5, 9), "active"), + ], + ); + select_match(&search_view, cx, Direction::Prev); + cx.run_until_parked(); + + assert_active_match_index(&search_view, cx, 1); + assert_selection_range(&search_view, cx, dp(2, 37)..dp(2, 40)); + assert_highlights( + &search_view, + cx, + vec![ + (dp(2, 32)..dp(2, 35), "selection"), + (dp(2, 32)..dp(2, 35), "match"), + (dp(2, 37)..dp(2, 40), "active"), + (dp(5, 6)..dp(5, 9), "selection"), + (dp(5, 6)..dp(5, 9), "match"), + ], + ); } #[perf] diff --git a/crates/settings/src/settings_content/theme.rs b/crates/settings/src/settings_content/theme.rs index 49942634af3da9f7009ba02ca6cbf79c30ddaa13..94045b75a1112af64ed56de318d4e27c392a230e 100644 --- a/crates/settings/src/settings_content/theme.rs +++ b/crates/settings/src/settings_content/theme.rs @@ -570,6 +570,9 @@ pub struct ThemeColorsContent { #[serde(rename = "search.match_background")] pub search_match_background: Option, + #[serde(rename = "search.active_match_background")] + pub search_active_match_background: Option, + #[serde(rename = "panel.background")] pub panel_background: Option, diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 2a5213ce7ebc3326c7f4a0b5a8291e098e65cd78..4d567d902ff4f9271a0bdcf6a4db94d0e3a34ec6 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -1434,6 +1434,7 @@ impl SearchableItem for TerminalView { fn update_matches( &mut self, matches: &[Self::Match], + _active_match_index: Option, _window: &mut Window, cx: &mut Context, ) { diff --git a/crates/theme/src/default_colors.rs b/crates/theme/src/default_colors.rs index 50da8c72b63443f2c70df59ccb9f5f5caf777ca8..82be2896c67f155ac61de1ca6afb058adbf5ea9c 100644 --- a/crates/theme/src/default_colors.rs +++ b/crates/theme/src/default_colors.rs @@ -91,6 +91,7 @@ impl ThemeColors { tab_inactive_background: neutral().light().step_2(), tab_active_background: neutral().light().step_1(), search_match_background: neutral().light().step_5(), + search_active_match_background: neutral().light().step_7(), panel_background: neutral().light().step_2(), panel_focused_border: blue().light().step_10(), panel_indent_guide: neutral().light_alpha().step_5(), @@ -228,6 +229,7 @@ impl ThemeColors { tab_inactive_background: neutral().dark().step_2(), tab_active_background: neutral().dark().step_1(), search_match_background: neutral().dark().step_5(), + search_active_match_background: neutral().dark().step_3(), panel_background: neutral().dark().step_2(), panel_focused_border: blue().dark().step_8(), panel_indent_guide: neutral().dark_alpha().step_4(), diff --git a/crates/theme/src/fallback_themes.rs b/crates/theme/src/fallback_themes.rs index 2351ed6bcbd2297ebb5a173d17c095d92bb27c20..6bfcb1c86811136388eb5a557458f88c65d0ac09 100644 --- a/crates/theme/src/fallback_themes.rs +++ b/crates/theme/src/fallback_themes.rs @@ -152,6 +152,7 @@ pub(crate) fn zed_default_dark() -> Theme { tab_inactive_background: bg, tab_active_background: editor, search_match_background: bg, + search_active_match_background: bg, editor_background: editor, editor_gutter_background: editor, diff --git a/crates/theme/src/schema.rs b/crates/theme/src/schema.rs index 9c9cfbffef681890a802d21b8bcff85d358a64b8..f52b2cf0e50bc5d8b26de9457432aba9218a17b9 100644 --- a/crates/theme/src/schema.rs +++ b/crates/theme/src/schema.rs @@ -287,6 +287,15 @@ pub fn theme_colors_refinement( .panel_background .as_ref() .and_then(|color| try_parse_color(color).ok()); + let search_match_background = this + .search_match_background + .as_ref() + .and_then(|color| try_parse_color(color).ok()); + let search_active_match_background = this + .search_active_match_background + .as_ref() + .and_then(|color| try_parse_color(color).ok()) + .or(search_match_background); ThemeColorsRefinement { border, border_variant: this @@ -442,10 +451,8 @@ pub fn theme_colors_refinement( .tab_active_background .as_ref() .and_then(|color| try_parse_color(color).ok()), - search_match_background: this - .search_match_background - .as_ref() - .and_then(|color| try_parse_color(color).ok()), + search_match_background: search_match_background, + search_active_match_background: search_active_match_background, panel_background, panel_focused_border: this .panel_focused_border diff --git a/crates/theme/src/styles/colors.rs b/crates/theme/src/styles/colors.rs index c6766ca955700e2b7c3cd0e86ab16535fca8d852..905f2245e03ad7a8ce7a4eb8be6799e5ded379c4 100644 --- a/crates/theme/src/styles/colors.rs +++ b/crates/theme/src/styles/colors.rs @@ -128,6 +128,7 @@ pub struct ThemeColors { pub tab_inactive_background: Hsla, pub tab_active_background: Hsla, pub search_match_background: Hsla, + pub search_active_match_background: Hsla, pub panel_background: Hsla, pub panel_focused_border: Hsla, pub panel_indent_guide: Hsla, @@ -352,6 +353,7 @@ pub enum ThemeColorField { TabInactiveBackground, TabActiveBackground, SearchMatchBackground, + SearchActiveMatchBackground, PanelBackground, PanelFocusedBorder, PanelIndentGuide, @@ -467,6 +469,7 @@ impl ThemeColors { ThemeColorField::TabInactiveBackground => self.tab_inactive_background, ThemeColorField::TabActiveBackground => self.tab_active_background, ThemeColorField::SearchMatchBackground => self.search_match_background, + ThemeColorField::SearchActiveMatchBackground => self.search_active_match_background, ThemeColorField::PanelBackground => self.panel_background, ThemeColorField::PanelFocusedBorder => self.panel_focused_border, ThemeColorField::PanelIndentGuide => self.panel_indent_guide, diff --git a/crates/vim/src/normal/yank.rs b/crates/vim/src/normal/yank.rs index 71ed0d44384a5ed8644f486aa16cdd704e9ce944..81350d780a507a6e1d2502cf0f05115dc19abcdf 100644 --- a/crates/vim/src/normal/yank.rs +++ b/crates/vim/src/normal/yank.rs @@ -227,7 +227,7 @@ impl Vim { editor.highlight_background::( &ranges_to_highlight, - |colors| colors.colors().editor_document_highlight_read_background, + |_, colors| colors.colors().editor_document_highlight_read_background, cx, ); cx.spawn(async move |this, cx| { diff --git a/crates/vim/src/replace.rs b/crates/vim/src/replace.rs index 93c30141daeac21805e8ea1aab610988a09a9635..63d452f84bfd5ee1cea8970698962169dc8fe94a 100644 --- a/crates/vim/src/replace.rs +++ b/crates/vim/src/replace.rs @@ -273,7 +273,7 @@ impl Vim { let ranges = [new_range]; editor.highlight_background::( &ranges, - |theme| theme.colors().editor_document_highlight_read_background, + |_, theme| theme.colors().editor_document_highlight_read_background, cx, ); } diff --git a/crates/workspace/src/searchable.rs b/crates/workspace/src/searchable.rs index 64dad0345fa323eb724b6b51656b841c8d433688..badfe7d2437424c1ce18a1afde19507e7d6e1d3b 100644 --- a/crates/workspace/src/searchable.rs +++ b/crates/workspace/src/searchable.rs @@ -96,6 +96,7 @@ pub trait SearchableItem: Item + EventEmitter { fn update_matches( &mut self, matches: &[Self::Match], + active_match_index: Option, window: &mut Window, cx: &mut Context, ); @@ -179,7 +180,13 @@ pub trait SearchableItemHandle: ItemHandle { handler: Box, ) -> Subscription; fn clear_matches(&self, window: &mut Window, cx: &mut App); - fn update_matches(&self, matches: &AnyVec, window: &mut Window, cx: &mut App); + fn update_matches( + &self, + matches: &AnyVec, + active_match_index: Option, + window: &mut Window, + cx: &mut App, + ); fn query_suggestion(&self, window: &mut Window, cx: &mut App) -> String; fn activate_match( &self, @@ -264,10 +271,16 @@ impl SearchableItemHandle for Entity { fn clear_matches(&self, window: &mut Window, cx: &mut App) { self.update(cx, |this, cx| this.clear_matches(window, cx)); } - fn update_matches(&self, matches: &AnyVec, window: &mut Window, cx: &mut App) { + fn update_matches( + &self, + matches: &AnyVec, + active_match_index: Option, + window: &mut Window, + cx: &mut App, + ) { let matches = matches.downcast_ref().unwrap(); self.update(cx, |this, cx| { - this.update_matches(matches.as_slice(), window, cx) + this.update_matches(matches.as_slice(), active_match_index, window, cx) }); } fn query_suggestion(&self, window: &mut Window, cx: &mut App) -> String {