tui: return from side chat on Ctrl-D (#20282)

## Why

Fixes #20264.

Side conversations are an ephemeral layer on top of the main chat.
Pressing `Ctrl+D` from an empty side-chat composer should unwind back to
the parent thread, matching the existing side-return behavior, instead
of falling through to the global quit shortcut and exiting Codex.

## What changed

The side-return shortcut matcher now treats `Ctrl+D` the same way it
already treats `Esc` and `Ctrl+C`. Because app-level side-return
handling runs before the chat widget's global quit handling, this
returns from `/side` while preserving normal `Ctrl+D` quit behavior
outside side conversations.

The existing shortcut coverage was updated to include lowercase and
uppercase `Ctrl+D` key events.

## Verification

- `cargo test -p codex-tui
side_return_shortcuts_match_esc_ctrl_c_and_ctrl_d`
- `cargo test -p codex-tui` starts successfully and the new shortcut
test passes, but the broader suite later aborts in the unrelated
existing test
`app::tests::attach_live_thread_for_selection_rejects_unmaterialized_fallback_threads`
with a stack overflow.
This commit is contained in:
Eric Traut
2026-04-29 17:26:11 -07:00
committed by GitHub
Unverified
parent fedcefe9da
commit 515aa9a4fb
+11 -3
View File
@@ -65,7 +65,11 @@ pub(super) fn side_return_shortcut_matches(key_event: KeyEvent) -> bool {
modifiers,
kind: KeyEventKind::Press,
..
} if modifiers.contains(KeyModifiers::CONTROL) && c.eq_ignore_ascii_case(&'c') => true,
} if modifiers.contains(KeyModifiers::CONTROL)
&& (c.eq_ignore_ascii_case(&'c') || c.eq_ignore_ascii_case(&'d')) =>
{
true
}
_ => false,
}
}
@@ -75,7 +79,7 @@ mod tests {
use super::*;
#[test]
fn side_return_shortcuts_match_esc_and_ctrl_c() {
fn side_return_shortcuts_match_esc_ctrl_c_and_ctrl_d() {
assert!(side_return_shortcut_matches(KeyEvent::new(
KeyCode::Esc,
KeyModifiers::NONE,
@@ -93,10 +97,14 @@ mod tests {
KeyCode::Char('C'),
KeyModifiers::CONTROL,
)));
assert!(!side_return_shortcut_matches(KeyEvent::new(
assert!(side_return_shortcut_matches(KeyEvent::new(
KeyCode::Char('d'),
KeyModifiers::CONTROL,
)));
assert!(side_return_shortcut_matches(KeyEvent::new(
KeyCode::Char('D'),
KeyModifiers::CONTROL,
)));
assert!(!side_return_shortcut_matches(KeyEvent::new_with_kind(
KeyCode::Esc,
KeyModifiers::NONE,