mirror of
https://github.com/openai/codex.git
synced 2026-09-08 15:50:34 +00:00
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:
@@ -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(¶ms, 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(¶ms, 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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 …
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user