mirror of
https://github.com/openai/codex.git
synced 2026-06-02 11:22:01 +00:00
fix(tui): clarify footer shortcut overlay hints (#25625)
## Why The TUI shortcut overlay used static labels for `Tab` and `Ctrl+C`, even though both keys change behavior while a task is running. That made the visible help misleading: idle `Tab` submits rather than queues, and active-turn `Ctrl+C` interrupts rather than exits. Closes #25531. Closes #25564. ## What Changed - Pass task-running state into the shortcut overlay renderer. - Render `Tab` as `submit message` while idle and `queue message` while work is running. - Render `Ctrl+C` as `exit` while idle and `interrupt` while work is running. - Add snapshot coverage for the active-work shortcut overlay and update idle overlay snapshots. ## How to Test 1. Start Codex and open the shortcut overlay with `?` while no task is running. 2. Confirm the overlay shows `tab to submit message` and `ctrl + c to exit`. 3. Start a task, then open or keep the shortcut overlay visible while work is running. 4. Confirm the overlay shows `tab to queue message` and `ctrl + c to interrupt`. 5. Type a follow-up prompt during active work and press `Tab`; confirm it queues rather than submitting immediately. Targeted tests: - `just test -p codex-tui footer_snapshots` - `just test -p codex-tui footer_mode_snapshots` ## Validation Notes `just test -p codex-tui` currently has two unrelated guardian feature-flag test failures on this base: - `app::tests::update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history` - `app::tests::update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default` `just argument-comment-lint codex-rs/tui/src/bottom_pane/footer.rs` could not run locally because the prebuilt wrapper requires `dotslash`; the touched Rust diff was manually inspected for opaque positional literals.
This commit is contained in:
@@ -3410,6 +3410,7 @@ impl ChatComposer {
|
||||
esc_backtrack_hint: self.footer.esc_backtrack_hint,
|
||||
use_shift_enter_hint: self.footer.use_shift_enter_hint,
|
||||
is_task_running: self.is_task_running,
|
||||
queue_submissions: self.queue_submissions,
|
||||
quit_shortcut_key: self.footer.quit_shortcut_key,
|
||||
collaboration_modes_enabled: self.collaboration_modes_enabled,
|
||||
is_wsl,
|
||||
@@ -4691,6 +4692,16 @@ mod tests {
|
||||
},
|
||||
);
|
||||
|
||||
snapshot_composer_state(
|
||||
"footer_mode_shortcut_overlay_queue_submissions",
|
||||
/*enhanced_keys_supported*/ true,
|
||||
|composer| {
|
||||
composer.set_queue_submissions(/*queue_submissions*/ true);
|
||||
let _ = composer
|
||||
.handle_key_event(KeyEvent::new(KeyCode::Char('?'), KeyModifiers::NONE));
|
||||
},
|
||||
);
|
||||
|
||||
snapshot_composer_state(
|
||||
"footer_mode_ctrl_c_quit",
|
||||
/*enhanced_keys_supported*/ true,
|
||||
|
||||
@@ -68,6 +68,7 @@ pub(crate) struct FooterProps {
|
||||
pub(crate) esc_backtrack_hint: bool,
|
||||
pub(crate) use_shift_enter_hint: bool,
|
||||
pub(crate) is_task_running: bool,
|
||||
pub(crate) queue_submissions: bool,
|
||||
pub(crate) collaboration_modes_enabled: bool,
|
||||
pub(crate) is_wsl: bool,
|
||||
/// Which key the user must press again to quit.
|
||||
@@ -742,6 +743,8 @@ fn footer_from_props_lines(
|
||||
let state = ShortcutsState {
|
||||
use_shift_enter_hint: props.use_shift_enter_hint,
|
||||
esc_backtrack_hint: props.esc_backtrack_hint,
|
||||
is_task_running: props.is_task_running,
|
||||
queue_submissions: props.queue_submissions,
|
||||
is_wsl: props.is_wsl,
|
||||
collaboration_modes_enabled: props.collaboration_modes_enabled,
|
||||
key_hints,
|
||||
@@ -864,6 +867,8 @@ fn footer_hint_items_line(items: &[(String, String)]) -> Line<'static> {
|
||||
struct ShortcutsState {
|
||||
use_shift_enter_hint: bool,
|
||||
esc_backtrack_hint: bool,
|
||||
is_task_running: bool,
|
||||
queue_submissions: bool,
|
||||
is_wsl: bool,
|
||||
collaboration_modes_enabled: bool,
|
||||
key_hints: FooterKeyHints,
|
||||
@@ -1096,6 +1101,13 @@ impl ShortcutDescriptor {
|
||||
}?;
|
||||
let mut line = Line::from(vec![self.prefix.into(), key.into()]);
|
||||
match self.id {
|
||||
ShortcutId::QueueMessageTab => {
|
||||
if state.is_task_running || state.queue_submissions {
|
||||
line.push_span(" to queue message");
|
||||
} else {
|
||||
line.push_span(" to submit message");
|
||||
}
|
||||
}
|
||||
ShortcutId::EditPrevious => {
|
||||
if state.esc_backtrack_hint {
|
||||
line.push_span(" again to edit previous message");
|
||||
@@ -1107,6 +1119,13 @@ impl ShortcutDescriptor {
|
||||
]);
|
||||
}
|
||||
}
|
||||
ShortcutId::Quit => {
|
||||
if state.is_task_running {
|
||||
line.push_span(" to interrupt");
|
||||
} else {
|
||||
line.push_span(" to exit");
|
||||
}
|
||||
}
|
||||
_ => line.push_span(self.label),
|
||||
};
|
||||
Some(line)
|
||||
@@ -1542,6 +1561,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1559,6 +1579,7 @@ mod tests {
|
||||
esc_backtrack_hint: true,
|
||||
use_shift_enter_hint: true,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1579,6 +1600,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: true,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1589,6 +1611,24 @@ mod tests {
|
||||
},
|
||||
);
|
||||
|
||||
snapshot_footer(
|
||||
"footer_shortcuts_running",
|
||||
FooterProps {
|
||||
mode: FooterMode::ShortcutOverlay,
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: true,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
status_line_value: None,
|
||||
status_line_enabled: false,
|
||||
key_hints: FooterKeyHints::default_bindings(),
|
||||
active_agent_label: None,
|
||||
},
|
||||
);
|
||||
|
||||
snapshot_footer(
|
||||
"footer_ctrl_c_quit_idle",
|
||||
FooterProps {
|
||||
@@ -1596,6 +1636,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1613,6 +1654,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: true,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1630,6 +1672,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1647,6 +1690,7 @@ mod tests {
|
||||
esc_backtrack_hint: true,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1664,6 +1708,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: true,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1683,6 +1728,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1702,6 +1748,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: true,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1717,6 +1764,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: true,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1745,6 +1793,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: true,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: true,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1766,6 +1815,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1782,6 +1832,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: true,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1798,6 +1849,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1814,6 +1866,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: true,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1844,6 +1897,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: true,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1866,6 +1920,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1889,6 +1944,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: true,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1913,6 +1969,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1929,6 +1986,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: false,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -1948,6 +2006,7 @@ mod tests {
|
||||
esc_backtrack_hint: false,
|
||||
use_shift_enter_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
collaboration_modes_enabled: true,
|
||||
is_wsl: false,
|
||||
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
|
||||
@@ -2009,6 +2068,8 @@ mod tests {
|
||||
.binding_for(ShortcutsState {
|
||||
use_shift_enter_hint: false,
|
||||
esc_backtrack_hint: false,
|
||||
is_task_running: false,
|
||||
queue_submissions: false,
|
||||
is_wsl,
|
||||
collaboration_modes_enabled: false,
|
||||
key_hints: FooterKeyHints::default_bindings(),
|
||||
|
||||
@@ -11,7 +11,7 @@ expression: terminal.backend()
|
||||
" "
|
||||
" "
|
||||
" / for commands ! for shell commands "
|
||||
" shift + enter for newline tab to queue message "
|
||||
" shift + enter for newline tab to submit message "
|
||||
" @ for file paths ctrl + v to paste images "
|
||||
" ctrl + g to edit in external editor esc again to edit previous message "
|
||||
" ctrl + r search history ctrl + c to exit "
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
source: tui/src/bottom_pane/chat_composer.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
" "
|
||||
"› Ask Codex to do anything "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" / for commands ! for shell commands "
|
||||
" shift + enter for newline tab to queue message "
|
||||
" @ for file paths ctrl + v to paste images "
|
||||
" ctrl + g to edit in external editor esc esc to edit previous message "
|
||||
" ctrl + r search history ctrl + c to exit "
|
||||
" ⌥ + , reasoning down ⌥ + . reasoning up "
|
||||
" ctrl + t to view transcript "
|
||||
" "
|
||||
" customize shortcuts with /keymap "
|
||||
@@ -3,7 +3,7 @@ source: tui/src/bottom_pane/footer.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
" / for commands ! for shell commands "
|
||||
" ctrl + j for newline tab to queue message "
|
||||
" ctrl + j for newline tab to submit message "
|
||||
" @ for file paths ctrl + v to paste images "
|
||||
" ctrl + g to edit in external editor esc esc to edit previous message "
|
||||
" ctrl + r search history ctrl + c to exit "
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
source: tui/src/bottom_pane/footer.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
" / for commands ! for shell commands "
|
||||
" ctrl + j for newline tab to queue message "
|
||||
" @ for file paths ctrl + v to paste images "
|
||||
" ctrl + g to edit in external editor esc esc to edit previous message "
|
||||
" ctrl + r search history ctrl + c to interrupt "
|
||||
" ⌥ + , reasoning down ⌥ + . reasoning up "
|
||||
" ctrl + t to view transcript "
|
||||
" "
|
||||
" customize shortcuts with /keymap "
|
||||
@@ -3,7 +3,7 @@ source: tui/src/bottom_pane/footer.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
" / for commands ! for shell commands "
|
||||
" shift + enter for newline tab to queue message "
|
||||
" shift + enter for newline tab to submit message "
|
||||
" @ for file paths ctrl + v to paste images "
|
||||
" ctrl + g to edit in external editor esc again to edit previous message "
|
||||
" ctrl + r search history ctrl + c to exit "
|
||||
|
||||
Reference in New Issue
Block a user