feat(tui): add common keymap picker category

Add a curated Common tab to `/keymap` for the shortcuts most
likely to be rebound, while keeping All as the initial view.

Demote onboarding from the top-level picker categories without
removing its keymap actions from All or search.
This commit is contained in:
Felipe Coury
2026-04-19 00:27:40 -03:00
parent b9a5f3c773
commit fb459feb5a
5 changed files with 113 additions and 10 deletions

View File

@@ -717,6 +717,7 @@ fn key_parts_to_config_key_spec(
#[cfg(test)]
mod tests {
use super::picker::KEYMAP_ALL_TAB_ID;
use super::picker::KEYMAP_COMMON_TAB_ID;
use super::picker::KEYMAP_CUSTOM_TAB_ID;
use super::picker::KEYMAP_UNBOUND_TAB_ID;
use super::*;
@@ -849,6 +850,65 @@ mod tests {
}));
}
#[test]
fn picker_common_tab_lists_curated_actions() {
let runtime = RuntimeKeymap::defaults();
let params = build_keymap_picker_params(&runtime, &TuiKeymap::default());
let common_tab = selection_tab(&params, KEYMAP_COMMON_TAB_ID);
let actions = common_tab
.items
.iter()
.map(|item| {
item.search_value
.as_deref()
.unwrap_or_default()
.split_whitespace()
.take(2)
.collect::<Vec<_>>()
.join(".")
})
.collect::<Vec<_>>();
assert_eq!(
actions,
vec![
"Composer.submit",
"Editor.insert_newline",
"Composer.queue",
"Global.open_external_editor",
"Global.copy",
"Global.toggle_vim_mode",
"Editor.delete_backward_word",
"Editor.delete_forward_word",
"Editor.move_word_left",
"Editor.move_word_right",
"Global.open_transcript",
"Pager.close",
"Pager.page_up",
"Pager.page_down",
"Approval.open_fullscreen",
"Approval.approve",
"Approval.approve_for_session",
"Approval.decline",
"Approval.cancel",
]
);
}
#[test]
fn picker_keeps_onboarding_actions_searchable_without_dedicated_tab() {
let runtime = RuntimeKeymap::defaults();
let params = build_keymap_picker_params(&runtime, &TuiKeymap::default());
let all_tab = selection_tab(&params, KEYMAP_ALL_TAB_ID);
assert!(params.tabs.iter().all(|tab| tab.label != "Onboarding"));
assert!(all_tab.items.iter().any(|item| {
item.search_value
.as_deref()
.is_some_and(|search_value| search_value.contains("Onboarding quit"))
}));
}
#[test]
fn picker_content_snapshot() {
let runtime = RuntimeKeymap::defaults();

View File

@@ -24,6 +24,7 @@ use super::has_custom_binding;
const KEYMAP_PICKER_VIEW_ID: &str = "keymap-picker";
pub(super) const KEYMAP_ALL_TAB_ID: &str = "all-shortcuts";
pub(super) const KEYMAP_COMMON_TAB_ID: &str = "common-shortcuts";
pub(super) const KEYMAP_CUSTOM_TAB_ID: &str = "custom-shortcuts";
pub(super) const KEYMAP_UNBOUND_TAB_ID: &str = "unbound-shortcuts";
const KEYMAP_CONTEXT_LABEL_WIDTH: usize = 12;
@@ -53,6 +54,28 @@ struct KeymapContextTab {
contexts: &'static [&'static str],
}
const KEYMAP_COMMON_ACTIONS: &[(&str, &str)] = &[
("composer", "submit"),
("editor", "insert_newline"),
("composer", "queue"),
("global", "open_external_editor"),
("global", "copy"),
("global", "toggle_vim_mode"),
("editor", "delete_backward_word"),
("editor", "delete_forward_word"),
("editor", "move_word_left"),
("editor", "move_word_right"),
("global", "open_transcript"),
("pager", "close"),
("pager", "page_up"),
("pager", "page_down"),
("approval", "open_fullscreen"),
("approval", "approve"),
("approval", "approve_for_session"),
("approval", "decline"),
("approval", "cancel"),
];
const KEYMAP_CONTEXT_TABS: &[KeymapContextTab] = &[
KeymapContextTab {
id: "app-shortcuts",
@@ -90,12 +113,6 @@ const KEYMAP_CONTEXT_TABS: &[KeymapContextTab] = &[
description: "Approval prompt shortcuts.",
contexts: &["approval"],
},
KeymapContextTab {
id: "onboarding-shortcuts",
label: "Onboarding",
description: "Onboarding flow shortcuts.",
contexts: &["onboarding"],
},
];
pub(crate) fn build_keymap_picker_params(
@@ -126,6 +143,22 @@ pub(crate) fn build_keymap_picker_params(
),
});
let common_rows = keymap_common_rows(&rows);
let common_count = common_rows.len();
tabs.push(SelectionTab {
id: KEYMAP_COMMON_TAB_ID.to_string(),
label: "Common".to_string(),
header: keymap_header(
"Frequently customized shortcuts.".to_string(),
action_count_line(common_count),
),
items: keymap_selection_items(
common_rows,
"No common shortcuts",
"No common shortcut actions are available.",
),
});
let custom_rows = rows
.iter()
.filter(|row| row.custom_binding)
@@ -223,6 +256,16 @@ fn build_keymap_rows(
.collect()
}
fn keymap_common_rows(rows: &[KeymapActionRow]) -> Vec<&KeymapActionRow> {
KEYMAP_COMMON_ACTIONS
.iter()
.filter_map(|(context, action)| {
rows.iter()
.find(|row| row.context == *context && row.action == *action)
})
.collect()
}
fn keymap_selection_items<'a>(
rows: impl IntoIterator<Item = &'a KeymapActionRow>,
empty_name: &str,

View File

@@ -3,6 +3,7 @@ source: tui/src/keymap_setup.rs
expression: snapshot
---
tab: All (91 selectable)
tab: Common (19 selectable)
tab: Customized (0) (0 selectable)
tab: Unbound (1) (1 selectable)
tab: App (6 selectable)
@@ -11,7 +12,6 @@ tab: Editor (16 selectable)
tab: Vim (34 selectable)
tab: Navigation (17 selectable)
tab: Approval (6 selectable)
tab: Onboarding (9 selectable)
Open Transcript | ctrl-t · Default | Global open_transcript Open Transcript Open the transcript overlay. ctrl-t Default
Open External Editor | ctrl-g · Default | Global open_external_editor Open External Editor Open the current draft in an external editor. ctrl-g Default
Copy | ctrl-o · Default | Global copy Copy Copy the last agent response to the clipboard. ctrl-o Default

View File

@@ -7,8 +7,8 @@ expression: "render_picker(params, 78)"
All configurable shortcuts.
91 actions, 0 customized, 1 unbound.
[All] Customized (0) Unbound (1) App Composer Editor Vim Navigation
Approval Onboarding
[All] Common Customized (0) Unbound (1) App Composer Editor Vim
Navigation Approval
Type to search shortcuts
[D] Global Open Transcript Current ctrl-t · Default …

View File

@@ -7,7 +7,7 @@ expression: "render_picker(params, 120)"
All configurable shortcuts.
91 actions, 0 customized, 1 unbound.
[All] Customized (0) Unbound (1) App Composer Editor Vim Navigation Approval Onboarding
[All] Common Customized (0) Unbound (1) App Composer Editor Vim Navigation Approval
Type to search shortcuts
[D] Global Open Transcript Current ctrl-t · Default keymap. Open the transcript overlay.