use bitflags::bitflags; bitflags! { #[derive(Copy, Clone)] pub struct TermMode: u32 { const NONE = 0; const SHOW_CURSOR = 0b0000_0000_0000_0000_0001; const APP_CURSOR = 0b0000_0000_0000_0000_0010; const APP_KEYPAD = 0b0000_0000_0000_0000_0100; const MOUSE_REPORT_CLICK = 0b0000_0000_0000_0000_1000; const BRACKETED_PASTE = 0b0000_0000_0000_0001_0000; const SGR_MOUSE = 0b0000_0000_0000_0010_0000; const MOUSE_MOTION = 0b0000_0000_0000_0100_0000; const LINE_WRAP = 0b0000_0000_0000_1000_0000; const LINE_FEED_NEW_LINE = 0b0000_0000_0001_0000_0000; const ORIGIN = 0b0000_0000_0010_0000_0000; const INSERT = 0b0000_0000_0100_0000_0000; const FOCUS_IN_OUT = 0b0000_0000_1000_0000_0000; const MOUSE_DRAG = 0b0000_0010_0000_0000_0000; const MOUSE_MODE = 0b0000_0010_0000_0100_1000; const UTF8_MOUSE = 0b0000_0100_0000_0000_0000; const ALTERNATE_SCROLL = 0b0000_1000_0000_0000_0000; const VI = 0b0001_0000_0000_0000_0000; const URGENCY_HINTS = 0b0010_0000_0000_0000_0000; // Kitty keyboard protocol enhancement flags // See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement /// Flag 1: Disambiguate escape codes. /// Encodes ambiguous keys using CSI u sequences instead of legacy encodings: /// - Esc key → CSI 27 u (distinguishes standalone Esc from escape sequence starts) /// - Modified keys (Alt+key, Ctrl+key, Ctrl+Alt+key, Shift+Alt+key) → CSI u format const KEYBOARD_DISAMBIGUATE_ESCAPE = 0b0100_0000_0000_0000_0000; /// Flag 2: Report event types. /// Enables reporting of key press, repeat, and release events, not just key presses. /// Format includes event type in the CSI u sequence. const KEYBOARD_REPORT_EVENT_TYPES = 0b1000_0000_0000_0000_0000; /// Flag 4: Report alternate keys. /// Reports the unshifted key alongside the shifted key. For example, when Shift+2 is /// pressed, reports both "@" (shifted) and "2" (unshifted) for layout-independent /// keybinding support. const KEYBOARD_REPORT_ALTERNATE_KEYS = 0b0001_0000_0000_0000_0000_0000; /// Flag 8: Report all keys as escape codes. /// Forces all keys, including printable characters, to be encoded as CSI u sequences. /// Provides a uniform encoding format. For example, plain 'a' becomes ESC[97;1u instead /// of just 0x61. Often combined with flag 1 for "full CSI u" mode (flags = 9). const KEYBOARD_REPORT_ALL_AS_ESCAPE = 0b0010_0000_0000_0000_0000_0000; /// Flag 16: Report associated text. /// Includes the text that would be generated by the key event, useful for applications /// that want both the semantic key information and the resulting text. const KEYBOARD_REPORT_ASSOCIATED_TEXT = 0b0100_0000_0000_0000_0000_0000; const KEYBOARD_PROTOCOL = Self::KEYBOARD_DISAMBIGUATE_ESCAPE.bits() | Self::KEYBOARD_REPORT_EVENT_TYPES.bits() | Self::KEYBOARD_REPORT_ALTERNATE_KEYS.bits() | Self::KEYBOARD_REPORT_ALL_AS_ESCAPE.bits() | Self::KEYBOARD_REPORT_ASSOCIATED_TEXT.bits(); const ANY = u32::MAX; } } impl Default for TermMode { fn default() -> TermMode { TermMode::SHOW_CURSOR | TermMode::LINE_WRAP | TermMode::ALTERNATE_SCROLL | TermMode::URGENCY_HINTS } } bitflags! { /// Kitty keyboard protocol modes. /// These map to the flags sent via CSI > flags u, CSI = flags u, etc. #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub struct KeyboardModes: u32 { const NO_MODE = 0; const DISAMBIGUATE_ESC_CODES = 0b0000_0001; const REPORT_EVENT_TYPES = 0b0000_0010; const REPORT_ALTERNATE_KEYS = 0b0000_0100; const REPORT_ALL_KEYS_AS_ESC = 0b0000_1000; const REPORT_ASSOCIATED_TEXT = 0b0001_0000; } } /// Convert KeyboardModes to TermMode flags impl From for TermMode { fn from(modes: KeyboardModes) -> Self { let mut term_mode = TermMode::NONE; if modes.contains(KeyboardModes::DISAMBIGUATE_ESC_CODES) { term_mode |= TermMode::KEYBOARD_DISAMBIGUATE_ESCAPE; } if modes.contains(KeyboardModes::REPORT_EVENT_TYPES) { term_mode |= TermMode::KEYBOARD_REPORT_EVENT_TYPES; } if modes.contains(KeyboardModes::REPORT_ALTERNATE_KEYS) { term_mode |= TermMode::KEYBOARD_REPORT_ALTERNATE_KEYS; } if modes.contains(KeyboardModes::REPORT_ALL_KEYS_AS_ESC) { term_mode |= TermMode::KEYBOARD_REPORT_ALL_AS_ESCAPE; } if modes.contains(KeyboardModes::REPORT_ASSOCIATED_TEXT) { term_mode |= TermMode::KEYBOARD_REPORT_ASSOCIATED_TEXT; } term_mode } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum KeyboardModesApplyBehavior { /// Replace all current modes with new ones Replace, /// Union (add) new modes to existing ones Union, /// Difference (remove) modes from existing ones Difference, } impl KeyboardModesApplyBehavior { /// Maps kitty keyboard protocol apply-mode values to behavior. /// /// From kitty's `CSI = flags ; mode u` command: /// - `1` (or omitted) = replace current flags /// - `2` = union/add flags /// - `3` = difference/remove flags pub fn from_kitty_apply_mode(mode: u16) -> Option { match mode { 1 => Some(Self::Replace), 2 => Some(Self::Union), 3 => Some(Self::Difference), _ => None, } } }