@@ -54,6 +54,51 @@ def empty(self) -> bool:
5454 """
5555 return not self .events
5656
57+ def pending (self ) -> bool :
58+ """
59+ True when we have received the start of an escape/key sequence but
60+ are still waiting for further bytes to disambiguate it.
61+
62+ This is the case right after a byte (such as ESC) that our keymap
63+ knows only as a prefix of a longer sequence has been pushed, but
64+ before the rest of that sequence arrives. Consoles use this to
65+ decide whether the next read should block indefinitely or only for
66+ the escape timeout (see ``flush``).
67+ """
68+ return self .keymap is not self .compiled_keymap
69+
70+ def flush (self ) -> None :
71+ """
72+ Finalize any pending, incomplete input as discrete events.
73+
74+ This implements the classic "escape-time" disambiguation used by
75+ TUIs such as ncurses, Vim and Tmux: when we have received the start
76+ of an escape sequence (e.g. a lone ESC) but no further bytes arrive
77+ within the escape timeout, we stop waiting and emit the bytes
78+ accumulated so far as a complete key instead.
79+
80+ The behavior mirrors that of an unrecognized escape sequence: the
81+ leading ESC is emitted as a key and any remaining bytes are fed
82+ back through ``push`` so they can start another sequence or be
83+ treated as ordinary text. Calling this when there is nothing
84+ pending is a no-op.
85+ """
86+ if self .keymap is self .compiled_keymap :
87+ # Nothing pending: either idle, or a complete key was already
88+ # emitted by ``push``.
89+ return
90+ buf = self .buf .take_bytes ()
91+ self .keymap = self .compiled_keymap
92+ if buf and buf [0 ] == 27 : # escape
93+ self .insert (Event ('key' , '\033 ' , b'\033 ' ))
94+ for _c in buf [1 :]:
95+ self .push (_c )
96+ else :
97+ # Defensive: a pending prefix that does not start with ESC
98+ # (e.g. a partial multi-byte sequence). Emit it as text.
99+ data = bytes (buf ).decode (self .encoding , 'replace' )
100+ self .insert (Event ('key' , data , buf ))
101+
57102 def insert (self , event : Event ) -> None :
58103 """
59104 Inserts an event into the queue.
0 commit comments