### Example: Using key! in a match expression Source: https://docs.rs/terminput/latest/terminput/macro.key.html Complete example from the docs showing how to use `key!` to match key press events with various modifiers and event state. It handles `'a'`, `'ctrl+d'`/`'alt+d'`, `'ctrl+alt+c'`, and `'d'` with caps lock. ```rust use terminput::KeyCode::*; use terminput::{ALT, CTRL, Event, KeyModifiers, Repeats, key, modifiers}; fn handle_event(event: Event) { if let Some(key_event) = event.as_key_press(Repeats::Include) { const CTRL_ALT: KeyModifiers = modifiers!(CTRL, ALT); match key_event { key!(Char('a')) => { println!("'a' pressed"); } key!(CTRL | ALT, Char('d')) => { println!("'ctrl+d' or 'alt+d' pressed"); } key!(CTRL_ALT, Char('c')) => { println!("'ctrl+alt+c' pressed"); } key!(CAPS_LOCK, KeyModifiers::NONE, Char('d')) => { println!("'d' pressed with caps lock"); } _ => {} } } } ``` -------------------------------- ### states! macro usage example Source: https://docs.rs/terminput/latest/src/terminput/key.rs.html?search=std%3A%3Avec Shows how to use the states! macro to combine key states in a const context. ```rust use terminput::{CAPS_LOCK, KeyEventState, NUM_LOCK, states}; const key_state: KeyEventState = states!(CAPS_LOCK, NUM_LOCK); assert_eq!(key_state, CAPS_LOCK | NUM_LOCK); ``` -------------------------------- ### key! macro usage example Source: https://docs.rs/terminput/latest/src/terminput/key.rs.html?search=std%3A%3Avec Shows how to use the key! macro to match KeyEvent patterns in a match expression, including combinations of modifiers and states. ```rust fn handle_event(event: Event) { if let Some(key_event) = event.as_key_press(Repeats::Include) { const CTRL_ALT: KeyModifiers = modifiers!(CTRL, ALT); match key_event { key!(Char('a')) => { println!("'a' pressed"); } key!(CTRL | ALT, Char('d')) => { println!("'ctrl+d' or 'alt+d' pressed"); } key!(CTRL_ALT, Char('c')) => { println!("'ctrl+alt+c' pressed"); } key!(CAPS_LOCK, KeyModifiers::NONE, Char('d')) => { println!("'d' pressed with caps lock"); } _ => {} } } } ``` -------------------------------- ### modifiers! macro usage example Source: https://docs.rs/terminput/latest/src/terminput/key.rs.html?search=std%3A%3Avec Shows how to use the modifiers! macro to combine key modifiers in a const context. ```rust use terminput::{ALT, CTRL, KeyModifiers, modifiers}; const mods: KeyModifiers = modifiers!(CTRL, ALT); assert_eq!(mods, CTRL | ALT); ``` -------------------------------- ### terminput lib.rs module setup and imports Source: https://docs.rs/terminput/latest/src/terminput/lib.rs.html?search=std%3A%3Avec Sets up the crate with no_std, denies unwrap usage, and conditionally includes std-dependent modules. The encoder and parser modules are only compiled with the 'std' feature. ```rust #![no_std] #![deny(clippy::unwrap_used)] #![warn(missing_docs, missing_debug_implementations)] #![cfg_attr(docsrs, feature(doc_cfg))] #![doc = include_str!("../README.md")] extern crate alloc; #[cfg(feature = "std")] extern crate std; #[cfg(feature = "std")] mod encoder; mod key; mod mouse; #[cfg(feature = "std")] mod parser; use alloc::string::String; use core::error::Error; use core::fmt; #[cfg(feature = "std")] pub use encoder::*; pub use key::*; pub use mouse::*; ``` -------------------------------- ### Encode events with Event::encode using legacy and Kitty encoding Source: https://docs.rs/terminput/latest/terminput Encodes a sample KeyEvent into an ANSI escape sequence using Event::encode with both the legacy Xterm encoding and the Kitty encoding. The example writes into a fixed-size buffer and prints the encoded bytes. ```text use terminput::{Encoding, Event, KeyCode, KeyEvent, KittyFlags}; let event = Event::Key(KeyEvent::new(KeyCode::Char('a'))); let mut buf = [0; 16]; // Legacy encoding let written = event.encode(&mut buf, Encoding::Xterm); if let Ok(written) = written { println!("Encoded: {:?}", &buf[..written]); } // Kitty encoding let mut buf = [0; 16]; let written = event.encode(&mut buf, Encoding::Kitty(KittyFlags::all())); if let Ok(written) = written { println!("Encoded: {:?}", &buf[..written]); } ``` -------------------------------- ### Convert between crossterm and terminput events Source: https://docs.rs/terminput/latest/index.html Shows how to use the conversion methods from terminput-crossterm to convert a crossterm event to a terminput Event and back. The example reads an event with crossterm::event::read, converts it with to_terminput, prints it, and then converts back with to_crossterm if the first conversion succeeded. ```rust use crossterm::event::read; use std::io; use terminput::Event; use terminput_crossterm::{to_crossterm, to_terminput}; fn main() -> io::Result<()> { let crossterm_event = read()?; let event: Result = to_terminput(crossterm_event); println!("{event:?}"); if let Ok(event) = event { // Conversions work both ways let event2: Result = to_crossterm(event); println!("{event2:?}"); } Ok(()) } ``` -------------------------------- ### Encode key event with Kitty protocol (partial) Source: https://docs.rs/terminput/latest/src/terminput/encoder.rs.html?search=u32+-%3E+bool Starts the Kitty keyboard protocol encoding for a key event. It checks for KEYPAD state and writes the private-use-area codes for CapsLock (57358) and ScrollLock (57359). The snippet is truncated in the source; the full function continues with additional key code handling. ```rust fn write_kitty_encoding( key_event: KeyEvent, flags: KittyFlags, buf: &mut Cursor<&mut [u8]>, ) -> io::Result<()> { let is_keypad = key_event.state.intersects(KeyEventState::KEYPAD); match key_event.code { KeyCode::CapsLock => { buf.write_all(b"57358")?; } KeyCode::ScrollLock => { buf.write_all(b"57359")?; } ``` -------------------------------- ### Encode events to ANSI escape sequences with Event::encode Source: https://docs.rs/terminput/latest/index.html Shows how to encode a terminput Event into ANSI escape sequences using Event::encode. The example creates a key event for 'a' and encodes it with both legacy (Encoding::Xterm) and Kitty (Encoding::Kitty with all flags) encodings, printing the encoded bytes. Useful for controlling a child pty. ```rust use terminput::{Encoding, Event, KeyCode, KeyEvent, KittyFlags}; let event = Event::Key(KeyEvent::new(KeyCode::Char('a'))); let mut buf = [0; 16]; // Legacy encoding let written = event.encode(&mut buf, Encoding::Xterm); if let Ok(written) = written { println!("Encoded: {:?}", &buf[..written]); } // Kitty encoding let mut buf = [0; 16]; let written = event.encode(&mut buf, Encoding::Kitty(KittyFlags::all())); if let Ok(written) = written { println!("Encoded: {:?}", &buf[..written]); } ``` -------------------------------- ### KeyEventState::from_name Source: https://docs.rs/terminput/latest/terminput/struct.KeyEventState.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Gets a flags value with the bits of a flag with the given name set. ```APIDOC ## KeyEventState::from_name ### Description Get a flags value with the bits of a flag with the given name set. This method will return `None` if `name` is empty or doesn’t correspond to any named flag. ### Method `pub fn from_name(name: &str) -> Option` ### Parameters - `name` (&str) - Required - The name of the flag. ### Returns - `Option` - `Some(KeyEventState)` if the name corresponds to a named flag, otherwise `None`. ``` -------------------------------- ### ScrollDirection Source: https://docs.rs/terminput/latest/src/terminput/mouse.rs.html?search= Enum representing the direction of a mouse scroll event, with a method to get the corresponding scroll delta. ```APIDOC ## ScrollDirection ### Description Represents the direction of a mouse scroll event. ### Variants - **Up** - Scrolled mouse wheel upwards (away from the user). - **Down** - Scrolled mouse wheel downwards (towards the user). - **Left** - Scrolled mouse wheel left (usually on a laptop touchpad). - **Right** - Scrolled mouse wheel right (usually on a laptop touchpad). ### Methods - **delta** (self) -> ScrollDelta - Convenience method for applying a change in the vertical or horizontal direction in response to a scroll event. Returns a ScrollDelta with x and y values: Up (0, 1), Down (0, -1), Left (1, 0), Right (-1, 0). ``` -------------------------------- ### Implement From conversions for KeyEvent Source: https://docs.rs/terminput/latest/src/terminput/key.rs.html?search=u32+-%3E+bool Implements From conversions to create a KeyEvent from a KeyCode and an Event from a KeyEvent. ```rust impl From for KeyEvent { fn from(code: KeyCode) -> Self { Self { code, modifiers: KeyModifiers::empty(), kind: KeyEventKind::Press, state: KeyEventState::empty(), } } } impl From for Event { fn from(value: KeyEvent) -> Self { Self::Key(value) } } ``` -------------------------------- ### KeyEventState::all Source: https://docs.rs/terminput/latest/terminput/struct.KeyEventState.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates a KeyEventState with all known bits set. ```APIDOC ## KeyEventState::all ### Description Get a flags value with all known bits set. ### Method `pub const fn all() -> Self` ### Parameters None ### Returns - `Self` - A new `KeyEventState` with all known bits set. ``` -------------------------------- ### impl Flags for KeyModifiers Source: https://docs.rs/terminput/latest/terminput/struct.KeyModifiers.html Provides bitwise flag operations for KeyModifiers, including methods to get, set, test, and iterate over bits. ```APIDOC ## impl Flags for KeyModifiers ### Description Provides bitwise flag operations for KeyModifiers, including methods to get, set, test, and iterate over bits. ### Associated Constants - **FLAGS**: `&'static [Flag]` - The set of defined flags. ### Associated Types - **Bits**: `u8` - The underlying bits type. ### Methods - **bits(&self) -> u8** - Get the underlying bits value. - **from_bits_retain(bits: u8) -> KeyModifiers** - Convert from a bits value exactly. - **all_named() -> KeyModifiers** - Get a flags value with all bits from named flags set. - **empty() -> Self** - Get a flags value with all bits unset. - **all() -> Self** - Get a flags value with all known bits set. - **known_bits(&self) -> Self::Bits** - Get the known bits from a flags value. - **unknown_bits(&self) -> Self::Bits** - Get the unknown bits from a flags value. - **contains_unknown_bits(&self) -> bool** - Returns `true` if any unknown bits are set. - **from_bits(bits: Self::Bits) -> Option** - Convert from a bits value. - **from_bits_truncate(bits: Self::Bits) -> Self** - Convert from a bits value, unsetting any unknown bits. - **from_name(name: &str) -> Option** - Get a flags value with the bits of a flag with the given name set. - **iter(&self) -> Iter** - Yield a set of contained flags values. - **iter_names(&self) -> IterNames** - Yield a set of contained named flags values. - **iter_defined_names() -> IterDefinedNames** - Yield a set of all named flags defined by `Self::FLAGS`. - **iter_equal_names(&self) -> IterEqualNames** - Get an iterator over all defined names for this flags value. - **is_empty(&self) -> bool** - Whether all bits in this flags value are unset. - **is_all(&self) -> bool** - Whether all known bits in this flags value are set. - **intersects(&self, other: Self) -> bool** - Whether any set bits in `other` are also set in `self`. - **contains(&self, other: Self) -> bool** - Whether all set bits in `other` are also set in `self`. - **truncate(&mut self)** - Remove any unknown bits from the flags. - **insert(&mut self, other: Self)** - The bitwise or (`|`) of the bits in `self` and `other`. - **remove(&mut self, other: Self)** - The intersection of `self` with the complement of `other` (`&!`). - **toggle(&mut self, other: Self)** - The bitwise exclusive-or (`^`) of the bits in `self` and `other`. - **set(&mut self, other: Self, value: bool)** - Call `Flags::insert` when `value` is `true` or `Flags::remove` when `value` is `false`. - **clear(&mut self)** - Unsets all bits in the flags. - **intersection(self, other: Self) -> Self** - The bitwise and (`&`) of the bits in `self` and `other`. - **union(self, other: Self) -> Self** - The bitwise or (`|`) of the bits in `self` and `other`. - **difference(self, other: Self) -> Self** - The intersection of `self` with the complement of `other` (`&!`). - **symmetric_difference(self, other: Self) -> Self** - The bitwise exclusive-or (`^`) of the bits in `self` and `other`. - **complement(self) -> Self** - The bitwise negation (`!`) of the bits in `self`, truncating the result. ``` -------------------------------- ### Parse CSI Special Key Code Source: https://docs.rs/terminput/latest/src/terminput/parser/mod.rs.html?search= Parses a CSI special key sequence, expecting a format starting with ESC [ and ending with ~. ```rust pub(crate) fn parse_csi_special_key_code(buffer: &[u8]) -> io::Result> { assert!(buffer.starts_with(b"\x1B[")); // ESC [ assert!(buffer.ends_with(b"~")); let s = std::str::from_utf8(&buffer[2..buffer.len() - 1]) .map_err(|_| could_not_parse_event_error())?; let mut split = s.split(';'); // This CSI sequence can be a list of semicolon-separated numbers. let first = next_parsed::(&mut split)?; let (modifiers, kind, state) = if let Ok((modifier_mask, kind_code)) = modifier_and_kind_parsed(&mut split) { ( parse_modifiers(modifier_mask), parse_key_event_kind(kind_code), ``` -------------------------------- ### KeyEvent::new Source: https://docs.rs/terminput/latest/terminput/struct.KeyEvent.html?search= Creates a new KeyEvent with the default state and no modifiers. ```APIDOC ## KeyEvent::new ### Description Creates a new `KeyEvent` with the default state and no modifiers. ### Signature `pub const fn new(code: KeyCode) -> Self` ### Parameters - **code** (KeyCode) - Required - The key code for the event. ### Returns - **Self** - A new `KeyEvent` instance. ``` -------------------------------- ### KeyEvent::new Source: https://docs.rs/terminput/latest/terminput/struct.KeyEvent.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates a new KeyEvent with the default state and no modifiers. ```APIDOC ## KeyEvent::new ### Description Creates a new `KeyEvent` with the default state and no modifiers. ### Signature ```rust pub const fn new(code: KeyCode) -> Self ``` ### Parameters - **code** (KeyCode) - Required - The key code for the event. ### Returns - **Self** - A new `KeyEvent` instance. ``` -------------------------------- ### KittyFlags Flags Implementation Source: https://docs.rs/terminput/latest/terminput/struct.KittyFlags.html?search=u32+-%3E+bool Methods for manipulating and querying KittyFlags bit flags, including getting bits, checking flags, and performing bitwise operations. ```APIDOC ## KittyFlags Flags Implementation ### Description Provides methods to manipulate and query the KittyFlags bit flags value. ### Methods #### bits(&self) -> u8 Get the underlying bits value. #### from_bits_retain(bits: u8) -> KittyFlags Convert from a bits value exactly. #### all_named() -> KittyFlags Get a flags value with all bits from named flags set. #### empty() -> Self Get a flags value with all bits unset. #### all() -> Self Get a flags value with all known bits set. #### known_bits(&self) -> Self::Bits Get the known bits from a flags value. #### unknown_bits(&self) -> Self::Bits Get the unknown bits from a flags value. #### contains_unknown_bits(&self) -> bool Returns `true` if any unknown bits are set. #### from_bits(bits: Self::Bits) -> Option Convert from a bits value, returning `None` if unknown bits are set. #### from_bits_truncate(bits: Self::Bits) -> Self Convert from a bits value, unsetting any unknown bits. #### from_name(name: &str) -> Option Get a flags value with the bits of a flag with the given name set. #### iter(&self) -> Iter Yield a set of contained flags values. #### iter_names(&self) -> IterNames Yield a set of contained named flags values. #### iter_defined_names() -> IterDefinedNames Yield a set of all named flags defined by `Self::FLAGS`. #### iter_equal_names(&self) -> IterEqualNames Get an iterator over all defined names for this flags value. #### is_empty(&self) -> bool Whether all bits in this flags value are unset. #### is_all(&self) -> bool Whether all known bits in this flags value are set. #### intersects(&self, other: Self) -> bool Whether any set bits in `other` are also set in `self`. #### contains(&self, other: Self) -> bool Whether all set bits in `other` are also set in `self`. #### truncate(&mut self) Remove any unknown bits from the flags. #### insert(&mut self, other: Self) The bitwise or (`|`) of the bits in `self` and `other`. #### remove(&mut self, other: Self) The intersection of `self` with the complement of `other` (`&!`). #### toggle(&mut self, other: Self) The bitwise exclusive-or (`^`) of the bits in `self` and `other`. #### set(&mut self, other: Self, value: bool) Call `Flags::insert` when `value` is `true` or `Flags::remove` when `value` is `false`. #### clear(&mut self) Unsets all bits in the flags. #### intersection(self, other: Self) -> Self The bitwise and (`&`) of the bits in `self` and `other`. #### union(self, other: Self) -> Self The bitwise or (`|`) of the bits in `self` and `other`. #### difference(self, other: Self) -> Self The intersection of `self` with the complement of `other` (`&!`). #### symmetric_difference(self, other: Self) -> Self The bitwise exclusive-or (`^`) of the bits in `self` and `other`. #### complement(self) -> Self The bitwise negation (`!`) of the bits in `self`, truncating the result. ### Associated Constants - **FLAGS**: &'static [Flag] - The set of defined flags. ### Associated Types - **Bits** = u8 - The underlying bits type. ``` -------------------------------- ### Parse CSI modifier key code in Rust Source: https://docs.rs/terminput/latest/src/terminput/parser/mod.rs.html?search= Parses a CSI sequence starting with ESC [ into an Event, extracting modifier and key code. Handles both semicolon-separated and single-digit modifier formats. ```rust pub(crate) fn parse_csi_modifier_key_code(buffer: &[u8]) -> io::Result> { assert!(buffer.starts_with(b"\x1B[")); // ESC [ let s = std::str::from_utf8(&buffer[2..buffer.len() - 1]) .map_err(|_| could_not_parse_event_error())?; let mut split = s.split(';'); split.next(); let (modifiers, kind) = if let Ok((modifier_mask, kind_code)) = modifier_and_kind_parsed(&mut split) { ( parse_modifiers(modifier_mask), parse_key_event_kind(kind_code), ) } else if buffer.len() > 3 { ( parse_modifiers( (buffer[buffer.len() - 2] as char) .to_digit(10) .ok_or_else(could_not_parse_event_error)? as u8, ), KeyEventKind::Press, ) } else { (KeyModifiers::NONE, KeyEventKind::Press) }; let key = buffer[buffer.len() - 1]; let keycode = match key { b'A' => KeyCode::Up, b'B' => KeyCode::Down, b'C' => KeyCode::Right, b'D' => KeyCode::Left, b'F' => KeyCode::End, b'H' => KeyCode::Home, b'P' => KeyCode::F(1), b'Q' => KeyCode::F(2), b'R' => KeyCode::F(3), b'S' => KeyCode::F(4), _ => return Err(could_not_parse_event_error()), }; let input_event = Event::Key(KeyEvent::new(keycode).modifiers(modifiers).kind(kind)); Ok(Some(input_event)) } ``` -------------------------------- ### KeyEvent::new Source: https://docs.rs/terminput/latest/src/terminput/key.rs.html?search=std%3A%3Avec Creates a new KeyEvent with the given key code, default state, and no modifiers. ```APIDOC ## KeyEvent::new ### Description Creates a new `KeyEvent` with the specified key code, default state (empty), and no modifiers. The event kind is set to `Press`. ### Method `pub const fn new(code: KeyCode) -> Self` ### Parameters - **code** (`KeyCode`) - The key code for the event. ### Returns - `KeyEvent` - A new key event with the given code, empty modifiers, `Press` kind, and empty state. ``` -------------------------------- ### Macros: key, modifiers, states Source: https://docs.rs/terminput/latest/terminput/index.html?search=u32+-%3E+bool Macros for pattern matching key events and combining key modifiers and states in const contexts. ```APIDOC ## Macros ### key Pattern matching for key events. ### modifiers Macro for combining key modifiers in a way that's valid in `const` contexts. Useful for match expressions. ### states Macro for combining key states together in a way that's valid in `const` contexts. Useful for match expressions. ``` -------------------------------- ### KeyModifiers Flags Implementation Source: https://docs.rs/terminput/latest/terminput/struct.KeyModifiers.html?search= The Flags trait implementation for KeyModifiers provides methods to manipulate and query the underlying bits value, including getting bits, converting from bits, checking for unknown bits, and iterating over flags. ```APIDOC ## KeyModifiers Flags Implementation ### Description Provides bitwise operations and queries for the KeyModifiers bitflags type. ### Associated Constants - **FLAGS** (`&'static [Flag]`) - The set of defined flags. ### Associated Types - **Bits** (`u8`) - The underlying bits type. ### Methods - **bits(&self) -> u8** - Get the underlying bits value. - **from_bits_retain(bits: u8) -> KeyModifiers** - Convert from a bits value exactly. - **all_named() -> KeyModifiers** - Get a flags value with all bits from named flags set. - **empty() -> Self** - Get a flags value with all bits unset. - **all() -> Self** - Get a flags value with all known bits set. - **known_bits(&self) -> Self::Bits** - Get the known bits from a flags value. - **unknown_bits(&self) -> Self::Bits** - Get the unknown bits from a flags value. - **contains_unknown_bits(&self) -> bool** - Returns true if any unknown bits are set. - **from_bits(bits: Self::Bits) -> Option** - Convert from a bits value. - **from_bits_truncate(bits: Self::Bits) -> Self** - Convert from a bits value, unsetting any unknown bits. - **from_name(name: &str) -> Option** - Get a flags value with the bits of a flag with the given name set. - **iter(&self) -> Iter** - Yield a set of contained flags values. - **iter_names(&self) -> IterNames** - Yield a set of contained named flags values. - **iter_defined_names() -> IterDefinedNames** - Yield a set of all named flags defined by `Self::FLAGS`. - **iter_equal_names(&self) -> IterEqualNames** - Get an iterator over all defined names for this flags value. - **is_empty(&self) -> bool** - Whether all bits in this flags value are unset. - **is_all(&self) -> bool** - Whether all known bits in this flags value are set. - **intersects(&self, other: Self) -> bool** - Whether any set bits in `other` are also set in `self`. - **contains(&self, other: Self) -> bool** - Whether all set bits in `other` are also set in `self`. - **truncate(&mut self)** - Remove any unknown bits from the flags. - **insert(&mut self, other: Self)** - The bitwise or (`|`) of the bits in `self` and `other`. - **remove(&mut self, other: Self)** - The intersection of `self` with the complement of `other` (`&!`). - **toggle(&mut self, other: Self)** - The bitwise exclusive-or (`^`) of the bits in `self` and `other`. - **set(&mut self, other: Self, value: bool)** - Call `Flags::insert` when `value` is `true` or `Flags::remove` when `value` is `false`. - **clear(&mut self)** - Unsets all bits in the flags. - **intersection(self, other: Self) -> Self** - The bitwise and (`&`) of the bits in `self` and `other`. - **union(self, other: Self) -> Self** - The bitwise or (`|`) of the bits in `self` and `other`. - **difference(self, other: Self) -> Self** - The intersection of `self` with the complement of `other` (`&!`). - **symmetric_difference(self, other: Self) -> Self** - The bitwise exclusive-or (`^`) of the bits in `self` and `other`. - **complement(self) -> Self** - The bitwise negation (`!`) of the bits in `self`, truncating the result. ### Example ```rust use key_modifiers::KeyModifiers; let flags = KeyModifiers::from_bits(0b0000_0001).unwrap(); assert!(flags.contains(KeyModifiers::SHIFT)); ``` ``` -------------------------------- ### KeyCode Mapping for System and Media Keys Source: https://docs.rs/terminput/latest/src/terminput/encoder.rs.html?search=std%3A%3Avec Maps system keys like NumLock and PrintScreen, function keys, and various media control keys to their respective byte codes. ```rust 387 KeyCode::NumLock => { 388 buf.write_all(b"57360")?; 389 } 390 KeyCode::PrintScreen => { 391 buf.write_all(b"57361")?; 392 } 393 KeyCode::Pause => { 394 buf.write_all(b"57362")?; 395 } 396 KeyCode::Menu => { 397 buf.write_all(b"57363")?; 398 } 399 KeyCode::F(val @ 13..=35) => { 400 buf.write_all(&(57376 + (val as u16 - 13)).to_string().into_bytes())?; 401 } 402 KeyCode::F(36..) => return unsupported_error(key_event).map(|_| ()), 403 KeyCode::Media(MediaKeyCode::Play) => { 404 buf.write_all(b"57428")?; 405 } 406 KeyCode::Media(MediaKeyCode::Pause) => { 407 buf.write_all(b"57429")?; 408 } 409 KeyCode::Media(MediaKeyCode::PlayPause) => { 410 buf.write_all(b"57430")?; 411 } 412 KeyCode::Media(MediaKeyCode::Reverse) => { 413 buf.write_all(b"57431")?; 414 } 415 KeyCode::Media(MediaKeyCode::Stop) => { 416 buf.write_all(b"57432")?; 417 } 418 KeyCode::Media(MediaKeyCode::FastForward) => { 419 buf.write_all(b"57433")?; 420 } 421 KeyCode::Media(MediaKeyCode::Rewind) => { 422 buf.write_all(b"57434")?; 423 } 424 KeyCode::Media(MediaKeyCode::TrackNext) => { 425 buf.write_all(b"57435")?; 426 } 427 KeyCode::Media(MediaKeyCode::TrackPrevious) => { 428 buf.write_all(b"57436")?; 429 } 430 KeyCode::Media(MediaKeyCode::Record) => { 431 buf.write_all(b"57437")?; 432 } 433 KeyCode::Media(MediaKeyCode::LowerVolume) => { 434 buf.write_all(b"57438")?; 435 } 436 KeyCode::Media(MediaKeyCode::RaiseVolume) => { 437 buf.write_all(b"57439")?; 438 } 439 KeyCode::Media(MediaKeyCode::MuteVolume) => { 440 buf.write_all(b"57440")?; 441 } ``` -------------------------------- ### Macro `key!` Source: https://docs.rs/terminput/latest/terminput/macro.key.html?search= Documentation for the `key!` macro used for pattern matching on key events in the terminput crate. ```APIDOC ## Macro `key!` ### Description Pattern matching for key events. There are three forms: `key!(keyCode)`, `key!(modifiers, keyCode)`, and `key!(eventState, modifiers, keyCode)`. If `modifiers` is omitted, only events with no modifiers are matched. If `eventState` is omitted, any event state will be matched. ### Syntax ```rust macro_rules! key { ($state:pat, $mods:pat, $code:pat) => { ... }; ($mods:pat, $code:pat) => { ... }; ($code:pat) => { ... }; } ``` ### Parameters - **$code** (pattern) - Required - The key code pattern to match. - **$mods** (pattern) - Optional - The key modifiers pattern to match. If omitted, only events with no modifiers are matched. - **$state** (pattern) - Optional - The event state pattern to match. If omitted, any event state will be matched. ### Example ```rust use terminput::KeyCode::*; use terminput::{ALT, CTRL, Event, KeyModifiers, Repeats, key, modifiers}; fn handle_event(event: Event) { if let Some(key_event) = event.as_key_press(Repeats::Include) { const CTRL_ALT: KeyModifiers = modifiers!(CTRL, ALT); match key_event { key!(Char('a')) => { println!("'a' pressed"); } key!(CTRL | ALT, Char('d')) => { println!("'ctrl+d' or 'alt+d' pressed"); } key!(CTRL_ALT, Char('c')) => { println!("'ctrl+alt+c' pressed"); } key!(CAPS_LOCK, KeyModifiers::NONE, Char('d')) => { println!("'d' pressed with caps lock"); } _ => {} } } } ``` ``` -------------------------------- ### Parse CSI u encoded key code Source: https://docs.rs/terminput/latest/src/terminput/parser/mod.rs.html Parses a byte buffer that starts with ESC [ and ends with u, interpreting the semicolon-separated numbers as a CSI u sequence. Returns an io::Result>, using could_not_parse_event_error() on invalid UTF-8. ```rust pub(crate) fn parse_csi_u_encoded_key_code(buffer: &[u8]) -> io::Result> { assert!(buffer.starts_with(b"\x1B[")); // ESC [ assert!(buffer.ends_with(b"u")); // This function parses `CSI … u` sequences. These are sequences defined in either // the `CSI u` (a.k.a. "Fix Keyboard Input on Terminals - Please", https://www.leonerd.org.uk/hacks/fixterms/) // or Kitty Keyboard Protocol (https://sw.kovidgoyal.net/kitty/keyboard-protocol/) specifications. // This CSI sequence is a tuple of semicolon-separated numbers. let s = std::str::from_utf8(&buffer[2..buffer.len() - 1]) .map_err(|_| could_not_parse_event_error())?; let mut split = s.split(';'); ``` -------------------------------- ### key! macro Source: https://docs.rs/terminput/latest/src/terminput/key.rs.html?search=std%3A%3Avec Pattern matching for key events. There are three forms: `key!(keyCode)`, `key!(modifiers, keyCode)`, and `key!(eventState, modifiers, keyCode)`. If `modifiers` is omitted, only events with no modifiers are matched. If `eventState` is omitted, any event state will be matched. ```APIDOC ## key! macro ### Description Pattern matching for key events. There are three forms: - `key!(keyCode)` - `key!(modifiers, keyCode)` - `key!(eventState, modifiers, keyCode)` If `modifiers` is omitted, only events with no modifiers are matched. If `eventState` is omitted, any event state will be matched. ### Example rust use terminput::KeyCode::*; use terminput::{ALT, CTRL, Event, KeyModifiers, Repeats, key, modifiers}; ``` -------------------------------- ### Parse CSI bracketed paste sequence Source: https://docs.rs/terminput/latest/src/terminput/parser/mod.rs.html?search= Parses a bracketed paste sequence starting with ESC [ 2 0 0 ~ and ending with ESC 2 0 1 ~. Returns None if the sequence is incomplete, otherwise returns the pasted text as an Event::Paste. ```Rust pub(crate) fn parse_csi_bracketed_paste(buffer: &[u8]) -> io::Result> { // ESC [ 2 0 0 ~ pasted text ESC 2 0 1 ~ assert!(buffer.starts_with(b"\x1B[200~")); if !buffer.ends_with(b"\x1b[201~") { Ok(None) } else { let paste = String::from_utf8_lossy(&buffer[6..buffer.len() - 6]).to_string(); Ok(Some(Event::Paste(paste))) } } ``` -------------------------------- ### KeyEventState Source: https://docs.rs/terminput/latest/terminput/struct.KeyEventState.html?search=u32+-%3E+bool Documentation for the KeyEventState struct and its associated methods. ```APIDOC ## Struct KeyEventState ### Description Represents extra state about the key event. ### Fields - `NONE` (const) - No extra state applicable. - `KEYPAD` (const) - The key event came from the keypad. - `CAPS_LOCK` (const) - Caps Lock was enabled for this key event. - `NUM_LOCK` (const) - Num Lock was enabled for this key event. ### Methods #### `empty()` Get a flags value with all bits unset. #### `all()` Get a flags value with all known bits set. #### `bits(&self) -> u8` Get the underlying bits value. The returned value is exactly the bits set in this flags value. #### `from_bits(bits: u8) -> Option` Convert from a bits value. This method will return `None` if any unknown bits are set. #### `from_bits_truncate(bits: u8) -> Self` Convert from a bits value, unsetting any unknown bits. #### `from_bits_retain(bits: u8) -> Self` Convert from a bits value exactly. #### `from_name(name: &str) -> Option` Get a flags value with the bits of a flag with the given name set. This method will return `None` if `name` is empty or doesn’t correspond to any named flag. #### `is_empty(&self) -> bool` Whether all bits in `self` are unset. #### `is_all(&self) -> bool` Whether all known bits in this flags value are set. #### `intersects(&self, other: Self) -> bool` Whether any set bits in `other` are also set in `self`. #### `contains(&self, other: Self) -> bool` Whether all set bits in `other` are also set in `self`. #### `insert(&mut self, other: Self)` The bitwise or (`|`) of the bits in `self` and `other`. #### `remove(&mut self, other: Self)` The intersection of `self` with the complement of `other` (`&!`). This method is not equivalent to `self & !other` when `other` has unknown bits set. `remove` won’t truncate `other`, but the `!` operator will. #### `toggle(&mut self, other: Self)` The bitwise exclusive-or (`^`) of the bits in `self` and `other`. #### `set(&mut self, other: Self, value: bool)` Call `insert` when `value` is `true` or `remove` when `value` is `false`. #### `intersection(self, other: Self) -> Self` The bitwise and (`&`) of the bits in `self` and `other`. #### `union(self, other: Self) -> Self` The bitwise or (`|`) of the bits in `self` and `other`. #### `difference(self, other: Self) -> Self` The intersection of `self` with the complement of `other` (`&!`). This method is not equivalent to `self & !other` when `other` has unknown bits set. `difference` won’t truncate `other`, but the `!` operator will. #### `symmetric_difference(self, other: Self) -> Self` The bitwise exclusive-or (`^`) of the bits in `self` and `other`. #### `complement(self) -> Self` The bitwise negation (`!`) of the bits in `self`, truncating the result. #### `iter(&self) -> Iter` Yield a set of contained flags values. Each yielded flags value will correspond to a defined named flag. Any unknown bits will be yielded together as a final flags value. #### `iter_names(&self) -> IterNames` Yield a set of contained named flags values. This method is like `iter`, except only yields bits in contained named flags. Any unknown bits, or bits not corresponding to a contained flag will not be yielded. ``` -------------------------------- ### Write Kitty Encoding Source: https://docs.rs/terminput/latest/src/terminput/encoder.rs.html Handles the initial encoding of specific keys for the Kitty keyboard protocol. ```rust fn write_kitty_encoding( key_event: KeyEvent, flags: KittyFlags, buf: &mut Cursor<&mut [u8]>, ) -> io::Result<()> { let is_keypad = key_event.state.intersects(KeyEventState::KEYPAD); match key_event.code { KeyCode::CapsLock => { buf.write_all(b"57358")?; } ``` -------------------------------- ### Parse SGR mouse encoding (parse_csi_sgr_mouse) Source: https://docs.rs/terminput/latest/src/terminput/parser/mod.rs.html?search= Parses SGR mouse sequences of the form ESC [ < Cb ; Cx ; Cy (;) (M or m). Expects the buffer to start with ESC [ < and end with either m or M. Returns None if the ending character is not m or M. Converts a lowercase m ending to a button release event. ```rust pub(crate) fn parse_csi_sgr_mouse(buffer: &[u8]) -> io::Result> { // ESC [ < Cb ; Cx ; Cy (;) (M or m) assert!(buffer.starts_with(b"\x1B[<")); // ESC [ < if !buffer.ends_with(b"m") && !buffer.ends_with(b"M") { return Ok(None); } let s = std::str::from_utf8(&buffer[3..buffer.len() - 1]) .map_err(|_| could_not_parse_event_error())?; let mut split = s.split(';'); let cb = next_parsed::(&mut split)?; let (kind, modifiers) = parse_cb(cb)?; // See http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking // The upper left character position on the terminal is denoted as 1,1. // Subtract 1 to keep it synced with cursor let cx = next_parsed::(&mut split)? - 1; let cy = next_parsed::(&mut split)? - 1; // When button 3 in Cb is used to represent mouse release, you can't tell which button was // released. SGR mode solves this by having the sequence end with a lowercase m if it's a // button release and an uppercase M if it's a button press. // // We've already checked that the last character is a lowercase or uppercase M at the start of // this function, so we just need one if. let kind = if buffer.last() == Some(&b'm') { match kind { MouseEventKind::Down(button) => MouseEventKind::Up(button), other => other, } } else { kind }; Ok(Some(Event::Mouse(MouseEvent { kind, column: cx, row: cy, modifiers, }))) } ``` -------------------------------- ### Parse rxvt mouse encoding (parse_csi_rxvt_mouse) Source: https://docs.rs/terminput/latest/src/terminput/parser/mod.rs.html?search= Parses rxvt mouse sequences of the form ESC [ Cb ; Cx ; Cy ; M. Expects the buffer to start with ESC [ and end with M. Converts the Cb byte using parse_cb and subtracts 1 from coordinates to align with cursor positions. ```rust pub(crate) fn parse_csi_rxvt_mouse(buffer: &[u8]) -> io::Result> { // rxvt mouse encoding: // ESC [ Cb ; Cx ; Cy ; M assert!(buffer.starts_with(b"\x1B[")); // ESC [ assert!(buffer.ends_with(b"M")); let s = std::str::from_utf8(&buffer[2..buffer.len() - 1]) .map_err(|_| could_not_parse_event_error())?; let mut split = s.split(';'); let cb = next_parsed::(&mut split)? .checked_sub(32) .ok_or_else(could_not_parse_event_error)?; let (kind, modifiers) = parse_cb(cb)?; let cx = next_parsed::(&mut split)? - 1; let cy = next_parsed::(&mut split)? - 1; Ok(Some(Event::Mouse(MouseEvent { kind, column: cx, row: cy, modifiers, }))) } ``` -------------------------------- ### impl PartialEq for KittyFlags Source: https://docs.rs/terminput/latest/terminput/struct.KittyFlags.html Provides equality and inequality operators for KittyFlags. ```APIDOC ## impl PartialEq for KittyFlags ### Description Provides equality and inequality operators for KittyFlags. ### Methods #### fn eq(&self, other: &KittyFlags) -> bool Equality operator `==`. #### fn ne(&self, other: &Rhs) -> bool Inequality operator `!=`. ``` -------------------------------- ### impl Serialize for KittyFlags Source: https://docs.rs/terminput/latest/terminput/struct.KittyFlags.html Serializes KittyFlags using Serde. ```APIDOC ## impl Serialize for KittyFlags ### Description Serializes KittyFlags using Serde. ### Methods #### fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error> where __S: Serializer, Serialize this value into the given Serde serializer. ``` -------------------------------- ### Parse normal mouse encoding (parse_csi_normal_mouse) Source: https://docs.rs/terminput/latest/src/terminput/parser/mod.rs.html?search= Parses normal mouse sequences of the form ESC [ M CB Cx Cy (6 characters only). Expects the buffer to start with ESC [ M. Returns None if the buffer is shorter than 6 bytes. Coordinates are computed by subtracting 33 from the raw bytes to align with cursor positions. ```rust pub(crate) fn parse_csi_normal_mouse(buffer: &[u8]) -> io::Result> { // Normal mouse encoding: ESC [ M CB Cx Cy (6 characters only). assert!(buffer.starts_with(b"\x1B[M")); // ESC [ M if buffer.len() < 6 { return Ok(None); } let cb = buffer[3] .checked_sub(32) .ok_or_else(could_not_parse_event_error)?; let (kind, modifiers) = parse_cb(cb)?; // See http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking // The upper left character position on the terminal is denoted as 1,1. // Subtract 1 to keep it synced with cursor let cx = u16::from(buffer[4].saturating_sub(33)); let cy = u16::from(buffer[5].saturating_sub(33)); Ok(Some(Event::Mouse(MouseEvent { kind, column: cx, row: cy, modifiers, }))) } ``` -------------------------------- ### states! Source: https://docs.rs/terminput/latest/src/terminput/key.rs.html?search=std%3A%3Avec Macro for combining key states together in a way that's valid in const contexts. Useful for match expressions. ```APIDOC ## states! ### Description Macro for combining key states together in a way that's valid in `const` contexts. Useful for match expressions. ### Usage rust states!($($state:tt),+) ### Parameters - `$state` (tt) - One or more key state constants (e.g., `CAPS_LOCK`, `NUM_LOCK`) ### Example rust use terminput::{CAPS_LOCK, KeyEventState, NUM_LOCK, states}; const key_state: KeyEventState = states!(CAPS_LOCK, NUM_LOCK); assert_eq!(key_state, CAPS_LOCK | NUM_LOCK); ```