From 306e4693fad8355c2e5d83f516de70e86449aded Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 17 Jan 2024 15:11:33 +0200 Subject: [PATCH] Start adding project search listeners to workspace co-authored-by: Piotr To be able to trigger them from search multibuffer excerpts. --- crates/assistant/src/assistant_panel.rs | 2 +- crates/search/src/buffer_search.rs | 72 +++++++++++++++++----- crates/search/src/project_search.rs | 70 ++++++++++++++++++++- crates/terminal_view/src/terminal_panel.rs | 2 +- 4 files changed, 129 insertions(+), 17 deletions(-) diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index df3dc3754f66aff8d83a6fcd3b92edd38c7c4e45..5a8376554e9c66db347dc7012e45208a6ab5f157 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -1148,7 +1148,7 @@ impl Render for AssistantPanel { |panel, cx| panel.toolbar.read(cx).item_of_type::(), cx, ); - BufferSearchBar::register_inner(&mut registrar); + BufferSearchBar::register(&mut registrar); registrar.into_div() } else { div() diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index e217a7ab73cd2fd1aaa540f1b56cf13b7ec1c84b..4c6d9a5708e3f2965a223a26a979258822ab446e 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -496,67 +496,111 @@ impl SearchActionsRegistrar for Workspace { }); } } + impl BufferSearchBar { - pub fn register_inner(registrar: &mut impl SearchActionsRegistrar) { + pub fn register(registrar: &mut impl SearchActionsRegistrar) { registrar.register_handler(|this, action: &ToggleCaseSensitive, cx| { + if this.is_dismissed() { + cx.propagate(); + return; + } + if this.supported_options().case { this.toggle_case_sensitive(action, cx); } }); - registrar.register_handler(|this, action: &ToggleWholeWord, cx| { + if this.is_dismissed() { + cx.propagate(); + return; + } + if this.supported_options().word { this.toggle_whole_word(action, cx); } }); - registrar.register_handler(|this, action: &ToggleReplace, cx| { + if this.is_dismissed() { + cx.propagate(); + return; + } + if this.supported_options().replacement { this.toggle_replace(action, cx); } }); - registrar.register_handler(|this, _: &ActivateRegexMode, cx| { + if this.is_dismissed() { + cx.propagate(); + return; + } + if this.supported_options().regex { this.activate_search_mode(SearchMode::Regex, cx); } }); - registrar.register_handler(|this, _: &ActivateTextMode, cx| { + if this.is_dismissed() { + cx.propagate(); + return; + } + this.activate_search_mode(SearchMode::Text, cx); }); - registrar.register_handler(|this, action: &CycleMode, cx| { + if this.is_dismissed() { + cx.propagate(); + return; + } + if this.supported_options().regex { // If regex is not supported then search has just one mode (text) - in that case there's no point in supporting // cycling. this.cycle_mode(action, cx) } }); - registrar.register_handler(|this, action: &SelectNextMatch, cx| { + if this.is_dismissed() { + cx.propagate(); + return; + } + this.select_next_match(action, cx); }); registrar.register_handler(|this, action: &SelectPrevMatch, cx| { + if this.is_dismissed() { + cx.propagate(); + return; + } + this.select_prev_match(action, cx); }); registrar.register_handler(|this, action: &SelectAllMatches, cx| { + if this.is_dismissed() { + cx.propagate(); + return; + } + this.select_all_matches(action, cx); }); registrar.register_handler(|this, _: &editor::Cancel, cx| { - if this.dismissed { + if this.is_dismissed() { cx.propagate(); - } else { - this.dismiss(&Dismiss, cx); + return; } + + this.dismiss(&Dismiss, cx); }); registrar.register_handler(|this, deploy, cx| { - this.deploy(deploy, cx); + if this.is_dismissed() { + this.deploy(deploy, cx); + return; + } + + cx.propagate(); }) } - fn register(workspace: &mut Workspace) { - Self::register_inner(workspace); - } + pub fn new(cx: &mut ViewContext) -> Self { let query_editor = cx.new_view(|cx| Editor::single_line(cx)); cx.subscribe(&query_editor, Self::on_query_editor_event) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 49eb24ce9ee9e267dc921b6ddb8eb10e92c83c97..30c29a0c089c067d1482074a7940892b3497929d 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -63,7 +63,57 @@ pub fn init(cx: &mut AppContext) { workspace .register_action(ProjectSearchView::new_search) .register_action(ProjectSearchView::deploy_search) - .register_action(ProjectSearchBar::search_in_new); + .register_action(ProjectSearchBar::search_in_new) + // TODO kb register these too, consider having the methods for &Workspace for that, as above + // ToggleCaseSensitive + // ToggleWholeWord + // ToggleReplace + // ActivateRegexMode + // SelectPrevMatch + // ActivateTextMode + // ActivateSemanticMode + // CycleMode + // SelectNextMatch (see a proto below) + /* + // Have a generic method similar to the registrar has: + fn register_workspace_action( + &mut workspace, + callback: fn(&mut ProjectSearchBar, &A, &mut ViewContext), + ) { + workspace.register_action(move |workspace, action: &A, cx| { + if workspace.has_active_modal(cx) { + cx.propagate(); + return; + } + if let Some(search_bar) = workspace.active_item(cx).and_then(|item| item.downcast::()) { + search_bar.update(cx, move |this, cx| callback(this, action, cx)); + cx.notify(); + } + }); + } + */ + .register_action(move |workspace, action: &SelectNextMatch, cx| { + dbg!("@@@@@@@@@1"); + if workspace.has_active_modal(cx) { + cx.propagate(); + return; + } + + dbg!("????? 2"); + let pane = workspace.active_pane(); + pane.update(cx, move |this, cx| { + this.toolbar().update(cx, move |this, cx| { + dbg!("@@@@@@@@@ 3"); + if let Some(search_bar) = this.item_of_type::() { + dbg!("$$$$$$$$$ 4"); + search_bar.update(cx, move |search_bar, cx| { + search_bar.select_next_match(action, cx) + }); + cx.notify(); + } + }) + }); + }); }) .detach(); } @@ -1502,6 +1552,22 @@ impl ProjectSearchBar { } } + pub fn select_next_match(&mut self, _: &SelectNextMatch, cx: &mut ViewContext) { + if let Some(search) = self.active_project_search.as_ref() { + search.update(cx, |this, cx| { + this.select_match(Direction::Next, cx); + }) + } + } + + fn select_prev_match(&mut self, _: &SelectPrevMatch, cx: &mut ViewContext) { + if let Some(search) = self.active_project_search.as_ref() { + search.update(cx, |this, cx| { + this.select_match(Direction::Prev, cx); + }) + } + } + fn new_placeholder_text(&self, cx: &mut ViewContext) -> Option { let previous_query_keystrokes = cx .bindings_for_action(&PreviousHistoryQuery {}) @@ -1870,6 +1936,8 @@ impl Render for ProjectSearchBar { })) }) }) + .on_action(cx.listener(Self::select_next_match)) + .on_action(cx.listener(Self::select_prev_match)) .child( h_flex() .justify_between() diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index 8954e70e8fc18d3d78775ba4eb56b11ec251c0de..7a988851d8a34b8533631e1f74dfcb5d73c45ed1 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -387,7 +387,7 @@ impl Render for TerminalPanel { }, cx, ); - BufferSearchBar::register_inner(&mut registrar); + BufferSearchBar::register(&mut registrar); registrar.into_div().size_full().child(self.pane.clone()) } }