Fix modified arrow and page keys resolving to the opposite direction - #2093
Open
despotak wants to merge 1 commit into
Open
Fix modified arrow and page keys resolving to the opposite direction#2093despotak wants to merge 1 commit into
despotak wants to merge 1 commit into
Conversation
Ten entries in ANSI_SEQUENCES named the wrong key, so Ctrl+Shift+Up moved the cursor down and Ctrl+Shift+Down moved it up, in any application on any terminal that reports modified arrows. The table already agreed that final byte A is cursor-up and B is cursor-down at modifiers 2, 3, 5 and 9; it disagreed with itself at 4, 6, 7 and 8, where the pairs were transposed. ESC[5;7~ and ESC[5;8~ are a different slip: they resolve to the same values as ESC[6;7~ and ESC[6;8~, so the PageUp rows read as copied from the PageDown rows rather than swapped with them. Left/Right and Home/End were correct at every level; only the up/down axis was affected. input/win32.py already maps Up to ControlShiftUp and Down to ControlShiftDown, so this makes the two input paths agree rather than changing what the library thinks these keys mean. The tests assert the property rather than the ten values: for each final byte, every modifier level the table carries must resolve to a key naming the right direction. Three of the six parametrised cases fail without the fix and three pass, which are exactly the families that were already correct. Fixes prompt-toolkit#2092
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.
Fixes #2092.
Ten entries in
ANSI_SEQUENCESname the wrong key, so Ctrl+Shift+Up moves the cursordown and Ctrl+Shift+Down moves it up, in any prompt_toolkit application on any terminal
that reports modified arrows.
The evidence, from the table's own entries
The table already agrees that final byte
Ais cursor-up andBis cursor-down at four ofthe eight modifier levels it carries, and disagrees with itself at the other four:
ESC[5;7~andESC[5;8~are a different slip rather than a swap — they resolve to thesame values as
ESC[6;7~andESC[6;8~, so the PageUp rows read as copied from thePageDown rows.
Left/Right (
C/D) and Home/End (H/F) are correct at every modifier level. Onlythe up/down axis is affected: 8 arrow entries + 2 tilde entries.
Corroboration outside the table
src/prompt_toolkit/input/win32.py:441-442already mapsKeys.Up → Keys.ControlShiftUpand
Keys.Down → Keys.ControlShiftDown. The Windows input path has it right, so this makesthe two paths agree rather than changing what the library thinks these keys mean.
A terminal, asked directly. kitty 0.48.2's own encoder, using its own key identities:
And xterm's
ctlseqs:CSI 1 ; modifier Ais cursor-up,Bis cursor-down;CSI 5 ; modifier ~is Prior/PageUp andCSI 6 ; modifier ~is Next/PageDown.The tests
Deliberately not ten assertions. Each row of a literal table is independently
unfalsifiable — a wrong row looks exactly like a right one, and nothing cross-checks
Aagainst
B, which is how these survived. So the tests assert the property instead: foreach final byte, every modifier level the table carries must resolve to a key naming the
right direction.
That also makes them specific rather than blanket. Without the source fix:
Three of six red, and they are exactly the three families that are broken; the ones that
were already correct stay green.
Verification
Run against the checkout rather than an installed wheel (
PYTHONPATH=src— without it,pytest silently tests the installed copy):
ruff checkandruff format --checkclean on both files. I have not run mypy — it is notinstalled in the environment I verified this in.
How these were found
By building a parser that computes the key from the sequence's grammar rather than looking
it up, and diffing its answers against the table across every key × modifier combination a
terminal can emit. A parser cannot disagree with itself about which final byte means up, so
the disagreements surfaced on their own — there were exactly these ten, plus two divergences
that are not defects (modifier 9, which xterm reads as meta and the kitty protocol defines
as super).