Repository navigation
Translate a lone TTY ESC to the escape key in terminal-input buffers - #595
Merged
Merged
Conversation
On text terminals the escape key arrives as a bare 0x1b byte, which the M-<char> bindings turn into a pending meta prefix, so a lone ESC never reached the PTY. Install a terminal-local menu-item filter on the ESC entry of input-decode-map (the evil-esc-mode technique) that yields the escape event when no follow-up byte arrives within the new ghostel-tty-escape-delay, keeping escape sequences and ESC-as-meta decoding intact and composing with other packages' filters such as evil's. The translated event goes through the native key encoder, so kitty-protocol children receive CSI 27 u and legacy children a raw ESC. Bind ESC ESC to the key encoder as alt+escape so a fast double-tap, whose second byte the filter deliberately leaves raw, no longer pends on the global keyboard-escape-quit prefix. Fixes #592
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On a TTY frame, pressing ESC in a ghostel buffer sent nothing: the mode maps bind
<escape>, a function-key event legacy TTYs never generate, while the TTY delivers the raw byte 27. TheM-<char>bindings make[27]a prefix keymap, and Emacs has no ESC timeout, soread-key-sequenceblocked with[27]pending forever. Collateral: ESC ESC also wedged (globalESC ESC ESCprefix), and C-g pressed while ESC was pending completed asC-M-g, injecting^[^Ginto the PTY.Fix
ghostel-tty-escape-delay(default 0.01 s, nil disables): a terminal-localmenu-item:filteron[?\e]ininput-decode-map(the evil-esc-mode technique) yields[escape]when no follow-up byte arrives within the delay — only in ghostel terminal-input buffers (semi-char/char with a live term). Everywhere else the filter returns the saved map, so escape sequences, ESC-as-meta, and non-ghostel buffers decode byte-identically to before. The translated event goes through the native key encoder, so kitty-protocol children getCSI 27 uand legacy children a rawESC.ghostel-modebody and from a buffer-localwindow-buffer-change-functionshandler (covers lateremacsclient -tframes). TTY terminals only; idempotent per terminal; re-wraps if another package replaces the entry. It reads the raw entry structurally becauselookup-keyresolvesmenu-itemfilters (which would drop e.g. evil's wrapper), and detects its own wrapper by the:filtertag becausedefine-keycopies menu-item lists.ESC ESCis bound to the key encoder as alt+escape: the filter deliberately leaves the second ESC of a fast pair raw, so the pair reaches[27 27]instead of pending on the globalkeyboard-escape-quitprefix.evil-escfilter in either install order; at most one translation delay is paid per key.Verification
ESC ESCbindings); existing ESC decode invariants (C-[not hijacked,ESC [/ESC Ounbound) still pass.make -j8 allgreen.^[promptly in semi-char and char with no pending prefix; C-g clean; fast ESC x →^[x; arrows →^[[A; slow ESC ESC → two^[; fast ESC ESC →^[^[; kitty protocol →^[[27u; non-ghostel buffers andM-xuntouched. GUI<escape>regression-checked.C-c M-dstill decodes as meta,C-c+ paused ESC runsevil-force-normal-state.Known limitation (deliberately deferred): no
defining-kbd-macrofixup à la evil — a macro recording a lone ESC records the raw byte and may not replay asescape.