mirror of
https://github.com/openai/codex.git
synced 2026-11-02 19:43:24 +00:00
Avoid requesting key-release events in Ghostty (#36834)
## Why Ghostty can leak release events for shortcuts that the terminal consumes. ## What changed - Detect Ghostty when `TERM` is `xterm-ghostty`, including when `TERM_PROGRAM` is unavailable. - Omit `REPORT_EVENT_TYPES` from keyboard enhancement flags for Ghostty while retaining alternate-key and escape-code disambiguation reporting. ## Testing - Cover Ghostty detection through `TERM` and its keyboard enhancement flags. GitOrigin-RevId: d865a6cdd1373aad4b78099e821d1ebaeb6cfdff
This commit is contained in:
@@ -150,6 +150,7 @@ impl TerminalInfo {
|
||||
fn from_term(term: String, multiplexer: Option<Multiplexer>) -> Self {
|
||||
let name = match term.as_str() {
|
||||
"dumb" => TerminalName::Dumb,
|
||||
"xterm-ghostty" => TerminalName::Ghostty,
|
||||
"wezterm" | "wezterm-mux" => TerminalName::WezTerm,
|
||||
_ => TerminalName::Unknown,
|
||||
};
|
||||
@@ -293,7 +294,7 @@ pub fn terminal_info() -> TerminalInfo {
|
||||
/// - Otherwise, `TERM_PROGRAM` (plus `TERM_PROGRAM_VERSION`) drives the detected terminal name.
|
||||
/// This means `TERM_PROGRAM` can mask later probes (for example `WT_SESSION`).
|
||||
/// - Next, terminal-specific variables (WEZTERM, iTerm2, Apple Terminal, kitty, etc.) are checked.
|
||||
/// - Finally, `TERM` is used as the capability fallback with `TerminalName::Unknown`.
|
||||
/// - Finally, `TERM` is used as the capability fallback.
|
||||
///
|
||||
/// tmux client term info is only consulted when a tmux multiplexer is detected, and it is
|
||||
/// derived from `tmux display-message` to surface the underlying terminal program instead of
|
||||
|
||||
@@ -239,6 +239,25 @@ fn detects_ghostty() {
|
||||
"Ghostty",
|
||||
"ghostty_term_program_user_agent"
|
||||
);
|
||||
|
||||
let env = FakeEnvironment::new().with_var("TERM", "xterm-ghostty");
|
||||
let terminal = detect_terminal_info_from_env(&env);
|
||||
assert_eq!(
|
||||
terminal,
|
||||
terminal_info(
|
||||
TerminalName::Ghostty,
|
||||
/*term_program*/ None,
|
||||
/*version*/ None,
|
||||
Some("xterm-ghostty"),
|
||||
/*multiplexer*/ None
|
||||
),
|
||||
"ghostty_term_info"
|
||||
);
|
||||
assert_eq!(
|
||||
terminal.user_agent_token(),
|
||||
"xterm-ghostty",
|
||||
"ghostty_term_user_agent"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -156,10 +156,12 @@ fn keyboard_enhancement_flags(
|
||||
let flags = KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
|
||||
| KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS;
|
||||
|
||||
// iTerm can leak the release of an exit shortcut into the parent shell.
|
||||
// iTerm and Ghostty can leak shortcut release events that the terminal consumes.
|
||||
// tmux's xterm key format also loses Shift-Enter when event types are
|
||||
// reported. Preserve repeat classification on transports that support it.
|
||||
if terminal_name == TerminalName::Iterm2 || matches!(tmux_extended_keys_format, Some("xterm")) {
|
||||
if matches!(terminal_name, TerminalName::Ghostty | TerminalName::Iterm2)
|
||||
|| matches!(tmux_extended_keys_format, Some("xterm"))
|
||||
{
|
||||
flags
|
||||
} else {
|
||||
flags | KeyboardEnhancementFlags::REPORT_EVENT_TYPES
|
||||
@@ -331,6 +333,17 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keyboard_enhancement_suppresses_release_reporting_for_ghostty() {
|
||||
assert_eq!(
|
||||
ansi_for(PushKeyboardEnhancementFlags(keyboard_enhancement_flags(
|
||||
TerminalName::Ghostty,
|
||||
/*tmux_extended_keys_format*/ None
|
||||
))),
|
||||
"\x1b[>5u"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keyboard_enhancement_preserves_repeat_reporting_for_kitty() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user