Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `link-hover-background` renamed to `link-background-hover`
- `link-hover-color` renamed to `link-color-hover`
- `link-hover-style` renamed to `link-style-hover`
- Brought rxvt's use of shift-numpad keys in line with most other terminals https://github.com/Textualize/textual/pull/3769

### Added

Expand Down
22 changes: 21 additions & 1 deletion src/textual/_ansi_sequences.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from __future__ import annotations

from typing import Mapping, Tuple

from .keys import Keys

# Mapping of vt100 escape codes to Keys.
ANSI_SEQUENCES_KEYS: Mapping[str, Tuple[Keys, ...]] = {
ANSI_SEQUENCES_KEYS: Mapping[str, Tuple[Keys, ...] | str] = {
# Control keys.
" ": (Keys.Space,),
"\r": (Keys.Enter,),
Expand Down Expand Up @@ -350,6 +352,24 @@
"\x1b[1;8w": (Keys.Escape, Keys.ControlShift7),
"\x1b[1;8x": (Keys.Escape, Keys.ControlShift8),
"\x1b[1;8y": (Keys.Escape, Keys.ControlShift9),
# Simplify some sequences that appear to be unique to rxvt; see
# https://github.com/Textualize/textual/issues/3741 for context.
"\x1bOj": "*",
"\x1bOk": "+",
"\x1bOm": "-",
"\x1bOn": ".",
"\x1bOo": "/",
"\x1bOp": "0",
"\x1bOq": "1",
"\x1bOr": "2",
"\x1bOs": "3",
"\x1bOt": "4",
"\x1bOu": "5",
"\x1bOv": "6",
"\x1bOw": "7",
"\x1bOx": "8",
"\x1bOy": "9",
"\x1bOM": (Keys.Enter,),
}

# https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036
Expand Down
14 changes: 12 additions & 2 deletions src/textual/_xterm_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,20 @@ def _sequence_to_key_events(
Keys
"""
keys = ANSI_SEQUENCES_KEYS.get(sequence)
if keys is not None:
if isinstance(keys, tuple):
# If the sequence mapped to a tuple, then it's values from the
# `Keys` enum. Raise key events from what we find in the tuple.
for key in keys:
yield events.Key(key.value, sequence if len(sequence) == 1 else None)
elif len(sequence) == 1:
return
# If keys is a string, the intention is that it's a mapping to a
# character, which should really be treated as the sequence for the
# purposes of the next step...
if isinstance(keys, str):
sequence = keys
# If the sequence is a single character, attempt to process it as a
# key.
if len(sequence) == 1:
try:
if not sequence.isalnum():
name = _character_to_key(sequence)
Expand Down