Merge branch 'main' into channel-guests

This commit is contained in:
Conrad Irwin
2024-01-05 10:05:59 -07:00
79 changed files with 3501 additions and 3265 deletions
+87 -41
View File
@@ -223,6 +223,7 @@ impl Render for BufferSearchBar {
.gap_2()
.border_1()
.border_color(editor_border)
.min_w(rems(384. / 16.))
.rounded_lg()
.child(IconElement::new(Icon::MagnifyingGlass))
.child(self.render_text_input(&self.query_editor, cx))
@@ -422,89 +423,134 @@ impl ToolbarItemView for BufferSearchBar {
}
}
impl BufferSearchBar {
fn register(workspace: &mut Workspace) {
workspace.register_action(move |workspace, deploy: &Deploy, cx| {
let pane = workspace.active_pane();
/// Registrar inverts the dependency between search and it's downstream user, allowing said downstream user to register search action without knowing exactly what those actions are.
pub trait SearchActionsRegistrar {
fn register_handler<A: Action>(
&mut self,
callback: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
);
}
pane.update(cx, |this, cx| {
this.toolbar().update(cx, |this, cx| {
type GetSearchBar<T> =
for<'a, 'b> fn(&'a T, &'a mut ViewContext<'b, T>) -> Option<View<BufferSearchBar>>;
/// Registers search actions on a div that can be taken out.
pub struct DivRegistrar<'a, 'b, T: 'static> {
div: Option<Div>,
cx: &'a mut ViewContext<'b, T>,
search_getter: GetSearchBar<T>,
}
impl<'a, 'b, T: 'static> DivRegistrar<'a, 'b, T> {
pub fn new(search_getter: GetSearchBar<T>, cx: &'a mut ViewContext<'b, T>) -> Self {
Self {
div: Some(div()),
cx,
search_getter,
}
}
pub fn into_div(self) -> Div {
// This option is always Some; it's an option in the first place because we want to call methods
// on div that require ownership.
self.div.unwrap()
}
}
impl<T: 'static> SearchActionsRegistrar for DivRegistrar<'_, '_, T> {
fn register_handler<A: gpui::Action>(
&mut self,
callback: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
) {
let getter = self.search_getter;
self.div = self.div.take().map(|div| {
div.on_action(self.cx.listener(move |this, action, cx| {
(getter)(this, cx)
.clone()
.map(|search_bar| search_bar.update(cx, |this, cx| callback(this, action, cx)));
}))
});
}
}
/// Register actions for an active pane.
impl SearchActionsRegistrar for Workspace {
fn register_handler<A: Action>(
&mut self,
callback: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
) {
self.register_action(move |workspace, action: &A, cx| {
let pane = workspace.active_pane();
pane.update(cx, move |this, cx| {
this.toolbar().update(cx, move |this, cx| {
if let Some(search_bar) = this.item_of_type::<BufferSearchBar>() {
search_bar.update(cx, |this, cx| {
this.deploy(deploy, cx);
});
return;
search_bar.update(cx, move |this, cx| callback(this, action, cx));
cx.notify();
}
let view = cx.new_view(|cx| BufferSearchBar::new(cx));
this.add_item(view.clone(), cx);
view.update(cx, |this, cx| this.deploy(deploy, cx));
cx.notify();
})
});
});
fn register_action<A: Action>(
workspace: &mut Workspace,
update: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
) {
workspace.register_action(move |workspace, action: &A, cx| {
let pane = workspace.active_pane();
pane.update(cx, move |this, cx| {
this.toolbar().update(cx, move |this, cx| {
if let Some(search_bar) = this.item_of_type::<BufferSearchBar>() {
search_bar.update(cx, move |this, cx| update(this, action, cx));
cx.notify();
}
})
});
});
}
register_action(workspace, |this, action: &ToggleCaseSensitive, cx| {
}
}
impl BufferSearchBar {
pub fn register_inner(registrar: &mut impl SearchActionsRegistrar) {
registrar.register_handler(|this, action: &ToggleCaseSensitive, cx| {
if this.supported_options().case {
this.toggle_case_sensitive(action, cx);
}
});
register_action(workspace, |this, action: &ToggleWholeWord, cx| {
registrar.register_handler(|this, action: &ToggleWholeWord, cx| {
if this.supported_options().word {
this.toggle_whole_word(action, cx);
}
});
register_action(workspace, |this, action: &ToggleReplace, cx| {
registrar.register_handler(|this, action: &ToggleReplace, cx| {
if this.supported_options().replacement {
this.toggle_replace(action, cx);
}
});
register_action(workspace, |this, _: &ActivateRegexMode, cx| {
registrar.register_handler(|this, _: &ActivateRegexMode, cx| {
if this.supported_options().regex {
this.activate_search_mode(SearchMode::Regex, cx);
}
});
register_action(workspace, |this, _: &ActivateTextMode, cx| {
registrar.register_handler(|this, _: &ActivateTextMode, cx| {
this.activate_search_mode(SearchMode::Text, cx);
});
register_action(workspace, |this, action: &CycleMode, cx| {
registrar.register_handler(|this, action: &CycleMode, cx| {
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)
}
});
register_action(workspace, |this, action: &SelectNextMatch, cx| {
registrar.register_handler(|this, action: &SelectNextMatch, cx| {
this.select_next_match(action, cx);
});
register_action(workspace, |this, action: &SelectPrevMatch, cx| {
registrar.register_handler(|this, action: &SelectPrevMatch, cx| {
this.select_prev_match(action, cx);
});
register_action(workspace, |this, action: &SelectAllMatches, cx| {
registrar.register_handler(|this, action: &SelectAllMatches, cx| {
this.select_all_matches(action, cx);
});
register_action(workspace, |this, _: &editor::Cancel, cx| {
registrar.register_handler(|this, _: &editor::Cancel, cx| {
if !this.dismissed {
this.dismiss(&Dismiss, cx);
return;
}
cx.propagate();
});
registrar.register_handler(|this, deploy, cx| {
this.deploy(deploy, cx);
})
}
fn register(workspace: &mut Workspace) {
Self::register_inner(workspace);
}
pub fn new(cx: &mut ViewContext<Self>) -> Self {
let query_editor = cx.new_view(|cx| Editor::single_line(cx));