1use std::{collections::VecDeque, num::NonZeroU16, str};
13
14use crate::{
15 escape::{
16 self,
17 csi::{self, Csi, KittyKeyboardFlags, ThemeMode},
18 dcs,
19 },
20 event::{
21 KeyCode, KeyEvent, KeyEventKind, KeyEventState, MediaKeyCode, ModifierKeyCode, Modifiers,
22 MouseButton, MouseEvent, MouseEventKind,
23 },
24 style, Event,
25};
26
27#[derive(Debug)]
29pub struct Parser {
30 buffer: Vec<u8>,
31 events: VecDeque<Event>,
33}
34
35impl Default for Parser {
36 fn default() -> Self {
37 Self {
38 buffer: Vec::with_capacity(256),
39 events: VecDeque::with_capacity(32),
40 }
41 }
42}
43
44impl Parser {
45 pub fn pop(&mut self) -> Option<Event> {
47 self.events.pop_front()
48 }
49
50 pub fn parse(&mut self, bytes: &[u8], maybe_more: bool) {
55 self.buffer.extend_from_slice(bytes);
56 self.process_bytes(maybe_more);
57 }
58
59 fn process_bytes(&mut self, maybe_more: bool) {
60 let mut start = 0;
61 for n in 0..self.buffer.len() {
62 let end = n + 1;
63 match parse_event(
64 &self.buffer[start..end],
65 maybe_more || end < self.buffer.len(),
66 ) {
67 Ok(Some(event)) => {
68 self.events.push_back(event);
69 start = end;
70 }
71 Ok(None) => continue,
72 Err(_) => start = end,
73 }
74 }
75 self.advance(start);
76 }
77
78 fn advance(&mut self, len: usize) {
79 if len == 0 {
80 return;
81 }
82 let remain = self.buffer.len() - len;
83 self.buffer.rotate_left(len);
84 self.buffer.truncate(remain);
85 }
86}
87
88#[cfg(windows)]
94mod windows {
95 use windows_sys::Win32::System::Console;
96
97 use crate::{OneBased, WindowSize};
98
99 use super::*;
100
101 impl Parser {
102 pub(crate) fn decode_input_records(&mut self, records: &[Console::INPUT_RECORD]) {
103 for record in records {
104 match record.EventType as u32 {
105 Console::KEY_EVENT => {
106 let record = unsafe { record.Event.KeyEvent };
107 if record.bKeyDown == 0 {
110 continue;
111 }
112 let byte = unsafe { record.uChar.AsciiChar } as u8;
113 if byte == 0 {
115 continue;
116 }
117 self.buffer.push(byte);
120 }
121 Console::WINDOW_BUFFER_SIZE_EVENT => {
122 let record = unsafe { record.Event.WindowBufferSizeEvent };
125 let Some(rows) = OneBased::new(record.dwSize.Y as u16) else {
126 continue;
127 };
128 let Some(cols) = OneBased::new(record.dwSize.X as u16) else {
129 continue;
130 };
131 self.events.push_back(Event::WindowResized(WindowSize {
132 rows: rows.get(),
133 cols: cols.get(),
134 pixel_width: None,
135 pixel_height: None,
136 }));
137 }
138 _ => (),
139 }
140 }
141 self.process_bytes(false);
142 }
143 }
144}
145
146#[derive(Debug)]
147struct MalformedSequenceError;
148
149impl From<str::Utf8Error> for MalformedSequenceError {
151 fn from(_: str::Utf8Error) -> Self {
152 Self
153 }
154}
155
156type Result<T> = std::result::Result<T, MalformedSequenceError>;
157
158macro_rules! bail {
159 () => {
160 return Err(MalformedSequenceError)
161 };
162}
163
164fn parse_event(buffer: &[u8], maybe_more: bool) -> Result<Option<Event>> {
165 if buffer.is_empty() {
166 return Ok(None);
167 }
168
169 match buffer[0] {
170 b'\x1B' => {
171 if buffer.len() == 1 {
172 if maybe_more {
173 Ok(None)
175 } else {
176 Ok(Some(Event::Key(KeyCode::Escape.into())))
177 }
178 } else {
179 match buffer[1] {
180 b'O' => {
181 if buffer.len() == 2 {
182 Ok(None)
183 } else {
184 match buffer[2] {
185 b'D' => Ok(Some(Event::Key(KeyCode::Left.into()))),
186 b'C' => Ok(Some(Event::Key(KeyCode::Right.into()))),
187 b'A' => Ok(Some(Event::Key(KeyCode::Up.into()))),
188 b'B' => Ok(Some(Event::Key(KeyCode::Down.into()))),
189 b'H' => Ok(Some(Event::Key(KeyCode::Home.into()))),
190 b'F' => Ok(Some(Event::Key(KeyCode::End.into()))),
191 val @ b'P'..=b'S' => {
193 Ok(Some(Event::Key(KeyCode::Function(1 + val - b'P').into())))
194 }
195 _ => bail!(),
196 }
197 }
198 }
199 b'[' => parse_csi(buffer),
200 b'P' => parse_dcs(buffer),
201 b'\x1B' => Ok(Some(Event::Key(KeyCode::Escape.into()))),
202 _ => parse_event(&buffer[1..], maybe_more).map(|event_option| {
203 event_option.map(|event| {
204 if let Event::Key(key_event) = event {
205 let mut alt_key_event = key_event;
206 alt_key_event.modifiers |= Modifiers::ALT;
207 Event::Key(alt_key_event)
208 } else {
209 event
210 }
211 })
212 }),
213 }
214 }
215 }
216 b'\r' => Ok(Some(Event::Key(KeyCode::Enter.into()))),
217 b'\t' => Ok(Some(Event::Key(KeyCode::Tab.into()))),
218 b'\x7F' => Ok(Some(Event::Key(KeyCode::Backspace.into()))),
219 b'\0' => Ok(Some(Event::Key(KeyEvent::new(
220 KeyCode::Char(' '),
221 Modifiers::CONTROL,
222 )))),
223 c @ b'\x01'..=b'\x1A' => Ok(Some(Event::Key(KeyEvent::new(
224 KeyCode::Char((c - 0x1 + b'a') as char),
225 Modifiers::CONTROL,
226 )))),
227 c @ b'\x1C'..=b'\x1F' => Ok(Some(Event::Key(KeyEvent::new(
228 KeyCode::Char((c - 0x1C + b'4') as char),
229 Modifiers::CONTROL,
230 )))),
231 _ => parse_utf8_char(buffer).map(|maybe_char| {
232 maybe_char.map(|ch| {
233 let modifiers = if ch.is_uppercase() {
234 Modifiers::SHIFT
235 } else {
236 Modifiers::NONE
237 };
238 Event::Key(KeyEvent::new(KeyCode::Char(ch), modifiers))
239 })
240 }),
241 }
242}
243
244fn parse_utf8_char(buffer: &[u8]) -> Result<Option<char>> {
245 assert!(!buffer.is_empty());
246 match str::from_utf8(buffer) {
247 Ok(s) => Ok(Some(s.chars().next().unwrap())),
248 Err(_) => {
249 let required_bytes = match buffer[0] {
252 (0x00..=0x7F) => 1, (0xC0..=0xDF) => 2, (0xE0..=0xEF) => 3, (0xF0..=0xF7) => 4, (0x80..=0xBF) | (0xF8..=0xFF) => bail!(),
258 };
259 if required_bytes > 1 && buffer.len() > 1 {
260 for byte in &buffer[1..] {
261 if byte & !0b0011_1111 != 0b1000_0000 {
262 bail!()
263 }
264 }
265 }
266 if buffer.len() < required_bytes {
267 Ok(None)
268 } else {
269 bail!()
270 }
271 }
272 }
273}
274
275fn parse_csi(buffer: &[u8]) -> Result<Option<Event>> {
276 assert!(buffer.starts_with(b"\x1B["));
277 if buffer.len() == 2 {
278 return Ok(None);
279 }
280 let maybe_event = match buffer[2] {
281 b'[' => match buffer.get(3) {
282 None => None,
283 Some(b @ b'A'..=b'E') => Some(Event::Key(KeyCode::Function(1 + b - b'A').into())),
284 Some(_) => bail!(),
285 },
286 b'D' => Some(Event::Key(KeyCode::Left.into())),
287 b'C' => Some(Event::Key(KeyCode::Right.into())),
288 b'A' => Some(Event::Key(KeyCode::Up.into())),
289 b'B' => Some(Event::Key(KeyCode::Down.into())),
290 b'H' => Some(Event::Key(KeyCode::Home.into())),
291 b'F' => Some(Event::Key(KeyCode::End.into())),
292 b'Z' => Some(Event::Key(KeyEvent {
293 code: KeyCode::BackTab,
294 modifiers: Modifiers::SHIFT,
295 kind: KeyEventKind::Press,
296 state: KeyEventState::NONE,
297 })),
298 b'M' => return parse_csi_normal_mouse(buffer),
299 b'<' => return parse_csi_sgr_mouse(buffer),
300 b'I' => Some(Event::FocusIn),
301 b'O' => Some(Event::FocusOut),
302 b';' => return parse_csi_modifier_key_code(buffer),
303 b'P' => Some(Event::Key(KeyCode::Function(1).into())),
308 b'Q' => Some(Event::Key(KeyCode::Function(2).into())),
309 b'S' => Some(Event::Key(KeyCode::Function(4).into())),
310 b'?' => match buffer[buffer.len() - 1] {
311 b'u' => return parse_csi_keyboard_enhancement_flags(buffer),
312 b'c' => return parse_csi_primary_device_attributes(buffer),
313 b'n' => return parse_csi_theme_mode(buffer),
314 b'y' => return parse_csi_synchronized_output_mode(buffer),
315 _ => None,
316 },
317 b'0'..=b'9' => {
318 if buffer.len() == 3 {
320 None
321 } else {
322 let last_byte = buffer[buffer.len() - 1];
325 if !(64..=126).contains(&last_byte) {
326 None
327 } else {
328 if buffer.starts_with(b"\x1B[200~") {
329 return parse_csi_bracketed_paste(buffer);
330 }
331 match last_byte {
332 b'M' => return parse_csi_rxvt_mouse(buffer),
333 b'~' => return parse_csi_special_key_code(buffer),
334 b'u' => return parse_csi_u_encoded_key_code(buffer),
335 b'R' => return parse_csi_cursor_position(buffer),
336 _ => return parse_csi_modifier_key_code(buffer),
337 }
338 }
339 }
340 }
341 _ => bail!(),
342 };
343 Ok(maybe_event)
344}
345
346fn next_parsed<T>(iter: &mut dyn Iterator<Item = &str>) -> Result<T>
347where
348 T: str::FromStr,
349{
350 iter.next()
351 .ok_or(MalformedSequenceError)?
352 .parse::<T>()
353 .map_err(|_| MalformedSequenceError)
354}
355
356fn modifier_and_kind_parsed(iter: &mut dyn Iterator<Item = &str>) -> Result<(u8, u8)> {
357 let mut sub_split = iter.next().ok_or(MalformedSequenceError)?.split(':');
358
359 let modifier_mask = next_parsed::<u8>(&mut sub_split)?;
360
361 if let Ok(kind_code) = next_parsed::<u8>(&mut sub_split) {
362 Ok((modifier_mask, kind_code))
363 } else {
364 Ok((modifier_mask, 1))
365 }
366}
367
368fn parse_csi_u_encoded_key_code(buffer: &[u8]) -> Result<Option<Event>> {
369 assert!(buffer.starts_with(b"\x1B")); assert!(buffer.ends_with(b"u"));
371
372 let s = str::from_utf8(&buffer[2..buffer.len() - 1])?;
377 let mut split = s.split(';');
378
379 let mut codepoints = split.next().ok_or(MalformedSequenceError)?.split(':');
389
390 let codepoint = codepoints
391 .next()
392 .ok_or(MalformedSequenceError)?
393 .parse::<u32>()
394 .map_err(|_| MalformedSequenceError)?;
395
396 let (mut modifiers, kind, state_from_modifiers) =
397 if let Ok((modifier_mask, kind_code)) = modifier_and_kind_parsed(&mut split) {
398 (
399 parse_modifiers(modifier_mask),
400 parse_key_event_kind(kind_code),
401 parse_modifiers_to_state(modifier_mask),
402 )
403 } else {
404 (Modifiers::NONE, KeyEventKind::Press, KeyEventState::NONE)
405 };
406
407 let (mut code, state_from_keycode) = {
408 if let Some((special_key_code, state)) = translate_functional_key_code(codepoint) {
409 (special_key_code, state)
410 } else if let Some(c) = char::from_u32(codepoint) {
411 (
412 match c {
413 '\x1B' => KeyCode::Escape,
414 '\r' => KeyCode::Enter,
415 '\t' => {
423 if modifiers.contains(Modifiers::SHIFT) {
424 KeyCode::BackTab
425 } else {
426 KeyCode::Tab
427 }
428 }
429 '\x7F' => KeyCode::Backspace,
430 _ => KeyCode::Char(c),
431 },
432 KeyEventState::empty(),
433 )
434 } else {
435 bail!();
436 }
437 };
438
439 if let KeyCode::Modifier(modifier_keycode) = code {
440 match modifier_keycode {
441 ModifierKeyCode::LeftAlt | ModifierKeyCode::RightAlt => {
442 modifiers.set(Modifiers::ALT, true)
443 }
444 ModifierKeyCode::LeftControl | ModifierKeyCode::RightControl => {
445 modifiers.set(Modifiers::CONTROL, true)
446 }
447 ModifierKeyCode::LeftShift | ModifierKeyCode::RightShift => {
448 modifiers.set(Modifiers::SHIFT, true)
449 }
450 ModifierKeyCode::LeftSuper | ModifierKeyCode::RightSuper => {
451 modifiers.set(Modifiers::SUPER, true)
452 }
453 ModifierKeyCode::LeftHyper | ModifierKeyCode::RightHyper => {
454 modifiers.set(Modifiers::HYPER, true)
455 }
456 ModifierKeyCode::LeftMeta | ModifierKeyCode::RightMeta => {
457 modifiers.set(Modifiers::META, true)
458 }
459 _ => {}
460 }
461 }
462
463 if modifiers.contains(Modifiers::SHIFT) {
468 if let Some(shifted_c) = codepoints
469 .next()
470 .and_then(|codepoint| codepoint.parse::<u32>().ok())
471 .and_then(char::from_u32)
472 {
473 code = KeyCode::Char(shifted_c);
474 modifiers.set(Modifiers::SHIFT, false);
475 }
476 }
477
478 let event = Event::Key(KeyEvent {
479 code,
480 modifiers,
481 kind,
482 state: state_from_keycode | state_from_modifiers,
483 });
484
485 Ok(Some(event))
486}
487
488fn parse_modifiers(mask: u8) -> Modifiers {
489 let modifier_mask = mask.saturating_sub(1);
490 let mut modifiers = Modifiers::empty();
491 if modifier_mask & 1 != 0 {
492 modifiers |= Modifiers::SHIFT;
493 }
494 if modifier_mask & 2 != 0 {
495 modifiers |= Modifiers::ALT;
496 }
497 if modifier_mask & 4 != 0 {
498 modifiers |= Modifiers::CONTROL;
499 }
500 if modifier_mask & 8 != 0 {
501 modifiers |= Modifiers::SUPER;
502 }
503 if modifier_mask & 16 != 0 {
504 modifiers |= Modifiers::HYPER;
505 }
506 if modifier_mask & 32 != 0 {
507 modifiers |= Modifiers::META;
508 }
509 modifiers
510}
511
512fn parse_modifiers_to_state(mask: u8) -> KeyEventState {
513 let modifier_mask = mask.saturating_sub(1);
514 let mut state = KeyEventState::empty();
515 if modifier_mask & 64 != 0 {
516 state |= KeyEventState::CAPS_LOCK;
517 }
518 if modifier_mask & 128 != 0 {
519 state |= KeyEventState::NUM_LOCK;
520 }
521 state
522}
523
524fn parse_key_event_kind(kind: u8) -> KeyEventKind {
525 match kind {
526 1 => KeyEventKind::Press,
527 2 => KeyEventKind::Repeat,
528 3 => KeyEventKind::Release,
529 _ => KeyEventKind::Press,
530 }
531}
532
533fn parse_csi_modifier_key_code(buffer: &[u8]) -> Result<Option<Event>> {
534 assert!(buffer.starts_with(b"\x1B[")); let s = str::from_utf8(&buffer[2..buffer.len() - 1])?;
536 let mut split = s.split(';');
537
538 split.next();
539
540 let (modifiers, kind) =
541 if let Ok((modifier_mask, kind_code)) = modifier_and_kind_parsed(&mut split) {
542 (
543 parse_modifiers(modifier_mask),
544 parse_key_event_kind(kind_code),
545 )
546 } else if buffer.len() > 3 {
547 (
548 parse_modifiers(
549 (buffer[buffer.len() - 2] as char)
550 .to_digit(10)
551 .ok_or(MalformedSequenceError)? as u8,
552 ),
553 KeyEventKind::Press,
554 )
555 } else {
556 (Modifiers::NONE, KeyEventKind::Press)
557 };
558 let key = buffer[buffer.len() - 1];
559
560 let code = match key {
561 b'A' => KeyCode::Up,
562 b'B' => KeyCode::Down,
563 b'C' => KeyCode::Right,
564 b'D' => KeyCode::Left,
565 b'F' => KeyCode::End,
566 b'H' => KeyCode::Home,
567 b'P' => KeyCode::Function(1),
568 b'Q' => KeyCode::Function(2),
569 b'R' => KeyCode::Function(3),
570 b'S' => KeyCode::Function(4),
571 _ => bail!(),
572 };
573
574 let event = Event::Key(KeyEvent {
575 code,
576 modifiers,
577 kind,
578 state: KeyEventState::NONE,
579 });
580
581 Ok(Some(event))
582}
583
584fn parse_csi_special_key_code(buffer: &[u8]) -> Result<Option<Event>> {
585 assert!(buffer.starts_with(b"\x1B[")); assert!(buffer.ends_with(b"~"));
587
588 let s = str::from_utf8(&buffer[2..buffer.len() - 1])?;
589 let mut split = s.split(';');
590
591 let first = next_parsed::<u8>(&mut split)?;
593
594 let (modifiers, kind, state) =
595 if let Ok((modifier_mask, kind_code)) = modifier_and_kind_parsed(&mut split) {
596 (
597 parse_modifiers(modifier_mask),
598 parse_key_event_kind(kind_code),
599 parse_modifiers_to_state(modifier_mask),
600 )
601 } else {
602 (Modifiers::NONE, KeyEventKind::Press, KeyEventState::NONE)
603 };
604
605 let code = match first {
606 1 | 7 => KeyCode::Home,
607 2 => KeyCode::Insert,
608 3 => KeyCode::Delete,
609 4 | 8 => KeyCode::End,
610 5 => KeyCode::PageUp,
611 6 => KeyCode::PageDown,
612 v @ 11..=15 => KeyCode::Function(v - 10),
613 v @ 17..=21 => KeyCode::Function(v - 11),
614 v @ 23..=26 => KeyCode::Function(v - 12),
615 v @ 28..=29 => KeyCode::Function(v - 15),
616 v @ 31..=34 => KeyCode::Function(v - 17),
617 _ => bail!(),
618 };
619
620 let event = Event::Key(KeyEvent {
621 code,
622 modifiers,
623 kind,
624 state,
625 });
626
627 Ok(Some(event))
628}
629
630fn translate_functional_key_code(codepoint: u32) -> Option<(KeyCode, KeyEventState)> {
631 if let Some(keycode) = match codepoint {
632 57399 => Some(KeyCode::Char('0')),
633 57400 => Some(KeyCode::Char('1')),
634 57401 => Some(KeyCode::Char('2')),
635 57402 => Some(KeyCode::Char('3')),
636 57403 => Some(KeyCode::Char('4')),
637 57404 => Some(KeyCode::Char('5')),
638 57405 => Some(KeyCode::Char('6')),
639 57406 => Some(KeyCode::Char('7')),
640 57407 => Some(KeyCode::Char('8')),
641 57408 => Some(KeyCode::Char('9')),
642 57409 => Some(KeyCode::Char('.')),
643 57410 => Some(KeyCode::Char('/')),
644 57411 => Some(KeyCode::Char('*')),
645 57412 => Some(KeyCode::Char('-')),
646 57413 => Some(KeyCode::Char('+')),
647 57414 => Some(KeyCode::Enter),
648 57415 => Some(KeyCode::Char('=')),
649 57416 => Some(KeyCode::Char(',')),
650 57417 => Some(KeyCode::Left),
651 57418 => Some(KeyCode::Right),
652 57419 => Some(KeyCode::Up),
653 57420 => Some(KeyCode::Down),
654 57421 => Some(KeyCode::PageUp),
655 57422 => Some(KeyCode::PageDown),
656 57423 => Some(KeyCode::Home),
657 57424 => Some(KeyCode::End),
658 57425 => Some(KeyCode::Insert),
659 57426 => Some(KeyCode::Delete),
660 57427 => Some(KeyCode::KeypadBegin),
661 _ => None,
662 } {
663 return Some((keycode, KeyEventState::KEYPAD));
664 }
665
666 if let Some(keycode) = match codepoint {
667 57358 => Some(KeyCode::CapsLock),
668 57359 => Some(KeyCode::ScrollLock),
669 57360 => Some(KeyCode::NumLock),
670 57361 => Some(KeyCode::PrintScreen),
671 57362 => Some(KeyCode::Pause),
672 57363 => Some(KeyCode::Menu),
673 57376 => Some(KeyCode::Function(13)),
674 57377 => Some(KeyCode::Function(14)),
675 57378 => Some(KeyCode::Function(15)),
676 57379 => Some(KeyCode::Function(16)),
677 57380 => Some(KeyCode::Function(17)),
678 57381 => Some(KeyCode::Function(18)),
679 57382 => Some(KeyCode::Function(19)),
680 57383 => Some(KeyCode::Function(20)),
681 57384 => Some(KeyCode::Function(21)),
682 57385 => Some(KeyCode::Function(22)),
683 57386 => Some(KeyCode::Function(23)),
684 57387 => Some(KeyCode::Function(24)),
685 57388 => Some(KeyCode::Function(25)),
686 57389 => Some(KeyCode::Function(26)),
687 57390 => Some(KeyCode::Function(27)),
688 57391 => Some(KeyCode::Function(28)),
689 57392 => Some(KeyCode::Function(29)),
690 57393 => Some(KeyCode::Function(30)),
691 57394 => Some(KeyCode::Function(31)),
692 57395 => Some(KeyCode::Function(32)),
693 57396 => Some(KeyCode::Function(33)),
694 57397 => Some(KeyCode::Function(34)),
695 57398 => Some(KeyCode::Function(35)),
696 57428 => Some(KeyCode::Media(MediaKeyCode::Play)),
697 57429 => Some(KeyCode::Media(MediaKeyCode::Pause)),
698 57430 => Some(KeyCode::Media(MediaKeyCode::PlayPause)),
699 57431 => Some(KeyCode::Media(MediaKeyCode::Reverse)),
700 57432 => Some(KeyCode::Media(MediaKeyCode::Stop)),
701 57433 => Some(KeyCode::Media(MediaKeyCode::FastForward)),
702 57434 => Some(KeyCode::Media(MediaKeyCode::Rewind)),
703 57435 => Some(KeyCode::Media(MediaKeyCode::TrackNext)),
704 57436 => Some(KeyCode::Media(MediaKeyCode::TrackPrevious)),
705 57437 => Some(KeyCode::Media(MediaKeyCode::Record)),
706 57438 => Some(KeyCode::Media(MediaKeyCode::LowerVolume)),
707 57439 => Some(KeyCode::Media(MediaKeyCode::RaiseVolume)),
708 57440 => Some(KeyCode::Media(MediaKeyCode::MuteVolume)),
709 57441 => Some(KeyCode::Modifier(ModifierKeyCode::LeftShift)),
710 57442 => Some(KeyCode::Modifier(ModifierKeyCode::LeftControl)),
711 57443 => Some(KeyCode::Modifier(ModifierKeyCode::LeftAlt)),
712 57444 => Some(KeyCode::Modifier(ModifierKeyCode::LeftSuper)),
713 57445 => Some(KeyCode::Modifier(ModifierKeyCode::LeftHyper)),
714 57446 => Some(KeyCode::Modifier(ModifierKeyCode::LeftMeta)),
715 57447 => Some(KeyCode::Modifier(ModifierKeyCode::RightShift)),
716 57448 => Some(KeyCode::Modifier(ModifierKeyCode::RightControl)),
717 57449 => Some(KeyCode::Modifier(ModifierKeyCode::RightAlt)),
718 57450 => Some(KeyCode::Modifier(ModifierKeyCode::RightSuper)),
719 57451 => Some(KeyCode::Modifier(ModifierKeyCode::RightHyper)),
720 57452 => Some(KeyCode::Modifier(ModifierKeyCode::RightMeta)),
721 57453 => Some(KeyCode::Modifier(ModifierKeyCode::IsoLevel3Shift)),
722 57454 => Some(KeyCode::Modifier(ModifierKeyCode::IsoLevel5Shift)),
723 _ => None,
724 } {
725 return Some((keycode, KeyEventState::empty()));
726 }
727
728 None
729}
730
731fn parse_csi_rxvt_mouse(buffer: &[u8]) -> Result<Option<Event>> {
732 assert!(buffer.starts_with(b"\x1B[")); assert!(buffer.ends_with(b"M"));
737
738 let s = str::from_utf8(&buffer[2..buffer.len() - 1])?;
739 let mut split = s.split(';');
740
741 let cb = next_parsed::<u8>(&mut split)?
742 .checked_sub(32)
743 .ok_or(MalformedSequenceError)?;
744 let (kind, modifiers) = parse_cb(cb)?;
745
746 let cx = next_parsed::<u16>(&mut split)? - 1;
747 let cy = next_parsed::<u16>(&mut split)? - 1;
748
749 Ok(Some(Event::Mouse(MouseEvent {
750 kind,
751 column: cx,
752 row: cy,
753 modifiers,
754 })))
755}
756
757fn parse_csi_normal_mouse(buffer: &[u8]) -> Result<Option<Event>> {
758 assert!(buffer.starts_with(b"\x1B[M")); if buffer.len() < 6 {
763 return Ok(None);
764 }
765
766 let cb = buffer[3].checked_sub(32).ok_or(MalformedSequenceError)?;
767 let (kind, modifiers) = parse_cb(cb)?;
768
769 let cx = u16::from(buffer[4].saturating_sub(33));
774 let cy = u16::from(buffer[5].saturating_sub(33));
775
776 Ok(Some(Event::Mouse(MouseEvent {
777 kind,
778 column: cx,
779 row: cy,
780 modifiers,
781 })))
782}
783
784fn parse_csi_sgr_mouse(buffer: &[u8]) -> Result<Option<Event>> {
785 assert!(buffer.starts_with(b"\x1B[<")); if !buffer.ends_with(b"m") && !buffer.ends_with(b"M") {
790 return Ok(None);
791 }
792
793 let s = str::from_utf8(&buffer[3..buffer.len() - 1])?;
794 let mut split = s.split(';');
795
796 let cb = next_parsed::<u8>(&mut split)?;
797 let (kind, modifiers) = parse_cb(cb)?;
798
799 let cx = next_parsed::<u16>(&mut split)? - 1;
803 let cy = next_parsed::<u16>(&mut split)? - 1;
804
805 let kind = if buffer.last() == Some(&b'm') {
812 match kind {
813 MouseEventKind::Down(button) => MouseEventKind::Up(button),
814 other => other,
815 }
816 } else {
817 kind
818 };
819
820 Ok(Some(Event::Mouse(MouseEvent {
821 kind,
822 column: cx,
823 row: cy,
824 modifiers,
825 })))
826}
827
828fn parse_cb(cb: u8) -> Result<(MouseEventKind, Modifiers)> {
842 let button_number = (cb & 0b0000_0011) | ((cb & 0b1100_0000) >> 4);
843 let dragging = cb & 0b0010_0000 == 0b0010_0000;
844
845 let kind = match (button_number, dragging) {
846 (0, false) => MouseEventKind::Down(MouseButton::Left),
847 (1, false) => MouseEventKind::Down(MouseButton::Middle),
848 (2, false) => MouseEventKind::Down(MouseButton::Right),
849 (0, true) => MouseEventKind::Drag(MouseButton::Left),
850 (1, true) => MouseEventKind::Drag(MouseButton::Middle),
851 (2, true) => MouseEventKind::Drag(MouseButton::Right),
852 (3, false) => MouseEventKind::Up(MouseButton::Left),
853 (3, true) | (4, true) | (5, true) => MouseEventKind::Moved,
854 (4, false) => MouseEventKind::ScrollUp,
855 (5, false) => MouseEventKind::ScrollDown,
856 (6, false) => MouseEventKind::ScrollLeft,
857 (7, false) => MouseEventKind::ScrollRight,
858 _ => bail!(),
860 };
861
862 let mut modifiers = Modifiers::empty();
863
864 if cb & 0b0000_0100 == 0b0000_0100 {
865 modifiers |= Modifiers::SHIFT;
866 }
867 if cb & 0b0000_1000 == 0b0000_1000 {
868 modifiers |= Modifiers::ALT;
869 }
870 if cb & 0b0001_0000 == 0b0001_0000 {
871 modifiers |= Modifiers::CONTROL;
872 }
873
874 Ok((kind, modifiers))
875}
876
877fn parse_csi_bracketed_paste(buffer: &[u8]) -> Result<Option<Event>> {
878 assert!(buffer.starts_with(b"\x1B[200~"));
880
881 if !buffer.ends_with(b"\x1b[201~") {
882 Ok(None)
883 } else {
884 let paste = String::from_utf8_lossy(&buffer[6..buffer.len() - 6]).to_string();
885 Ok(Some(Event::Paste(paste)))
886 }
887}
888
889fn parse_csi_cursor_position(buffer: &[u8]) -> Result<Option<Event>> {
890 assert!(buffer.starts_with(b"\x1B[")); assert!(buffer.ends_with(b"R"));
895
896 let s = str::from_utf8(&buffer[2..buffer.len() - 1])?;
897
898 let mut split = s.split(';');
899
900 let line = next_parsed::<NonZeroU16>(&mut split)?.into();
901 let col = next_parsed::<NonZeroU16>(&mut split)?.into();
902
903 Ok(Some(Event::Csi(Csi::Cursor(
904 csi::Cursor::ActivePositionReport { line, col },
905 ))))
906}
907
908fn parse_csi_keyboard_enhancement_flags(buffer: &[u8]) -> Result<Option<Event>> {
909 assert!(buffer.starts_with(b"\x1B[?")); assert!(buffer.ends_with(b"u"));
912
913 if buffer.len() < 5 {
914 return Ok(None);
915 }
916
917 let bits = buffer[3];
918 let mut flags = KittyKeyboardFlags::empty();
919
920 if bits & 1 != 0 {
921 flags |= KittyKeyboardFlags::DISAMBIGUATE_ESCAPE_CODES;
922 }
923 if bits & 2 != 0 {
924 flags |= KittyKeyboardFlags::REPORT_EVENT_TYPES;
925 }
926 if bits & 4 != 0 {
927 flags |= KittyKeyboardFlags::REPORT_ALTERNATE_KEYS;
928 }
929 if bits & 8 != 0 {
930 flags |= KittyKeyboardFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES;
931 }
932 Ok(Some(Event::Csi(Csi::Keyboard(csi::Keyboard::ReportFlags(
938 flags,
939 )))))
940}
941
942fn parse_csi_primary_device_attributes(buffer: &[u8]) -> Result<Option<Event>> {
943 assert!(buffer.starts_with(b"\x1B[?"));
945 assert!(buffer.ends_with(b"c"));
946
947 Ok(Some(Event::Csi(Csi::Device(
952 csi::Device::DeviceAttributes(()),
953 ))))
954}
955
956fn parse_csi_theme_mode(buffer: &[u8]) -> Result<Option<Event>> {
957 assert!(buffer.starts_with(b"\x1B[?"));
960 assert!(buffer.ends_with(b"n"));
961
962 let s = str::from_utf8(&buffer[3..buffer.len() - 1])?;
963
964 let mut split = s.split(';');
965
966 if next_parsed::<u16>(&mut split)? != 997 {
967 bail!();
968 }
969
970 let theme_mode = match next_parsed::<u8>(&mut split)? {
971 1 => ThemeMode::Dark,
972 2 => ThemeMode::Light,
973 _ => bail!(),
974 };
975
976 Ok(Some(Event::Csi(Csi::Mode(csi::Mode::ReportTheme(
977 theme_mode,
978 )))))
979}
980
981fn parse_csi_synchronized_output_mode(buffer: &[u8]) -> Result<Option<Event>> {
982 assert!(buffer.starts_with(b"\x1B[?"));
984 assert!(buffer.ends_with(b"y"));
985
986 let s = str::from_utf8(&buffer[3..buffer.len() - 1])?;
987 let s = match s.strip_suffix('$') {
988 Some(s) => s,
989 None => bail!(),
990 };
991
992 let mut split = s.split(';');
993
994 let mode = csi::DecPrivateModeCode::SynchronizedOutput;
995 if next_parsed::<u16>(&mut split)? != mode as u16 {
996 bail!();
997 }
998
999 let setting = match next_parsed::<u8>(&mut split)? {
1002 0 | 4 => csi::DecModeSetting::NotRecognized,
1003 1 => csi::DecModeSetting::Set,
1004 2 => csi::DecModeSetting::Reset,
1005 _ => bail!(),
1006 };
1007
1008 Ok(Some(Event::Csi(Csi::Mode(
1009 csi::Mode::ReportDecPrivateMode {
1010 mode: csi::DecPrivateMode::Code(mode),
1011 setting,
1012 },
1013 ))))
1014}
1015
1016fn parse_dcs(buffer: &[u8]) -> Result<Option<Event>> {
1017 assert!(buffer.starts_with(escape::DCS.as_bytes()));
1018 if !buffer.ends_with(escape::ST.as_bytes()) {
1019 return Ok(None);
1020 }
1021 match buffer[buffer.len() - 3] {
1022 b'm' => {
1024 if buffer.get(3..5) != Some(b"$r") {
1025 bail!();
1026 }
1027 let is_request_valid = match buffer[2] {
1031 b'1' => true,
1032 b'0' => false,
1034 _ => bail!(),
1035 };
1036 let s = str::from_utf8(&buffer[5..buffer.len() - 3])?;
1037 let mut sgrs = Vec::new();
1038 for sgr in s.split(';') {
1040 sgrs.push(parse_sgr(sgr)?);
1041 }
1042 Ok(Some(Event::Dcs(dcs::Dcs::Response {
1043 is_request_valid,
1044 value: dcs::DcsResponse::GraphicRendition(sgrs),
1045 })))
1046 }
1047 _ => bail!(),
1048 }
1049}
1050
1051fn parse_sgr(buffer: &str) -> Result<csi::Sgr> {
1052 use csi::Sgr;
1053 use style::*;
1054
1055 let sgr = match buffer {
1056 "0" => Sgr::Reset,
1057 "22" => Sgr::Intensity(Intensity::Normal),
1058 "1" => Sgr::Intensity(Intensity::Bold),
1059 "2" => Sgr::Intensity(Intensity::Dim),
1060 "24" => Sgr::Underline(Underline::None),
1061 "4" => Sgr::Underline(Underline::Single),
1062 "21" => Sgr::Underline(Underline::Double),
1063 "4:3 " => Sgr::Underline(Underline::Curly),
1064 "4:4" => Sgr::Underline(Underline::Dotted),
1065 "4:5" => Sgr::Underline(Underline::Dashed),
1066 "25" => Sgr::Blink(Blink::None),
1067 "5" => Sgr::Blink(Blink::Slow),
1068 "6" => Sgr::Blink(Blink::Rapid),
1069 "3" => Sgr::Italic(true),
1070 "23" => Sgr::Italic(false),
1071 "7" => Sgr::Reverse(true),
1072 "27" => Sgr::Reverse(false),
1073 "8" => Sgr::Invisible(true),
1074 "28" => Sgr::Invisible(false),
1075 "9" => Sgr::StrikeThrough(true),
1076 "29" => Sgr::StrikeThrough(false),
1077 "53" => Sgr::Overline(true),
1078 "55" => Sgr::Overline(false),
1079 "10" => Sgr::Font(Font::Default),
1080 "11" => Sgr::Font(Font::Alternate(1)),
1081 "12" => Sgr::Font(Font::Alternate(2)),
1082 "13" => Sgr::Font(Font::Alternate(3)),
1083 "14" => Sgr::Font(Font::Alternate(4)),
1084 "15" => Sgr::Font(Font::Alternate(5)),
1085 "16" => Sgr::Font(Font::Alternate(6)),
1086 "17" => Sgr::Font(Font::Alternate(7)),
1087 "18" => Sgr::Font(Font::Alternate(8)),
1088 "19" => Sgr::Font(Font::Alternate(9)),
1089 "75" => Sgr::VerticalAlign(VerticalAlign::BaseLine),
1090 "73" => Sgr::VerticalAlign(VerticalAlign::SuperScript),
1091 "74" => Sgr::VerticalAlign(VerticalAlign::SubScript),
1092 "39" => Sgr::Foreground(ColorSpec::Reset),
1093 "30" => Sgr::Foreground(ColorSpec::BLACK),
1094 "31" => Sgr::Foreground(ColorSpec::RED),
1095 "32" => Sgr::Foreground(ColorSpec::GREEN),
1096 "33" => Sgr::Foreground(ColorSpec::YELLOW),
1097 "34" => Sgr::Foreground(ColorSpec::BLUE),
1098 "35" => Sgr::Foreground(ColorSpec::MAGENTA),
1099 "36" => Sgr::Foreground(ColorSpec::CYAN),
1100 "37" => Sgr::Foreground(ColorSpec::WHITE),
1101 "90" => Sgr::Foreground(ColorSpec::BRIGHT_BLACK),
1102 "91" => Sgr::Foreground(ColorSpec::BRIGHT_RED),
1103 "92" => Sgr::Foreground(ColorSpec::BRIGHT_GREEN),
1104 "93" => Sgr::Foreground(ColorSpec::BRIGHT_YELLOW),
1105 "94" => Sgr::Foreground(ColorSpec::BRIGHT_BLUE),
1106 "95" => Sgr::Foreground(ColorSpec::BRIGHT_MAGENTA),
1107 "96" => Sgr::Foreground(ColorSpec::BRIGHT_CYAN),
1108 "97" => Sgr::Foreground(ColorSpec::BRIGHT_WHITE),
1109 "49" => Sgr::Background(ColorSpec::Reset),
1110 "40" => Sgr::Background(ColorSpec::BLACK),
1111 "41" => Sgr::Background(ColorSpec::RED),
1112 "42" => Sgr::Background(ColorSpec::GREEN),
1113 "43" => Sgr::Background(ColorSpec::YELLOW),
1114 "44" => Sgr::Background(ColorSpec::BLUE),
1115 "45" => Sgr::Background(ColorSpec::MAGENTA),
1116 "46" => Sgr::Background(ColorSpec::CYAN),
1117 "47" => Sgr::Background(ColorSpec::WHITE),
1118 "100" => Sgr::Background(ColorSpec::BRIGHT_BLACK),
1119 "101" => Sgr::Background(ColorSpec::BRIGHT_RED),
1120 "102" => Sgr::Background(ColorSpec::BRIGHT_GREEN),
1121 "103" => Sgr::Background(ColorSpec::BRIGHT_YELLOW),
1122 "104" => Sgr::Background(ColorSpec::BRIGHT_BLUE),
1123 "105" => Sgr::Background(ColorSpec::BRIGHT_MAGENTA),
1124 "106" => Sgr::Background(ColorSpec::BRIGHT_CYAN),
1125 "107" => Sgr::Background(ColorSpec::BRIGHT_WHITE),
1126 "59" => Sgr::UnderlineColor(ColorSpec::Reset),
1127 _ => {
1128 let mut split = buffer.split(':').filter(|s| !s.is_empty());
1129 let first = next_parsed::<u8>(&mut split)?;
1130 let color = match next_parsed::<u8>(&mut split)? {
1131 2 => RgbColor {
1132 red: next_parsed::<u8>(&mut split)?,
1133 green: next_parsed::<u8>(&mut split)?,
1134 blue: next_parsed::<u8>(&mut split)?,
1135 }
1136 .into(),
1137 5 => ColorSpec::PaletteIndex(next_parsed::<u8>(&mut split)?),
1138 6 => RgbaColor {
1139 red: next_parsed::<u8>(&mut split)?,
1140 green: next_parsed::<u8>(&mut split)?,
1141 blue: next_parsed::<u8>(&mut split)?,
1142 alpha: next_parsed::<u8>(&mut split)?,
1143 }
1144 .into(),
1145 _ => bail!(),
1146 };
1147 match first {
1148 38 => Sgr::Foreground(color),
1149 48 => Sgr::Background(color),
1150 58 => Sgr::UnderlineColor(color),
1151 _ => bail!(),
1152 }
1153 }
1154 };
1155 Ok(sgr)
1156}
1157
1158#[cfg(test)]
1159mod test {
1160 use super::*;
1161
1162 #[test]
1163 fn parse_dcs_sgr_response() {
1164 let event = parse_event(b"\x1bP0$r0;4;5;7m\x1b\\", false)
1171 .unwrap()
1172 .unwrap();
1173 assert_eq!(
1174 event,
1175 Event::Dcs(dcs::Dcs::Response {
1176 is_request_valid: false,
1177 value: dcs::DcsResponse::GraphicRendition(vec![
1178 csi::Sgr::Reset,
1179 csi::Sgr::Underline(style::Underline::Single),
1180 csi::Sgr::Blink(style::Blink::Slow),
1181 csi::Sgr::Reverse(true),
1182 ])
1183 })
1184 );
1185 }
1186}