Start adding project search listeners to workspace

co-authored-by: Piotr <piotr@zed.dev>

To be able to trigger them from search multibuffer excerpts.
This commit is contained in:
Kirill Bulatov 2024-01-17 15:11:33 +02:00
parent c6c56c35df
commit 306e4693fa
4 changed files with 129 additions and 17 deletions

View File

@ -1148,7 +1148,7 @@ impl Render for AssistantPanel {
|panel, cx| panel.toolbar.read(cx).item_of_type::<BufferSearchBar>(), |panel, cx| panel.toolbar.read(cx).item_of_type::<BufferSearchBar>(),
cx, cx,
); );
BufferSearchBar::register_inner(&mut registrar); BufferSearchBar::register(&mut registrar);
registrar.into_div() registrar.into_div()
} else { } else {
div() div()

View File

@ -496,67 +496,111 @@ impl SearchActionsRegistrar for Workspace {
}); });
} }
} }
impl BufferSearchBar { impl BufferSearchBar {
pub fn register_inner(registrar: &mut impl SearchActionsRegistrar) { pub fn register(registrar: &mut impl SearchActionsRegistrar) {
registrar.register_handler(|this, action: &ToggleCaseSensitive, cx| { registrar.register_handler(|this, action: &ToggleCaseSensitive, cx| {
if this.is_dismissed() {
cx.propagate();
return;
}
if this.supported_options().case { if this.supported_options().case {
this.toggle_case_sensitive(action, cx); this.toggle_case_sensitive(action, cx);
} }
}); });
registrar.register_handler(|this, action: &ToggleWholeWord, cx| { registrar.register_handler(|this, action: &ToggleWholeWord, cx| {
if this.is_dismissed() {
cx.propagate();
return;
}
if this.supported_options().word { if this.supported_options().word {
this.toggle_whole_word(action, cx); this.toggle_whole_word(action, cx);
} }
}); });
registrar.register_handler(|this, action: &ToggleReplace, cx| { registrar.register_handler(|this, action: &ToggleReplace, cx| {
if this.is_dismissed() {
cx.propagate();
return;
}
if this.supported_options().replacement { if this.supported_options().replacement {
this.toggle_replace(action, cx); this.toggle_replace(action, cx);
} }
}); });
registrar.register_handler(|this, _: &ActivateRegexMode, cx| { registrar.register_handler(|this, _: &ActivateRegexMode, cx| {
if this.is_dismissed() {
cx.propagate();
return;
}
if this.supported_options().regex { if this.supported_options().regex {
this.activate_search_mode(SearchMode::Regex, cx); this.activate_search_mode(SearchMode::Regex, cx);
} }
}); });
registrar.register_handler(|this, _: &ActivateTextMode, cx| { registrar.register_handler(|this, _: &ActivateTextMode, cx| {
if this.is_dismissed() {
cx.propagate();
return;
}
this.activate_search_mode(SearchMode::Text, cx); this.activate_search_mode(SearchMode::Text, cx);
}); });
registrar.register_handler(|this, action: &CycleMode, cx| { registrar.register_handler(|this, action: &CycleMode, cx| {
if this.is_dismissed() {
cx.propagate();
return;
}
if this.supported_options().regex { 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 // If regex is not supported then search has just one mode (text) - in that case there's no point in supporting
// cycling. // cycling.
this.cycle_mode(action, cx) this.cycle_mode(action, cx)
} }
}); });
registrar.register_handler(|this, action: &SelectNextMatch, cx| { registrar.register_handler(|this, action: &SelectNextMatch, cx| {
if this.is_dismissed() {
cx.propagate();
return;
}
this.select_next_match(action, cx); this.select_next_match(action, cx);
}); });
registrar.register_handler(|this, action: &SelectPrevMatch, cx| { registrar.register_handler(|this, action: &SelectPrevMatch, cx| {
if this.is_dismissed() {
cx.propagate();
return;
}
this.select_prev_match(action, cx); this.select_prev_match(action, cx);
}); });
registrar.register_handler(|this, action: &SelectAllMatches, cx| { registrar.register_handler(|this, action: &SelectAllMatches, cx| {
if this.is_dismissed() {
cx.propagate();
return;
}
this.select_all_matches(action, cx); this.select_all_matches(action, cx);
}); });
registrar.register_handler(|this, _: &editor::Cancel, cx| { registrar.register_handler(|this, _: &editor::Cancel, cx| {
if this.dismissed { if this.is_dismissed() {
cx.propagate(); cx.propagate();
} else { return;
this.dismiss(&Dismiss, cx);
} }
this.dismiss(&Dismiss, cx);
}); });
registrar.register_handler(|this, deploy, 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>) -> Self { pub fn new(cx: &mut ViewContext<Self>) -> Self {
let query_editor = cx.new_view(|cx| Editor::single_line(cx)); let query_editor = cx.new_view(|cx| Editor::single_line(cx));
cx.subscribe(&query_editor, Self::on_query_editor_event) cx.subscribe(&query_editor, Self::on_query_editor_event)

View File

@ -63,7 +63,57 @@ pub fn init(cx: &mut AppContext) {
workspace workspace
.register_action(ProjectSearchView::new_search) .register_action(ProjectSearchView::new_search)
.register_action(ProjectSearchView::deploy_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<A: Action>(
&mut workspace,
callback: fn(&mut ProjectSearchBar, &A, &mut ViewContext<ProjectSearchBar>),
) {
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::<ProjectSearchView>()) {
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::<ProjectSearchBar>() {
dbg!("$$$$$$$$$ 4");
search_bar.update(cx, move |search_bar, cx| {
search_bar.select_next_match(action, cx)
});
cx.notify();
}
})
});
});
}) })
.detach(); .detach();
} }
@ -1502,6 +1552,22 @@ impl ProjectSearchBar {
} }
} }
pub fn select_next_match(&mut self, _: &SelectNextMatch, cx: &mut ViewContext<Self>) {
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<Self>) {
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<Self>) -> Option<String> { fn new_placeholder_text(&self, cx: &mut ViewContext<Self>) -> Option<String> {
let previous_query_keystrokes = cx let previous_query_keystrokes = cx
.bindings_for_action(&PreviousHistoryQuery {}) .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( .child(
h_flex() h_flex()
.justify_between() .justify_between()

View File

@ -387,7 +387,7 @@ impl Render for TerminalPanel {
}, },
cx, cx,
); );
BufferSearchBar::register_inner(&mut registrar); BufferSearchBar::register(&mut registrar);
registrar.into_div().size_full().child(self.pane.clone()) registrar.into_div().size_full().child(self.pane.clone())
} }
} }