Fix cmd-e on macOS to behave more like it should (#54451)

Closes #50578

Release Notes:

- Fixed cmd-e on macOS to work when `seed_search_query_from_cursor` has
been changed
This commit is contained in:
Conrad Irwin authored and GitHub committed 2026-04-21 19:54:02 +00:00
1 parent 38ff6b0b53
commit 4f6eeb0718
13 files changed
+101 -56

No files matched your search

+1 -1
View File
@@ -171,7 +171,7 @@
"cmd-f": "buffer_search::Deploy",
"cmd-alt-f": "buffer_search::DeployReplace",
"cmd-alt-l": ["buffer_search::Deploy", { "selection_search_enabled": true }],
"cmd-e": ["buffer_search::Deploy", { "focus": false }],
"cmd-e": "buffer_search::UseSelectionForFind",
"cmd->": "agent::AddSelectionToThread",
"cmd-alt-e": "editor::SelectEnclosingSymbol",
"alt-enter": "editor::OpenSelectionsInMultibuffer",
+7 -2
View File
@@ -1028,9 +1028,14 @@ impl SearchableItem for DapLogView {
})
}
fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context<Self>) -> String {
fn query_suggestion(
&mut self,
ignore_settings: bool,
window: &mut Window,
cx: &mut Context<Self>,
) -> String {
self.editor
.update(cx, |e, cx| e.query_suggestion(window, cx))
.update(cx, |e, cx| e.query_suggestion(ignore_settings, window, cx))
}
fn activate_match(
+11 -2
View File
@@ -1660,8 +1660,17 @@ impl SearchableItem for Editor {
}
}
fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context<Self>) -> String {
let setting = EditorSettings::get_global(cx).seed_search_query_from_cursor;
fn query_suggestion(
&mut self,
ignore_settings: bool,
window: &mut Window,
cx: &mut Context<Self>,
) -> String {
let setting = if ignore_settings {
SeedQuerySetting::Always
} else {
EditorSettings::get_global(cx).seed_search_query_from_cursor
};
let snapshot = self.snapshot(window, cx);
let selection = self.selections.newest_adjusted(&snapshot.display_snapshot);
let buffer_snapshot = snapshot.buffer_snapshot();
+9 -3
View File
@@ -1901,9 +1901,15 @@ impl SearchableItem for SplittableEditor {
}
}
fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context<Self>) -> String {
self.focused_editor()
.update(cx, |editor, cx| editor.query_suggestion(window, cx))
fn query_suggestion(
&mut self,
ignore_settings: bool,
window: &mut Window,
cx: &mut Context<Self>,
) -> String {
self.focused_editor().update(cx, |editor, cx| {
editor.query_suggestion(ignore_settings, window, cx)
})
}
fn activate_match(
+7 -2
View File
@@ -822,9 +822,14 @@ impl SearchableItem for LspLogView {
})
}
fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context<Self>) -> String {
fn query_suggestion(
&mut self,
ignore_settings: bool,
window: &mut Window,
cx: &mut Context<Self>,
) -> String {
self.editor
.update(cx, |e, cx| e.query_suggestion(window, cx))
.update(cx, |e, cx| e.query_suggestion(ignore_settings, window, cx))
}
fn activate_match(
@@ -956,7 +956,12 @@ impl SearchableItem for MarkdownPreviewView {
}
}
fn query_suggestion(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> String {
fn query_suggestion(
&mut self,
_ignore_settings: bool,
_window: &mut Window,
cx: &mut Context<Self>,
) -> String {
self.markdown.read(cx).selected_text().unwrap_or_default()
}
+37 -4
View File
@@ -56,7 +56,9 @@ use registrar::{ForDeployed, ForDismissed, SearchActionsRegistrar};
const MAX_BUFFER_SEARCH_HISTORY_SIZE: usize = 50;
pub use zed_actions::buffer_search::{Deploy, DeployReplace, Dismiss, FocusEditor};
pub use zed_actions::buffer_search::{
Deploy, DeployReplace, Dismiss, FocusEditor, UseSelectionForFind,
};
pub enum Event {
UpdateLocation,
@@ -839,6 +841,16 @@ impl BufferSearchBar {
this.deploy(&Deploy::replace(), window, cx);
}
}));
registrar.register_handler(ForDeployed(
|this, action: &UseSelectionForFind, window, cx| {
this.use_selection_for_find(action, window, cx);
},
));
registrar.register_handler(ForDismissed(
|this, action: &UseSelectionForFind, window, cx| {
this.use_selection_for_find(action, window, cx);
},
));
}
pub fn new(
@@ -991,7 +1003,7 @@ impl BufferSearchBar {
let mut handle = self.query_editor.focus_handle(cx);
let mut select_query = true;
let has_seed_text = self.query_suggestion(window, cx).is_some();
let has_seed_text = self.query_suggestion(false, window, cx).is_some();
if deploy.replace_enabled && has_seed_text {
handle = self.replacement_editor.focus_handle(cx);
select_query = false;
@@ -1100,7 +1112,7 @@ impl BufferSearchBar {
}
pub fn search_suggested(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let search = self.query_suggestion(window, cx).map(|suggestion| {
let search = self.query_suggestion(false, window, cx).map(|suggestion| {
self.search(&suggestion, Some(self.default_options), true, window, cx)
});
@@ -1154,12 +1166,13 @@ impl BufferSearchBar {
pub fn query_suggestion(
&mut self,
ignore_settings: bool,
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<String> {
self.active_searchable_item
.as_ref()
.map(|searchable_item| searchable_item.query_suggestion(window, cx))
.map(|searchable_item| searchable_item.query_suggestion(ignore_settings, window, cx))
.filter(|suggestion| !suggestion.is_empty())
}
@@ -1224,6 +1237,26 @@ impl BufferSearchBar {
));
}
pub fn use_selection_for_find(
&mut self,
_: &UseSelectionForFind,
window: &mut Window,
cx: &mut Context<Self>,
) {
let Some(search_text) = self.query_suggestion(true, window, cx) else {
return;
};
self.query_editor.update(cx, |query_editor, cx| {
query_editor.buffer().update(cx, |query_buffer, cx| {
let len = query_buffer.len(cx);
query_buffer.edit([(MultiBufferOffset(0)..len, search_text)], None, cx);
});
});
#[cfg(target_os = "macos")]
self.update_find_pasteboard(cx);
cx.notify();
}
pub fn focus_editor(&mut self, _: &FocusEditor, window: &mut Window, cx: &mut Context<Self>) {
if let Some(active_editor) = self.active_searchable_item.as_ref() {
let handle = active_editor.item_focus_handle(cx);
+1 -1
View File
@@ -1181,7 +1181,7 @@ impl ProjectSearchView {
}
let editor = item.act_as::<Editor>(cx)?;
let query = editor.query_suggestion(window, cx);
let query = editor.query_suggestion(false, window, cx);
if query.is_empty() { None } else { Some(query) }
});
+6 -1
View File
@@ -1852,7 +1852,12 @@ impl SearchableItem for TerminalView {
}
/// Returns the selection content to pre-load into this search
fn query_suggestion(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> String {
fn query_suggestion(
&mut self,
_ignore_settings: bool,
_window: &mut Window,
cx: &mut Context<Self>,
) -> String {
self.terminal()
.read(cx)
.last_content
+1 -5
View File
@@ -434,7 +434,6 @@ impl Vim {
let count = Vim::take_count(cx).unwrap_or(1);
Vim::take_forced_motion(cx);
let prior_selections = self.editor_selections(window, cx);
let cursor_word = self.editor_cursor_word(window, cx);
let vim = cx.entity();
let searched = pane.update(cx, |pane, cx| {
@@ -456,10 +455,7 @@ impl Vim {
if !search_bar.show(window, cx) {
return None;
}
let Some(query) = search_bar
.query_suggestion(window, cx)
.or_else(|| cursor_word)
else {
let Some(query) = search_bar.query_suggestion(true, window, cx) else {
drop(search_bar.search("", None, false, window, cx));
return None;
};
+1 -29
View File
@@ -33,9 +33,7 @@ use gpui::{
KeystrokeEvent, Render, Subscription, Task, WeakEntity, Window, actions,
};
use insert::{NormalBefore, TemporaryNormal};
use language::{
CharKind, CharScopeContext, CursorShape, Point, Selection, SelectionGoal, TransactionId,
};
use language::{CursorShape, Point, Selection, SelectionGoal, TransactionId};
pub use mode_indicator::ModeIndicator;
use motion::Motion;
use multi_buffer::ToPoint as _;
@@ -1595,32 +1593,6 @@ impl Vim {
.unwrap_or_default()
}
fn editor_cursor_word(
&mut self,
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<String> {
self.update_editor(cx, |_, editor, cx| {
let snapshot = &editor.snapshot(window, cx);
let selection = editor
.selections
.newest::<MultiBufferOffset>(&snapshot.display_snapshot);
let snapshot = snapshot.buffer_snapshot();
let (range, kind) =
snapshot.surrounding_word(selection.start, Some(CharScopeContext::Completion));
if kind == Some(CharKind::Word) {
let text: String = snapshot.text_for_range(range).collect();
if !text.trim().is_empty() {
return Some(text);
}
}
None
})
.unwrap_or_default()
}
/// When doing an action that modifies the buffer, we start recording so that `.`
/// will replay the action.
pub fn start_recording(&mut self, cx: &mut Context<Self>) {
+11 -4
View File
@@ -116,7 +116,12 @@ pub trait SearchableItem: Item + EventEmitter<SearchEvent> {
window: &mut Window,
cx: &mut Context<Self>,
);
fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context<Self>) -> String;
fn query_suggestion(
&mut self,
ignore_settings: bool,
window: &mut Window,
cx: &mut Context<Self>,
) -> String;
fn activate_match(
&mut self,
index: usize,
@@ -221,7 +226,7 @@ pub trait SearchableItemHandle: ItemHandle {
window: &mut Window,
cx: &mut App,
);
fn query_suggestion(&self, window: &mut Window, cx: &mut App) -> String;
fn query_suggestion(&self, ignore_settings: bool, window: &mut Window, cx: &mut App) -> String;
fn activate_match(
&self,
index: usize,
@@ -335,8 +340,10 @@ impl<T: SearchableItem> SearchableItemHandle for Entity<T> {
this.update_matches(matches.as_slice(), active_match_index, token, window, cx)
});
}
fn query_suggestion(&self, window: &mut Window, cx: &mut App) -> String {
self.update(cx, |this, cx| this.query_suggestion(window, cx))
fn query_suggestion(&self, ignore_settings: bool, window: &mut Window, cx: &mut App) -> String {
self.update(cx, |this, cx| {
this.query_suggestion(ignore_settings, window, cx)
})
}
fn activate_match(
&self,
+3 -1
View File
@@ -467,7 +467,9 @@ pub mod buffer_search {
/// Dismisses the search bar.
Dismiss,
/// Focuses back on the editor.
FocusEditor
FocusEditor,
/// Sets the search query to the current selection without opening the search bar or running a search.
UseSelectionForFind,
]
);
}