keyboard.py
Sub-module providing ‘keyboard awareness’.
- class Keystroke(ucs: str = '', code: int | None = None, name: str | None = None, mode: int | None = None, match: Any = None)[source]
A unicode-derived class for describing a single “keystroke”.
A class instance describes a single keystroke received on input, which may contain multiple characters as a multibyte sequence, which is indicated by properties
is_sequencereturningTrue. Note that keystrokes may also represent mouse input, bracketed paste, or focus in/out events depending on enabled terminal modes.The string
nameof the sequence is used to identify in code logic, such as'KEY_LEFT'to represent a common and human-readable form of the Keystroke this class instance represents.Class constructor.
- static __new__(cls: Type[_T], ucs: str = '', code: int | None = None, name: str | None = None, mode: int | None = None, match: Any = None) _T[source]
Class constructor.
- static _infer_modifiers(ucs: str, mode: int | None, match: Any) int[source]
Infer modifiers from keystroke data.
Returns modifiers in standard format: 1 + bitwise OR of modifier flags.
- _get_modified_keycode_name() str | None[source]
Get base name for modern/legacy CSI sequence with modifiers.
Returns name like ‘KEY_CTRL_ALT_F1’ or ‘KEY_SHIFT_UP’ without event-type suffix. The suffix is applied by
name.
- _get_kitty_protocol_name() str | None[source]
Get base name for Kitty keyboard protocol letter/digit/symbol.
Returns name like ‘KEY_CTRL_ALT_A’, ‘KEY_ALT_SHIFT_5’, ‘KEY_LEFT_SQUARE_BRACKET’ without event-type suffix. The suffix is applied by
name.
- _get_control_char_name() str | None[source]
Get name for single-character control sequences.
Returns name like ‘KEY_CTRL_A’ or ‘KEY_CTRL_SPACE’.
- _get_control_symbol(char_code: int) str[source]
Get control symbol for a character code.
Returns symbol like ‘A’ for Ctrl+A, ‘SPACE’ for Ctrl+Space, ‘BACKSPACE’ for Ctrl+H, etc.
- _get_alt_only_control_name(char_code: int) str | None[source]
Get name for Alt-only special control characters.
Returns names like ‘KEY_ALT_ESCAPE’, ‘KEY_ALT_BACKSPACE’, etc.
- _get_meta_escape_name() str | None[source]
Get name for metaSendsEscape sequences (ESC + char).
Returns name like ‘KEY_ALT_A’, ‘KEY_ALT_SHIFT_Z’, ‘KEY_CTRL_ALT_C’, or ‘KEY_ALT_ESCAPE’.
- _get_mouse_event_name() str | None[source]
Get name for mouse events.
Returns name like ‘MOUSE_LEFT’, ‘MOUSE_CTRL_LEFT’, ‘MOUSE_SCROLL_UP’, ‘MOUSE_LEFT_RELEASED’, ‘MOUSE_MOTION’, ‘MOUSE_RIGHT_MOTION’, etc.
- _get_focus_event_name() str | None[source]
Get name for focus events.
Returns ‘FOCUS_IN’ or ‘FOCUS_OUT’.
- _get_bracketed_paste_name() str | None[source]
Get name for bracketed paste events.
Returns ‘BRACKETED_PASTE’.
- _resolve_name() str | None[source]
Resolve key name without event-type suffix.
Shared by
nameandkey_name. The two keyboard protocol helpers (_get_modified_keycode_name, _get_kitty_protocol_name) return the base name only;nameappends the suffix.
- property name: str | None
Special application key name.
This is the best equality attribute to use for special keys, as raw string value of the ‘F1’ key can be received in many different values.
The ‘name’ property will return a reliable constant, eg.
'KEY_F1'.The name supports “modifiers”, such as
'KEY_CTRL_F1','KEY_CTRL_ALT_F1','KEY_CTRL_ALT_SHIFT_F1'When using a keyboard protocol with event reporting, names include an event-type suffix:
'KEY_CTRL_J_REPEATED'for repeat and'KEY_CTRL_J_RELEASED'for release events. Press events have no suffix. Seekey_namefor the same name without the suffix.For mouse events, the name includes the
'MOUSE_'prefix followed by the button/action name, such as'MOUSE_LEFT','MOUSE_MOTION','MOUSE_RIGHT_MOTION','MOUSE_LEFT_RELEASED'.For other DEC events:
Focus events: ‘FOCUS_IN’ or ‘FOCUS_OUT’
Bracketed paste: ‘BRACKETED_PASTE’
Resize events: ‘RESIZE_EVENT’
For terminal query responses:
Cursor position report: ‘CPR_RESPONSE’ (row >= 2 only; row 1 is ambiguous with F3+modifier)
When non-None, all phrases begin with either ‘KEY’, ‘MOUSE’, ‘FOCUS_IN’, ‘FOCUS_OUT’, ‘BRACKETED_PASTE’, or ‘RESIZE_EVENT’, with one exception: ‘CSI’ is returned for ‘\x1b[’ in legacy (non-kitty-protocol) mode to indicate the beginning of a presumed unsupported input sequence. In kitty keyboard protocol mode, the ‘[’ key uses the name ‘KEY_LEFT_SQUARE_BRACKET’ (with modifier and event-type suffixes as appropriate).
If this value is None, then it can probably be assumed that the value is an unsurprising textual character without any modifiers, like the letter
'a'.
- property key_name: str | None
Key identity without event-type suffix.
Like
name, but without_RELEASEDand_REPEATEDsuffixes, so that press, repeat, and release events for the same key all return the same value. Useful for key-map lookups when tracking press/release pairs.- Return type:
str or None
- property modifiers: int
Modifier flags in standard keyboard protocol format.
- Return type:
- Returns:
Standard-style modifiers value (1 means no modifiers)
The value is 1 + bitwise OR of modifier flags:
shift: 0b1 (1)
alt: 0b10 (2)
ctrl: 0b100 (4)
super: 0b1000 (8)
hyper: 0b10000 (16)
meta: 0b100000 (32)
caps_lock: 0b1000000 (64)
num_lock: 0b10000000 (128)
- property modifiers_bits: int
Raw modifier bit flags without the +1 offset.
- Return type:
- Returns:
Raw bitwise OR of modifier flags (0 means no modifiers)
- property uses_keyboard_protocol: bool
Whether this keystroke uses a special keyboard protocol mode.
Returns True for Kitty, ModifyOtherKeys, or LegacyCSIModifier protocols, which use negative mode values (SpecialInternalKitty=-1, SpecialInternalModifyOtherKeys=-2, SpecialInternalLegacyCSIModifier=-3).
- Return type:
- Returns:
True if using special keyboard protocol mode
- property pressed: bool
Whether this is a key press event.
- Return type:
- Returns:
True if this is a key press event (event_type=1 or not specified), False for repeat or release events
- property repeated: bool
Whether this is a key repeat event.
- Return type:
- Returns:
True if this is a key repeat event (event_type=2), False otherwise
- property released: bool
Whether this is a key release event.
- Return type:
- Returns:
True if this is a key release event (event_type=3), False otherwise
- _is_escape_sequence(length: int = 2) bool[source]
Check if keystroke is an escape sequence of given length.
- static _make_expected_bits(tokens_modifiers: List[str]) int[source]
Build expected modifier bits from token list.
- static _get_keycode_by_name(key_name: str) int | None[source]
Get keycode value for a given key name.
- _build_appkeys_predicate(tokens_modifiers: List[str], key_name: str, event_type: str | None = None) Callable[[str | None, bool], bool][source]
Build a predicate function for application keys.
- _build_alphanum_predicate(tokens_modifiers: List[str]) Callable[[str | None, bool], bool][source]
Build a predicate function for modifier checking of alphanumeric input.
- _get_plain_char_value() str | None[source]
Get value for plain printable characters.
Returns the character as-is if it’s a single printable character.
- _get_escape_sequence_value() str | None[source]
Get value for ESC+char sequences (Alt, Ctrl+Alt combinations).
Handles Alt+printable, Alt-only special keys, and Ctrl+Alt sequences. Returns the base character or empty string for application keys.
- _get_ctrl_sequence_value() str | None[source]
Get value for Ctrl+char sequences.
Maps control characters back to their base characters.
- _get_protocol_value() str | None[source]
Get value for Kitty or ModifyOtherKeys protocol sequences.
Extracts the character from modern keyboard protocols.
- property value: str
The textual character represented by this keystroke.
- Return type:
- Returns:
For text keys, returns the base character (ignoring modifiers). For application keys and sequences, returns empty string ‘’. For release events, always returns empty string.
Some Examples,
Plain text: ‘a’, ‘A’, ‘1’, ‘;’, ‘ ‘, ‘Ω’, emoji with ZWJ sequences
Alt+printable: Alt+a -> ‘a’, Alt+A -> ‘A’
Ctrl+letter: Ctrl+A -> ‘a’, Ctrl+Z -> ‘z’
Ctrl+symbol: Ctrl+@ -> ‘@’, Ctrl+? -> ‘?’, Ctrl+[ → ‘[’
Control chars: ‘t’, ‘n’, ‘x08’, ‘x1b’ (for Enter/Tab/Backspace/Escape keycodes)
Application keys: KEY_UP, KEY_F1, etc. → ‘’
Release events: always -> ‘’
- property key_value: str
Character for this key, even for release events.
Like
value, but does not suppress the character for release events. For press and repeat events, identical tovalue.- Return type:
- property mode: DecPrivateMode | None
DEC Private Mode associated with this keystroke, if any.
- Return type:
blessed.dec_modes.DecPrivateMode or None
- Returns:
The
DecPrivateModeenum value associated with this keystroke, orNoneif this is not a DEC mode event.
Note
Mode names beginning SpecialInternal with negative values (-1, -2, -3) are used to track how some kinds of application keys are matched.
- property mouse_yx: Tuple[int, int]
Mouse position as (y, x) tuple for mouse events.
This is particularly useful with terminal movement functions:
term.move_yx(*keystroke.mouse_yx)
- property text: str | None
Pasted text for bracketed paste events.
- Return type:
str or None
- Returns:
The pasted text for
BRACKETED_PASTEevents, orNoneif not a bracketed paste event
- property _mode_values: BracketedPasteEvent | MouseEvent | FocusEvent | ResizeEvent | None
Return structured data for DEC private mode events (private API).
Returns a namedtuple with parsed event data for supported
DecPrivateModemodes:BRACKETED_PASTE:BracketedPasteEventwithtextfieldMOUSE_EXTENDED_SGR,MOUSE_ALL_MOTION,MOUSE_REPORT_DRAG, andMOUSE_REPORT_CLICKevents:MouseEventwith button, coordinates, and modifier flagsFOCUS_IN_OUT_EVENTS:FocusEventwithgainedboolean fieldIN_BAND_WINDOW_RESIZE:ResizeEventwith dimension fields
- Return type:
namedtuple or None
- Returns:
Structured event data for this DEC mode event, or
Noneif this keystroke is not a DEC mode event or the mode is not supported
- _parse_focus() FocusEvent[source]
Parse focus event from stored regex match.
- _parse_bracketed_paste() BracketedPasteEvent[source]
Parse bracketed paste event from stored regex match.
- get_keyboard_codes() Dict[int, str][source]
Return mapping of keycode integer values paired by their curses key name.
- Return type:
- Returns:
Dictionary of (code, name) pairs for curses keyboard constant values and their mnemonic name. Such as key
260, with the value of its identity,'KEY_LEFT'.
These keys are derived from the attributes by the same of the curses(jinxed) module, with the following exceptions:
KEY_DELETEin place ofKEY_DCKEY_INSERTin place ofKEY_ICKEY_PGUPin place ofKEY_PPAGEKEY_PGDOWNin place ofKEY_NPAGEKEY_ESCAPEin place ofKEY_EXITKEY_SUPin place ofKEY_SRKEY_SDOWNin place ofKEY_SF
This function is the inverse of
get_curses_keycodes(). With the given override “mixins” listed above, the keycode for the delete key will map to our imaginaryKEY_DELETEmnemonic, effectively erasing the phraseKEY_DCfrom our code vocabulary for anyone that wishes to use the return value to determine the key-name by keycode.
- get_keyboard_sequences(term: Terminal) OrderedDict[str, int][source]
Return mapping of keyboard sequences paired by keycodes.
- Parameters:
term (blessed.Terminal) –
Terminalinstance.- Returns:
mapping of keyboard unicode sequences paired by keycodes as integer. This is used as the argument
mapperto the supporting functionresolve_sequence().- Return type:
OrderedDict
Initialize and return a keyboard map and sequence lookup table, (sequence, keycode) from
Terminalinstanceterm, wheresequenceis a multibyte input sequence of unicode characters, such as'\x1b[D', andkeycodeis an integer value, matching curses constant such as term.KEY_LEFT.The return value is an OrderedDict instance, with their keys sorted longest-first.
- class KittyKeyEvent(unicode_key, shifted_key, base_key, modifiers, event_type, int_codepoints)
Create new instance of KittyKeyEvent(unicode_key, shifted_key, base_key, modifiers, event_type, int_codepoints)
- static __new__(_cls, unicode_key, shifted_key, base_key, modifiers, event_type, int_codepoints)
Create new instance of KittyKeyEvent(unicode_key, shifted_key, base_key, modifiers, event_type, int_codepoints)
- _asdict()
Return a new dict which maps field names to their values.
- _field_defaults = {}
- _fields = ('unicode_key', 'shifted_key', 'base_key', 'modifiers', 'event_type', 'int_codepoints')
- classmethod _make(iterable)
Make a new KittyKeyEvent object from a sequence or iterable
- _replace(**kwds)
Return a new KittyKeyEvent object replacing specified fields with new values
- base_key
Alias for field number 2
- event_type
Alias for field number 4
- int_codepoints
Alias for field number 5
- modifiers
Alias for field number 3
- shifted_key
Alias for field number 1
- unicode_key
Alias for field number 0
- class ModifyOtherKeysEvent(key, modifiers)
Create new instance of ModifyOtherKeysEvent(key, modifiers)
- static __new__(_cls, key, modifiers)
Create new instance of ModifyOtherKeysEvent(key, modifiers)
- _asdict()
Return a new dict which maps field names to their values.
- _field_defaults = {}
- _fields = ('key', 'modifiers')
- classmethod _make(iterable)
Make a new ModifyOtherKeysEvent object from a sequence or iterable
- _replace(**kwds)
Return a new ModifyOtherKeysEvent object replacing specified fields with new values
- key
Alias for field number 0
- modifiers
Alias for field number 1
- class LegacyCSIKeyEvent(kind, key_id, modifiers, event_type)
Create new instance of LegacyCSIKeyEvent(kind, key_id, modifiers, event_type)
- static __new__(_cls, kind, key_id, modifiers, event_type)
Create new instance of LegacyCSIKeyEvent(kind, key_id, modifiers, event_type)
- _asdict()
Return a new dict which maps field names to their values.
- _field_defaults = {}
- _fields = ('kind', 'key_id', 'modifiers', 'event_type')
- classmethod _make(iterable)
Make a new LegacyCSIKeyEvent object from a sequence or iterable
- _replace(**kwds)
Return a new LegacyCSIKeyEvent object replacing specified fields with new values
- event_type
Alias for field number 3
- key_id
Alias for field number 1
- kind
Alias for field number 0
- modifiers
Alias for field number 2
- class KittyKeyboardProtocol(value: int)[source]
Represents Kitty keyboard protocol flags.
Encapsulates the integer flag value returned by Kitty keyboard protocol queries and provides properties for individual flag bits and a method to convert back to enable_kitty_keyboard() arguments.
Initialize with raw integer flag value.
- Parameters:
value (int) – Raw integer flags value from Kitty keyboard protocol query
- class DeviceAttribute(raw: str, service_class: int, extensions: List[int] | None)[source]
Represents a terminal’s Device Attributes (DA1) response.
Device Attributes queries allow discovering terminal capabilities and type. The primary DA1 query sends CSI c and expects a response like:
CSI ? Psc ; Ps1 ; Ps2 ; ... ; Psn c
Where Psc is the service class (architectural class) and Ps1…Psn are supported extensions/capabilities.
Initialize DeviceAttribute instance.
- Parameters:
- RE_RESPONSE = re.compile('\\x1b\\[\\?([0-9]+)((?:;[0-9]+)*)c')
- property supports_sixel: bool
Whether the terminal supports sixel graphics.
- Return type:
- Returns:
True if extension 4 (sixel) is present in device attributes
- property supports_osc52: bool
Whether the terminal advertises OSC 52 clipboard support.
Extension 52 in DA1 indicates the terminal supports writing to the system clipboard via the OSC 52 protocol.
- Return type:
- Returns:
True if extension 52 is present in device attributes
- class SoftwareVersion(raw: str, name: str, version: str)[source]
Represents a terminal’s software name and version from XTVERSION response.
Initialize SoftwareVersion instance.
- Parameters:
- RE_RESPONSE = re.compile('\\x1bP>\\|(.+?)\\x1b\\\\')
- classmethod from_match(match: Match[str]) SoftwareVersion[source]
Create SoftwareVersion from regex match object.
- Parameters:
match (re.Match) – Regex match object with group for software text
- Return type:
- Returns:
SoftwareVersion instance parsed from match
- static _parse_text(text: str) Tuple[str, str][source]
Parse software name and version from text.
Parsing logic (in order): 1. Check for space-separated format: “tmux 3.2a” or “X.Org 7.7.0(370)” 2. Check for parentheses format: “kitty(0.24.2)” 3. Name-only format: “software” (version is empty string)
- class BracketedPasteEvent(text)
Create new instance of BracketedPasteEvent(text,)
- static __new__(_cls, text)
Create new instance of BracketedPasteEvent(text,)
- _asdict()
Return a new dict which maps field names to their values.
- _field_defaults = {}
- _fields = ('text',)
- classmethod _make(iterable)
Make a new BracketedPasteEvent object from a sequence or iterable
- _replace(**kwds)
Return a new BracketedPasteEvent object replacing specified fields with new values
- text
Alias for field number 0
- class FocusEvent(gained)
Create new instance of FocusEvent(gained,)
- static __new__(_cls, gained)
Create new instance of FocusEvent(gained,)
- _asdict()
Return a new dict which maps field names to their values.
- _field_defaults = {}
- _fields = ('gained',)
- classmethod _make(iterable)
Make a new FocusEvent object from a sequence or iterable
- _replace(**kwds)
Return a new FocusEvent object replacing specified fields with new values
- gained
Alias for field number 0
- class SyncEvent(begin)
Create new instance of SyncEvent(begin,)
- static __new__(_cls, begin)
Create new instance of SyncEvent(begin,)
- _asdict()
Return a new dict which maps field names to their values.
- _field_defaults = {}
- _fields = ('begin',)
- classmethod _make(iterable)
Make a new SyncEvent object from a sequence or iterable
- _replace(**kwds)
Return a new SyncEvent object replacing specified fields with new values
- begin
Alias for field number 0
- DEFAULT_SEQUENCE_MIXIN = (('\n', 343), ('\r', 343), ('\x08', 263), ('\t', 512), ('\x1b', 361), ('\x7f', 263), ('\x1b[A', 259), ('\x1b[B', 258), ('\x1b[C', 261), ('\x1b[D', 260), ('\x1b[E', 350), ('\x1b[1;2A', 337), ('\x1b[1;2B', 336), ('\x1b[1;2C', 402), ('\x1b[1;2D', 393), ('\x1b[F', 360), ('\x1b[H', 262), ('\x1b[K', 360), ('\x1b[U', 338), ('\x1b[V', 339), ('\x1bOM', 343), ('\x1bOj', 513), ('\x1bOk', 514), ('\x1bOl', 515), ('\x1bOm', 516), ('\x1bOn', 517), ('\x1bOo', 518), ('\x1bOX', 519), ('\x1bOp', 520), ('\x1bOq', 521), ('\x1bOr', 522), ('\x1bOs', 523), ('\x1bOt', 524), ('\x1bOu', 525), ('\x1bOv', 526), ('\x1bOw', 527), ('\x1bOx', 528), ('\x1bOy', 529), ('\x1b[1~', 262), ('\x1b[2~', 331), ('\x1b[3~', 330), ('\x1b[4~', 360), ('\x1b[5~', 339), ('\x1b[6~', 338), ('\x1b[7~', 262), ('\x1b[8~', 360), ('\x1b[OA', 259), ('\x1b[OB', 258), ('\x1b[OC', 261), ('\x1b[OD', 260), ('\x1b[OF', 360), ('\x1b[OH', 262), ('\x1bOP', 265), ('\x1bOQ', 266), ('\x1bOR', 267), ('\x1bOS', 268), ('\x1b[P', 265), ('\x1b[Q', 266), ('\x1b[13~', 267), ('\x1b[S', 268))
In a perfect world, terminal emulators would always send exactly what the terminfo(5) capability database plans for them, accordingly by the value of the
TERMname they declare.But this isn’t a perfect world. Many vt220-derived terminals, such as those declaring ‘xterm’, will continue to send vt220 codes instead of their native-declared codes, for backwards-compatibility.
This goes for many: rxvt, putty, iTerm.
These “mixins” are used for all terminals, regardless of their type.
Furthermore, curses does not provide sequences sent by the keypad, at least, it does not provide a way to distinguish between keypad 0 and numeric 0.
- CURSES_KEYCODE_OVERRIDE_MIXIN = (('KEY_DELETE', 330), ('KEY_INSERT', 331), ('KEY_PGUP', 339), ('KEY_PGDOWN', 338), ('KEY_ESCAPE', 361), ('KEY_SUP', 337), ('KEY_SDOWN', 336), ('KEY_UP_LEFT', 348), ('KEY_UP_RIGHT', 349), ('KEY_CENTER', 350), ('KEY_BEGIN', 354), ('KEY_DOWN_LEFT', 351), ('KEY_DOWN_RIGHT', 352))
Override mixins for a few curses constants with easier mnemonics: there may only be a 1:1 mapping when only a keycode (int) is given, where these phrases are preferred.