From 533699f98c1ecf6b360e61701748098eba255e2a Mon Sep 17 00:00:00 2001 From: I LUK KIM Date: Tue, 24 Mar 2026 23:58:51 -0700 Subject: [PATCH] feat: add arrow keys, shift+tab, home/end/delete/pageup/pagedown to sendNamedKey (#1920) The socket API's send-key command only supported enter, escape, tab, backspace, and ctrl+letter. Arrow keys and shift+tab had to be sent as raw escape sequences via send_text, but 0x1B is filtered out by socketTextChunks and converted to a standalone Escape key event, breaking multi-byte sequences like \x1b[A (ArrowUp). This commit extends sendNamedKey to handle: - Arrow keys: up/down/left/right (with arrow_up/arrowup aliases) - shift+tab / shift-tab / backtab - home, end - delete / del / forward_delete - pageup / page_up - pagedown / page_down These map directly to the existing sendKeyEvent infrastructure using the appropriate kVK_* keycodes and modifier flags. Co-authored-by: I Luk Kim --- Sources/TerminalController.swift | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Sources/TerminalController.swift b/Sources/TerminalController.swift index 37b3bd17..ce54dfe3 100644 --- a/Sources/TerminalController.swift +++ b/Sources/TerminalController.swift @@ -13205,6 +13205,36 @@ class TerminalController { case "backspace": sendKeyEvent(surface: surface, keycode: UInt32(kVK_Delete)) return true + case "up", "arrow_up", "arrowup": + sendKeyEvent(surface: surface, keycode: UInt32(kVK_UpArrow)) + return true + case "down", "arrow_down", "arrowdown": + sendKeyEvent(surface: surface, keycode: UInt32(kVK_DownArrow)) + return true + case "left", "arrow_left", "arrowleft": + sendKeyEvent(surface: surface, keycode: UInt32(kVK_LeftArrow)) + return true + case "right", "arrow_right", "arrowright": + sendKeyEvent(surface: surface, keycode: UInt32(kVK_RightArrow)) + return true + case "shift+tab", "shift-tab", "backtab": + sendKeyEvent(surface: surface, keycode: UInt32(kVK_Tab), mods: GHOSTTY_MODS_SHIFT) + return true + case "home": + sendKeyEvent(surface: surface, keycode: UInt32(kVK_Home)) + return true + case "end": + sendKeyEvent(surface: surface, keycode: UInt32(kVK_End)) + return true + case "delete", "del", "forward_delete": + sendKeyEvent(surface: surface, keycode: UInt32(kVK_ForwardDelete)) + return true + case "pageup", "page_up": + sendKeyEvent(surface: surface, keycode: UInt32(kVK_PageUp)) + return true + case "pagedown", "page_down": + sendKeyEvent(surface: surface, keycode: UInt32(kVK_PageDown)) + return true default: if keyName.lowercased().hasPrefix("ctrl-") || keyName.lowercased().hasPrefix("ctrl+") { let letter = keyName.dropFirst(5)