keymap_editor: Make "toggle exact match mode" the default for binding search (#42883)
I think having the "exact mode" turned on by default is usually what users will expect when searching for a specific keybinding. When it's turned off, it's very odd to search for a super common binding like "command-enter" and get no results. That happens because without that mode, we're trying to match for subsequent matches, which I'm betting it's an edge case. Hopefully, this change will make the keymap editor feel more like it works well. I'm also adding the toggle icon button inside the keystroke input for consistency with the project search input. Making this change very inspired by [Sam Rose's feedback](https://bsky.app/profile/samwho.dev/post/3m5juszqyd22w). Release Notes: - keymap editor: Made the "toggle exact match mode" the default keystroke search mode so that whatever you search for matches exactly to results.
This commit is contained in:
@@ -184,7 +184,7 @@ enum SearchMode {
|
||||
impl SearchMode {
|
||||
fn invert(&self) -> Self {
|
||||
match self {
|
||||
SearchMode::Normal => SearchMode::KeyStroke { exact_match: false },
|
||||
SearchMode::Normal => SearchMode::KeyStroke { exact_match: true },
|
||||
SearchMode::KeyStroke { .. } => SearchMode::Normal,
|
||||
}
|
||||
}
|
||||
@@ -1600,9 +1600,33 @@ impl Item for KeymapEditor {
|
||||
|
||||
impl Render for KeymapEditor {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut ui::Context<Self>) -> impl ui::IntoElement {
|
||||
if let SearchMode::KeyStroke { exact_match } = self.search_mode {
|
||||
let button = IconButton::new("keystrokes-exact-match", IconName::CaseSensitive)
|
||||
.tooltip(move |_window, cx| {
|
||||
Tooltip::for_action(
|
||||
"Toggle Exact Match Mode",
|
||||
&ToggleExactKeystrokeMatching,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.shape(IconButtonShape::Square)
|
||||
.toggle_state(exact_match)
|
||||
.on_click(cx.listener(|_, _, window, cx| {
|
||||
window.dispatch_action(ToggleExactKeystrokeMatching.boxed_clone(), cx);
|
||||
}));
|
||||
|
||||
self.keystroke_editor.update(cx, |editor, _| {
|
||||
editor.actions_slot = Some(button.into_any_element());
|
||||
});
|
||||
} else {
|
||||
self.keystroke_editor.update(cx, |editor, _| {
|
||||
editor.actions_slot = None;
|
||||
});
|
||||
}
|
||||
|
||||
let row_count = self.matches.len();
|
||||
let theme = cx.theme();
|
||||
let focus_handle = &self.focus_handle;
|
||||
let theme = cx.theme();
|
||||
|
||||
v_flex()
|
||||
.id("keymap-editor")
|
||||
@@ -1786,49 +1810,14 @@ impl Render for KeymapEditor {
|
||||
)
|
||||
),
|
||||
)
|
||||
.when_some(
|
||||
match self.search_mode {
|
||||
SearchMode::Normal => None,
|
||||
SearchMode::KeyStroke { exact_match } => Some(exact_match),
|
||||
},
|
||||
|this, exact_match| {
|
||||
.when(
|
||||
matches!(self.search_mode, SearchMode::KeyStroke { .. }),
|
||||
|this| {
|
||||
this.child(
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(self.keystroke_editor.clone())
|
||||
.child(
|
||||
h_flex()
|
||||
.min_w_64()
|
||||
.child(
|
||||
IconButton::new(
|
||||
"keystrokes-exact-match",
|
||||
IconName::CaseSensitive,
|
||||
)
|
||||
.tooltip({
|
||||
let keystroke_focus_handle =
|
||||
self.keystroke_editor.read(cx).focus_handle(cx);
|
||||
|
||||
move |_window, cx| {
|
||||
Tooltip::for_action_in(
|
||||
"Toggle Exact Match Mode",
|
||||
&ToggleExactKeystrokeMatching,
|
||||
&keystroke_focus_handle,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
})
|
||||
.shape(IconButtonShape::Square)
|
||||
.toggle_state(exact_match)
|
||||
.on_click(
|
||||
cx.listener(|_, _, window, cx| {
|
||||
window.dispatch_action(
|
||||
ToggleExactKeystrokeMatching.boxed_clone(),
|
||||
cx,
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(div().min_w_64()), // Spacer div to align with the search input
|
||||
)
|
||||
},
|
||||
),
|
||||
|
||||
@@ -64,6 +64,7 @@ pub struct KeystrokeInput {
|
||||
clear_close_keystrokes_timer: Option<Task<()>>,
|
||||
#[cfg(test)]
|
||||
recording: bool,
|
||||
pub actions_slot: Option<AnyElement>,
|
||||
}
|
||||
|
||||
impl KeystrokeInput {
|
||||
@@ -94,6 +95,7 @@ impl KeystrokeInput {
|
||||
clear_close_keystrokes_timer: None,
|
||||
#[cfg(test)]
|
||||
recording: false,
|
||||
actions_slot: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,6 +447,11 @@ impl KeystrokeInput {
|
||||
// not get de-synced
|
||||
self.inner_focus_handle.is_focused(window)
|
||||
}
|
||||
|
||||
pub fn actions_slot(mut self, action: impl IntoElement) -> Self {
|
||||
self.actions_slot = Some(action.into_any_element());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<()> for KeystrokeInput {}
|
||||
@@ -586,7 +593,7 @@ impl Render for KeystrokeInput {
|
||||
.min_w_0()
|
||||
.justify_center()
|
||||
.flex_wrap()
|
||||
.gap(ui::DynamicSpacing::Base04.rems(cx))
|
||||
.gap_1()
|
||||
.children(self.render_keystrokes(is_recording)),
|
||||
)
|
||||
.child(
|
||||
@@ -636,6 +643,7 @@ impl Render for KeystrokeInput {
|
||||
)
|
||||
}
|
||||
})
|
||||
.when_some(self.actions_slot.take(), |this, action| this.child(action))
|
||||
.when(is_recording, |this| {
|
||||
this.child(
|
||||
IconButton::new("clear-btn", IconName::Backspace)
|
||||
|
||||
Reference in New Issue
Block a user