summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulie Peña <203125+paulie4@users.noreply.github.com>2025-01-10 12:52:19 (GMT)
committerGitHub <noreply@github.com>2025-01-10 12:52:19 (GMT)
commit688f3a0d4b94874ff6d72af3baafd8bbf911153e (patch)
treee7145801bd4a6d2a5b7ef5a9949423f48b1b4bab
parentbaf65715fc9002e43cd0e1010b8dba9b4c84d503 (diff)
downloadcpython-688f3a0d4b94874ff6d72af3baafd8bbf911153e.zip
cpython-688f3a0d4b94874ff6d72af3baafd8bbf911153e.tar.gz
cpython-688f3a0d4b94874ff6d72af3baafd8bbf911153e.tar.bz2
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>
-rw-r--r--Lib/_pyrepl/windows_console.py42
-rw-r--r--Misc/NEWS.d/next/Library/2025-01-01-19-24-43.gh-issue-128388.8UdMz_.rst1
2 files changed, 27 insertions, 16 deletions
diff --git a/Lib/_pyrepl/windows_console.py b/Lib/_pyrepl/windows_console.py
index d457d2b..e738fd0 100644
--- a/Lib/_pyrepl/windows_console.py
+++ b/Lib/_pyrepl/windows_console.py
@@ -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:
"""
diff --git a/Misc/NEWS.d/next/Library/2025-01-01-19-24-43.gh-issue-128388.8UdMz_.rst b/Misc/NEWS.d/next/Library/2025-01-01-19-24-43.gh-issue-128388.8UdMz_.rst
new file mode 100644
index 0000000..5bef0fd
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-01-01-19-24-43.gh-issue-128388.8UdMz_.rst
@@ -0,0 +1 @@
+Fix ``PyREPL`` on Windows to support more keybindings, like the :kbd:`Control-←` and :kbd:`Control-→` word-skipping keybindings and those with meta (i.e. :kbd:`Alt`), e.g. :kbd:`Alt-d` to ``kill-word`` or :kbd:`Alt-Backspace` ``backward-kill-word``.