struct Tput::KeyEvent

Overview

A single, normalized key event — the keyboard counterpart of Tput::Mouse::Event.

The legacy parser (Tput::Key.read_control) collapses every keystroke into a flat Key enum value, which can't carry a modifier bitmask, a key release, auto-repeat, or a lone modifier press. When the terminal speaks an enhanced keyboard protocol (kitty, or xterm modifyOtherKeys), Tput::Input#listen parses those into a KeyEvent alongside the legacy Key.

The encodings understood (all re-parsed from the raw sequence by Input#parse_key_event):

Defined in:

tput/key_event.cr

Constant Summary

KEYPAD = 57399..57427

kitty functional key codes for the numeric keypad, KP_0 (57399) through KP_BEGIN (57427). Under the kitty protocol the keypad reports these; Input#listen gives an application-keypad (DECKPAM) key the same code (.from_ss3_keypad), so #keypad? tells a keypad key apart whichever way it arrived, as Qt marks one with Qt::KeypadModifier.

MODIFIER_KEYS = {57441 => :left_shift, 57442 => :left_control, 57443 => :left_alt, 57444 => :left_super, 57445 => :left_hyper, 57446 => :left_meta, 57447 => :right_shift, 57448 => :right_control, 57449 => :right_alt, 57450 => :right_super, 57451 => :right_hyper, 57452 => :right_meta}

kitty functional key codes for the standalone modifier keys. A u-final event whose #number is one of these is a lone modifier press/release — the basis for gestures like "tap Alt" (see #modifier_key).

SS3_KEYPAD = {'M' => 57414, 'X' => 57415, 'j' => 57411, 'k' => 57413, 'l' => 57416, 'm' => 57412, 'n' => 57409, 'o' => 57410, 'p' => 57399, 'q' => 57400, 'r' => 57401, 's' => 57402, 't' => 57403, 'u' => 57404, 'v' => 57405, 'w' => 57406, 'x' => 57407, 'y' => 57408}

kitty's keypad code for the final byte of an application-keypad SS3 sequence (\eO + final), after xterm's table.

Constructors

Class Method Summary

Instance Method Summary

Constructor Detail

def self.from_csi(final : Char, g0_0 : Int32 | Nil, g0_1 : Int32 | Nil, g0_2 : Int32 | Nil, g1_0 : Int32 | Nil, g1_1 : Int32 | Nil, g2 : Array(Int32 | Nil) | Nil) : KeyEvent #

Builds a KeyEvent from the parsed CSI sub-parameters and the final byte: first three sub-params of group 0 (number : shifted : base), first two of group 1 (mods : event), group 2 in full (associated-text codepoints). See Input#parse_key_event.


[View source]
def self.new(number : Int32, final : Char, mods : Tput::Modifiers = Modifiers::None, type : Tput::KeyEvent::Type = Type::Press, shifted : Int32 | Nil = nil, base : Int32 | Nil = nil, text : Nil | String = nil) #

[View source]

Class Method Detail

def self.from_ss3_keypad(final : Char) : KeyEvent | Nil #

The event for an application-keypad key, \eO followed by final (M for Enter, p for 0, …): a press of kitty's code for that key, or nil for a final that is no keypad key.


[View source]

Instance Method Detail

def alt? : Bool #

[View source]
def base : Int32 | Nil #

[View source]
def char : Char | Nil #

The printable character this key would produce, for press/repeat events with no control-style modifier held — so plain typing keeps flowing through Input#listen's #char argument even under an enhanced protocol. nil for releases, control combos, and non-text keys.

Prefers the terminal-supplied associated text (handles layouts, caps lock, dead keys); else the shifted codepoint when Shift is held and reported (Shift+a → A), else the base codepoint.


[View source]
def codepoint : Int32 #

The Unicode codepoint for u-final events. Meaningless for legacy-final forms (where #number is a CSI parameter).


[View source]
def ctrl? : Bool #

[View source]
def final : Char #

The CSI final byte of the originating sequence ('u', '~', or a cursor letter such as 'A'). Together with #number it determines the key.


[View source]
def hyper? : Bool #

[View source]
def keypad? : Bool #

Whether this is a numeric-keypad key (kitty's KP_* codes), Qt's Qt::KeypadModifier. Widgets mostly treat it as the key it stands for (#main_key): the keypad's Enter as Return, its digits as digits.


[View source]
def main_key : KeyEvent | Nil #

For a keypad key, the main-keyboard key it stands for, with the same modifiers, type and text: Enter for KP_ENTER, the character for the digits and operators, the cursor and editing keys for the keypad's navigation keys (NumLock off). nil for any other key, and for KP_BEGIN (the keypad's 5 with NumLock off), which stands for none.


[View source]
def meta? : Bool #

[View source]
def modifier_key : Symbol | Nil #

Which standalone modifier key this is (:left_alt, :right_ctrl, …), or nil if not a lone modifier. A #release? of one of these is the "modifier tapped" gesture.


[View source]
def modifier_key? : Bool #

Whether this event is a standalone modifier key press (Left/Right Shift, Ctrl, Alt, Super, Hyper, Meta) — only reported under kitty's report all keys flag.


[View source]
def mods : Modifiers #

The active modifiers.


[View source]
def number : Int32 #

The primary key number from the sequence. For a u-final (kitty/ modifyOtherKeys-1) event this is the Unicode codepoint or kitty functional key code; for legacy-final forms it's the legacy CSI parameter (#final identifies the key instead).


[View source]
def press? : Bool #

[View source]
def release? : Bool #

[View source]
def repeat? : Bool #

[View source]
def shift? : Bool #

[View source]
def shifted : Int32 | Nil #

kitty alternate keys: shifted and base-layout codepoints, when reported (report alternate keys flag). nil otherwise.


[View source]
def super? : Bool #

[View source]
def text : String | Nil #

kitty associated text: the text the key would produce, when reported (report associated text flag). nil otherwise.


[View source]
def to_legacy_bytes : String | Nil #

Re-encodes this event as the legacy byte sequence a terminal with no enhanced protocol active would have sent — what a child process that never negotiated kitty/modifyOtherKeys expects on its tty: Ctrl+C → 0x03, Esc → "\e", Alt+x → "\ex", nav/function keys → their legacy CSI/SS3 forms, plain text → the character itself. Used by embedded terminals to forward host keystrokes to a legacy-mode child.

Returns nil when a legacy terminal would have sent nothing: releases, lone modifier presses, and functional keys with no legacy encoding (kitty Private-Use-Area codes such as media keys). A keypad key sends what the key it stands for sends (#main_key), as the keypad does in a legacy terminal's numeric keypad mode.


[View source]
def to_legacy_key : Key | Nil #

Projects this event back onto the flat Key enum, for consumers that only understand legacy keys. Returns nil when there's no legacy equivalent (a plain printable key — use #char — a lone modifier, or an unexpressable combination).

Releases return nil deliberately, so a legacy consumer never mistakes a release for a press. Auto-repeats do project.


[View source]
def type : Type #

Press / repeat / release.


[View source]