mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
gh-128388: pyrepl on Windows: add meta and ctrl+arrow keybindings (GH-128389)
Fix `Lib/_pyrepl/windows_console.py` to support more keybindings, like the `Ctrl`+`←` and `Ctrl`+`→` word-skipping keybindings and those with meta (i.e. Alt), e.g. to `kill-word` or `backward-kill-word`. Specifics: if Ctrl is pressed, emit "ctrl left" and "ctrl right" instead of just "left" or "right," and if Meta/Alt is pressed, emit the special key code for meta before emitting the other key that was pressed. Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Pieter Eendebak <pieter.eendebak@gmail.com>
This commit is contained in:
parent
baf65715fc
commit
688f3a0d4b
2 changed files with 27 additions and 16 deletions
|
@ -102,6 +102,10 @@ MOVE_UP = "\x1b[{}A"
|
|||
MOVE_DOWN = "\x1b[{}B"
|
||||
CLEAR = "\x1b[H\x1b[J"
|
||||
|
||||
# State of control keys: https://learn.microsoft.com/en-us/windows/console/key-event-record-str
|
||||
ALT_ACTIVE = 0x01 | 0x02
|
||||
CTRL_ACTIVE = 0x04 | 0x08
|
||||
|
||||
|
||||
class _error(Exception):
|
||||
pass
|
||||
|
@ -407,31 +411,37 @@ class WindowsConsole(Console):
|
|||
continue
|
||||
return None
|
||||
|
||||
key = rec.Event.KeyEvent.uChar.UnicodeChar
|
||||
key_event = rec.Event.KeyEvent
|
||||
raw_key = key = key_event.uChar.UnicodeChar
|
||||
|
||||
if rec.Event.KeyEvent.uChar.UnicodeChar == "\r":
|
||||
# Make enter make unix-like
|
||||
if key == "\r":
|
||||
# Make enter unix-like
|
||||
return Event(evt="key", data="\n", raw=b"\n")
|
||||
elif rec.Event.KeyEvent.wVirtualKeyCode == 8:
|
||||
elif key_event.wVirtualKeyCode == 8:
|
||||
# Turn backspace directly into the command
|
||||
return Event(
|
||||
evt="key",
|
||||
data="backspace",
|
||||
raw=rec.Event.KeyEvent.uChar.UnicodeChar,
|
||||
)
|
||||
elif rec.Event.KeyEvent.uChar.UnicodeChar == "\x00":
|
||||
key = "backspace"
|
||||
elif key == "\x00":
|
||||
# Handle special keys like arrow keys and translate them into the appropriate command
|
||||
code = VK_MAP.get(rec.Event.KeyEvent.wVirtualKeyCode)
|
||||
if code:
|
||||
return Event(
|
||||
evt="key", data=code, raw=rec.Event.KeyEvent.uChar.UnicodeChar
|
||||
)
|
||||
key = VK_MAP.get(key_event.wVirtualKeyCode)
|
||||
if key:
|
||||
if key_event.dwControlKeyState & CTRL_ACTIVE:
|
||||
key = f"ctrl {key}"
|
||||
elif key_event.dwControlKeyState & ALT_ACTIVE:
|
||||
# queue the key, return the meta command
|
||||
self.event_queue.insert(0, Event(evt="key", data=key, raw=key))
|
||||
return Event(evt="key", data="\033") # keymap.py uses this for meta
|
||||
return Event(evt="key", data=key, raw=key)
|
||||
if block:
|
||||
continue
|
||||
|
||||
return None
|
||||
|
||||
return Event(evt="key", data=key, raw=rec.Event.KeyEvent.uChar.UnicodeChar)
|
||||
if key_event.dwControlKeyState & ALT_ACTIVE:
|
||||
# queue the key, return the meta command
|
||||
self.event_queue.insert(0, Event(evt="key", data=key, raw=raw_key))
|
||||
return Event(evt="key", data="\033") # keymap.py uses this for meta
|
||||
|
||||
return Event(evt="key", data=key, raw=raw_key)
|
||||
|
||||
def push_char(self, char: int | bytes) -> None:
|
||||
"""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue