mac: Delay initial find pasteboard search until ⌘G or ⌘F (#45605)
Follow up to https://github.com/zed-industries/zed/pull/45311. Instead of searching for the string in the find pasteboard as soon as the pane is focused, we will now wait until the search bar is either deployed or `Select{Next|Prev}Match` is triggered. Release Notes: - N/A
This commit is contained in:
@@ -4,6 +4,7 @@ use crate::{
|
||||
FocusSearch, NextHistoryQuery, PreviousHistoryQuery, ReplaceAll, ReplaceNext, SearchOption,
|
||||
SearchOptions, SearchSource, SelectAllMatches, SelectNextMatch, SelectPreviousMatch,
|
||||
ToggleCaseSensitive, ToggleRegex, ToggleReplace, ToggleSelection, ToggleWholeWord,
|
||||
buffer_search::registrar::WithResultsOrExternalQuery,
|
||||
search_bar::{ActionButtonState, input_base_styles, render_action_button, render_text_input},
|
||||
};
|
||||
use any_vec::AnyVec;
|
||||
@@ -43,7 +44,7 @@ use workspace::{
|
||||
};
|
||||
|
||||
pub use registrar::DivRegistrar;
|
||||
use registrar::{ForDeployed, ForDismissed, SearchActionsRegistrar, WithResults};
|
||||
use registrar::{ForDeployed, ForDismissed, SearchActionsRegistrar};
|
||||
|
||||
const MAX_BUFFER_SEARCH_HISTORY_SIZE: usize = 50;
|
||||
|
||||
@@ -110,6 +111,8 @@ pub struct BufferSearchBar {
|
||||
active_searchable_item_subscriptions: Option<[Subscription; 2]>,
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
active_searchable_item_subscriptions: Option<Subscription>,
|
||||
#[cfg(target_os = "macos")]
|
||||
pending_external_query: Option<(String, SearchOptions)>,
|
||||
active_search: Option<Arc<SearchQuery>>,
|
||||
searchable_items_with_matches: HashMap<Box<dyn WeakSearchableItemHandle>, AnyVec<dyn Send>>,
|
||||
pending_search: Option<Task<()>>,
|
||||
@@ -510,24 +513,27 @@ impl ToolbarItemView for BufferSearchBar {
|
||||
}
|
||||
|
||||
cx.defer_in(window, |this, window, cx| {
|
||||
if let Some(item) = cx.read_from_find_pasteboard()
|
||||
&& let Some(text) = item.text()
|
||||
{
|
||||
if this.query(cx) != text {
|
||||
let search_options = item
|
||||
.metadata()
|
||||
.and_then(|m| m.parse().ok())
|
||||
.and_then(SearchOptions::from_bits)
|
||||
.unwrap_or(this.search_options);
|
||||
let Some(item) = cx.read_from_find_pasteboard() else {
|
||||
return;
|
||||
};
|
||||
let Some(text) = item.text() else {
|
||||
return;
|
||||
};
|
||||
|
||||
drop(this.search(
|
||||
&text,
|
||||
Some(search_options),
|
||||
true,
|
||||
window,
|
||||
cx,
|
||||
));
|
||||
}
|
||||
if this.query(cx) == text {
|
||||
return;
|
||||
}
|
||||
|
||||
let search_options = item
|
||||
.metadata()
|
||||
.and_then(|m| m.parse().ok())
|
||||
.and_then(SearchOptions::from_bits)
|
||||
.unwrap_or(this.search_options);
|
||||
|
||||
if this.dismissed {
|
||||
this.pending_external_query = Some((text, search_options));
|
||||
} else {
|
||||
drop(this.search(&text, Some(search_options), true, window, cx));
|
||||
}
|
||||
});
|
||||
}),
|
||||
@@ -594,14 +600,16 @@ impl BufferSearchBar {
|
||||
cx.propagate();
|
||||
}
|
||||
}));
|
||||
registrar.register_handler(WithResults(|this, action: &SelectNextMatch, window, cx| {
|
||||
if this.supported_options(cx).find_in_results {
|
||||
cx.propagate();
|
||||
} else {
|
||||
this.select_next_match(action, window, cx);
|
||||
}
|
||||
}));
|
||||
registrar.register_handler(WithResults(
|
||||
registrar.register_handler(WithResultsOrExternalQuery(
|
||||
|this, action: &SelectNextMatch, window, cx| {
|
||||
if this.supported_options(cx).find_in_results {
|
||||
cx.propagate();
|
||||
} else {
|
||||
this.select_next_match(action, window, cx);
|
||||
}
|
||||
},
|
||||
));
|
||||
registrar.register_handler(WithResultsOrExternalQuery(
|
||||
|this, action: &SelectPreviousMatch, window, cx| {
|
||||
if this.supported_options(cx).find_in_results {
|
||||
cx.propagate();
|
||||
@@ -610,7 +618,7 @@ impl BufferSearchBar {
|
||||
}
|
||||
},
|
||||
));
|
||||
registrar.register_handler(WithResults(
|
||||
registrar.register_handler(WithResultsOrExternalQuery(
|
||||
|this, action: &SelectAllMatches, window, cx| {
|
||||
if this.supported_options(cx).find_in_results {
|
||||
cx.propagate();
|
||||
@@ -707,6 +715,8 @@ impl BufferSearchBar {
|
||||
replacement_editor_focused: false,
|
||||
active_searchable_item: None,
|
||||
active_searchable_item_subscriptions: None,
|
||||
#[cfg(target_os = "macos")]
|
||||
pending_external_query: None,
|
||||
active_match_index: None,
|
||||
searchable_items_with_matches: Default::default(),
|
||||
default_options: search_options,
|
||||
@@ -852,11 +862,20 @@ impl BufferSearchBar {
|
||||
self.search(&suggestion, Some(self.default_options), true, window, cx)
|
||||
});
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let search = search.or_else(|| {
|
||||
self.pending_external_query
|
||||
.take()
|
||||
.map(|(query, options)| self.search(&query, Some(options), true, window, cx))
|
||||
});
|
||||
|
||||
if let Some(search) = search {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if search.await.is_ok() {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.activate_current_match(window, cx)
|
||||
if !this.dismissed {
|
||||
this.activate_current_match(window, cx)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -1071,6 +1090,22 @@ impl BufferSearchBar {
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
#[cfg(target_os = "macos")]
|
||||
if let Some((query, options)) = self.pending_external_query.take() {
|
||||
let search_rx = self.search(&query, Some(options), true, window, cx);
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if search_rx.await.is_ok() {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.activate_current_match(window, cx);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(index) = self.active_match_index
|
||||
&& let Some(searchable_item) = self.active_searchable_item.as_ref()
|
||||
&& let Some(matches) = self
|
||||
@@ -1271,6 +1306,8 @@ impl BufferSearchBar {
|
||||
let (done_tx, done_rx) = oneshot::channel();
|
||||
let query = self.query(cx);
|
||||
self.pending_search.take();
|
||||
#[cfg(target_os = "macos")]
|
||||
self.pending_external_query.take();
|
||||
|
||||
if let Some(active_searchable_item) = self.active_searchable_item.as_ref() {
|
||||
self.query_error = None;
|
||||
@@ -1367,8 +1404,8 @@ impl BufferSearchBar {
|
||||
cx,
|
||||
);
|
||||
}
|
||||
let _ = done_tx.send(());
|
||||
}
|
||||
let _ = done_tx.send(());
|
||||
cx.notify();
|
||||
}
|
||||
})
|
||||
|
||||
@@ -149,16 +149,16 @@ impl<A: Action> ActionExecutor<A> for ForDeployed<A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Run an action when the search bar has any matches, regardless of whether it
|
||||
/// is visible or not.
|
||||
pub struct WithResults<A>(pub(super) SearchBarActionCallback<A>);
|
||||
impl<A> Clone for WithResults<A> {
|
||||
/// Run an action when the search bar has any matches or a pending external query,
|
||||
/// regardless of whether it is visible or not.
|
||||
pub struct WithResultsOrExternalQuery<A>(pub(super) SearchBarActionCallback<A>);
|
||||
impl<A> Clone for WithResultsOrExternalQuery<A> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Action> ActionExecutor<A> for WithResults<A> {
|
||||
impl<A: Action> ActionExecutor<A> for WithResultsOrExternalQuery<A> {
|
||||
fn execute(
|
||||
&self,
|
||||
search_bar: &mut BufferSearchBar,
|
||||
@@ -166,7 +166,13 @@ impl<A: Action> ActionExecutor<A> for WithResults<A> {
|
||||
window: &mut Window,
|
||||
cx: &mut Context<BufferSearchBar>,
|
||||
) -> DidHandleAction {
|
||||
if search_bar.active_match_index.is_some() {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let has_external_query = false;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let has_external_query = search_bar.pending_external_query.is_some();
|
||||
|
||||
if has_external_query || search_bar.active_match_index.is_some() {
|
||||
self.0(search_bar, action, window, cx);
|
||||
true
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user