Skip to content

Commit 36f47ac

Browse files
committed
Add esc_timeout parameter to BaseEventQueue
1 parent 296b9e4 commit 36f47ac

3 files changed

Lines changed: 13 additions & 18 deletions

File tree

Lib/_pyrepl/base_eventqueue.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,26 @@
2424
See unix_eventqueue and windows_eventqueue for subclasses.
2525
"""
2626

27+
import os
2728
from collections import deque
2829

2930
from . import keymap
3031
from .console import Event
3132
from .trace import trace
3233

34+
ESC_TIMEOUT_DEFAULT = 0.1
35+
3336
class BaseEventQueue:
34-
def __init__(self, encoding: str, keymap_dict: dict[bytes, str]) -> None:
37+
def __init__(self, encoding: str, keymap_dict: dict[bytes, str],
38+
esc_timeout: float | None = None) -> None:
3539
self.compiled_keymap = keymap.compile_keymap(keymap_dict)
3640
self.keymap = self.compiled_keymap
3741
trace("keymap {k!r}", k=self.keymap)
3842
self.encoding = encoding
3943
self.events: deque[Event] = deque()
4044
self.buf = bytearray()
45+
default = float(os.environ.get("PYREPL_ESC_TIMEOUT", ESC_TIMEOUT_DEFAULT))
46+
self.esc_timeout = esc_timeout if esc_timeout is not None else default
4147

4248
def get(self) -> Event | None:
4349
"""
@@ -63,25 +69,13 @@ def pending(self) -> bool:
6369
knows only as a prefix of a longer sequence has been pushed, but
6470
before the rest of that sequence arrives. Consoles use this to
6571
decide whether the next read should block indefinitely or only for
66-
the escape timeout (see ``flush``).
72+
the escape timeout.
6773
"""
6874
return self.keymap is not self.compiled_keymap
6975

7076
def flush(self) -> None:
7177
"""
7278
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.
8579
"""
8680
if self.keymap is self.compiled_keymap:
8781
# Nothing pending: either idle, or a complete key was already

Lib/_pyrepl/unix_eventqueue.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ def get_terminal_keycodes(ti: TermInfo) -> dict[bytes, str]:
6969

7070

7171
class EventQueue(BaseEventQueue):
72-
def __init__(self, fd: int, encoding: str, ti: TermInfo) -> None:
72+
def __init__(self, fd: int, encoding: str, ti: TermInfo,
73+
esc_timeout: float | None = None) -> None:
7374
keycodes = get_terminal_keycodes(ti)
7475
if os.isatty(fd):
7576
backspace = tcgetattr(fd)[6][VERASE]
7677
keycodes[backspace] = "backspace"
77-
BaseEventQueue.__init__(self, encoding, keycodes)
78+
BaseEventQueue.__init__(self, encoding, keycodes, esc_timeout)

Lib/_pyrepl/windows_eventqueue.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@
3838
}
3939

4040
class EventQueue(BaseEventQueue):
41-
def __init__(self, encoding: str) -> None:
42-
BaseEventQueue.__init__(self, encoding, VT_MAP)
41+
def __init__(self, encoding: str, esc_timeout: float | None = None) -> None:
42+
BaseEventQueue.__init__(self, encoding, VT_MAP, esc_timeout)

0 commit comments

Comments
 (0)