1use crossterm::event::{
7 Event, KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind,
8};
9
10#[derive(Debug)]
12pub struct InputParser {
13 buffer: Vec<u8>,
15 max_buffer_size: usize,
17 paste_buffer: Option<Vec<u8>>,
20}
21
22impl Default for InputParser {
23 fn default() -> Self {
24 Self::new()
25 }
26}
27
28impl InputParser {
29 pub fn new() -> Self {
30 Self {
31 buffer: Vec::with_capacity(32),
32 max_buffer_size: 256,
33 paste_buffer: None,
34 }
35 }
36
37 pub fn parse(&mut self, bytes: &[u8]) -> Vec<Event> {
49 let mut events = Vec::new();
50
51 if !bytes.is_empty() || !self.buffer.is_empty() {
52 tracing::trace!(
53 "InputParser.parse: input={} bytes, buffer={} bytes ({:02x?})",
54 bytes.len(),
55 self.buffer.len(),
56 &self.buffer,
57 );
58 }
59
60 if bytes.is_empty() {
71 return events;
72 }
73
74 for &byte in bytes {
75 if let Some(ref mut paste_buf) = self.paste_buffer {
77 paste_buf.push(byte);
78 if paste_buf.len() >= 6 && paste_buf.ends_with(b"\x1b[201~") {
80 let content_len = paste_buf.len() - 6;
82 let text = String::from_utf8_lossy(&paste_buf[..content_len]).into_owned();
83 self.paste_buffer = None;
84 events.push(Event::Paste(text));
85 }
86 continue;
87 }
88
89 self.buffer.push(byte);
90
91 match self.try_parse() {
93 ParseResult::Complete(event) => {
94 events.push(event);
95 self.buffer.clear();
96 }
97 ParseResult::PasteStart => {
98 self.paste_buffer = Some(Vec::new());
100 self.buffer.clear();
101 }
102 ParseResult::Incomplete => {
103 if self.buffer.len() > self.max_buffer_size {
105 for &b in &self.buffer {
107 if let Some(event) = self.byte_to_event(b) {
108 events.push(event);
109 }
110 }
111 self.buffer.clear();
112 }
113 }
114 ParseResult::Invalid => {
115 tracing::trace!(
117 "InputParser: Invalid sequence, buffer={:02x?}",
118 &self.buffer,
119 );
120 if !self.buffer.is_empty() {
121 let first = self.buffer[0];
122 if let Some(event) = self.byte_to_event(first) {
123 events.push(event);
124 }
125 let rest: Vec<u8> = self.buffer[1..].to_vec();
126 self.buffer.clear();
127 events.extend(self.parse(&rest));
129 }
130 }
131 }
132 }
133
134 events
135 }
136
137 fn try_parse(&self) -> ParseResult {
139 if self.buffer.is_empty() {
140 return ParseResult::Incomplete;
141 }
142
143 let bytes = &self.buffer;
144
145 if bytes[0] == 0x1b {
147 return self.parse_escape_sequence();
148 }
149
150 if is_utf8_start_byte(bytes[0]) {
152 return self.parse_utf8_sequence();
153 }
154
155 if let Some(event) = self.byte_to_event(bytes[0]) {
157 return ParseResult::Complete(event);
158 }
159
160 ParseResult::Invalid
161 }
162
163 fn parse_utf8_sequence(&self) -> ParseResult {
165 let bytes = &self.buffer;
166 let needed = utf8_char_width(bytes[0]);
167 if needed == 0 {
168 return ParseResult::Invalid;
169 }
170 if bytes.len() < needed {
171 return ParseResult::Incomplete;
172 }
173 match std::str::from_utf8(&bytes[..needed]) {
174 Ok(s) => {
175 if let Some(c) = s.chars().next() {
176 ParseResult::Complete(Event::Key(KeyEvent::new(
177 KeyCode::Char(c),
178 KeyModifiers::empty(),
179 )))
180 } else {
181 ParseResult::Invalid
182 }
183 }
184 Err(_) => ParseResult::Invalid,
185 }
186 }
187
188 fn parse_escape_sequence(&self) -> ParseResult {
190 let bytes = &self.buffer;
191
192 if bytes.len() < 2 {
193 return ParseResult::Incomplete;
194 }
195
196 match bytes[1] {
197 b'[' => self.parse_csi_sequence(),
199 b'O' => self.parse_ss3_sequence(),
201 0x1b => ParseResult::Invalid,
205 _ => {
207 let key = bytes[1];
208 let event = Event::Key(KeyEvent::new(byte_to_keycode(key), KeyModifiers::ALT));
209 ParseResult::Complete(event)
210 }
211 }
212 }
213
214 fn parse_csi_sequence(&self) -> ParseResult {
216 let bytes = &self.buffer;
217
218 if bytes.len() < 3 {
219 return ParseResult::Incomplete;
220 }
221
222 let final_idx = bytes[2..].iter().position(|&b| (0x40..=0x7E).contains(&b));
224
225 match final_idx {
226 None => {
227 let all_valid = bytes[2..].iter().all(|&b| (0x20..=0x3F).contains(&b));
229 if all_valid {
230 ParseResult::Incomplete
231 } else {
232 ParseResult::Invalid
233 }
234 }
235 Some(idx) => {
236 let final_byte = bytes[2 + idx];
237 let params = &bytes[2..2 + idx];
238
239 self.parse_csi_final(params, final_byte)
240 }
241 }
242 }
243
244 fn parse_csi_final(&self, params: &[u8], final_byte: u8) -> ParseResult {
246 match final_byte {
247 b'A' => ParseResult::Complete(Event::Key(KeyEvent::new(
249 KeyCode::Up,
250 self.parse_modifiers(params),
251 ))),
252 b'B' => ParseResult::Complete(Event::Key(KeyEvent::new(
253 KeyCode::Down,
254 self.parse_modifiers(params),
255 ))),
256 b'C' => ParseResult::Complete(Event::Key(KeyEvent::new(
257 KeyCode::Right,
258 self.parse_modifiers(params),
259 ))),
260 b'D' => ParseResult::Complete(Event::Key(KeyEvent::new(
261 KeyCode::Left,
262 self.parse_modifiers(params),
263 ))),
264 b'H' => ParseResult::Complete(Event::Key(KeyEvent::new(
265 KeyCode::Home,
266 self.parse_modifiers(params),
267 ))),
268 b'F' => ParseResult::Complete(Event::Key(KeyEvent::new(
269 KeyCode::End,
270 self.parse_modifiers(params),
271 ))),
272
273 b'~' => self.parse_tilde_sequence(params),
275
276 b'M' | b'm' => {
278 if !params.is_empty() && params[0] == b'<' {
279 self.parse_sgr_mouse(params, final_byte == b'M')
280 } else {
281 self.parse_x10_mouse()
283 }
284 }
285
286 b'Z' => ParseResult::Complete(Event::Key(KeyEvent::new(
288 KeyCode::BackTab,
289 KeyModifiers::SHIFT,
290 ))),
291
292 b'I' => ParseResult::Complete(Event::FocusGained),
294 b'O' => ParseResult::Complete(Event::FocusLost),
295
296 b'u' => self.parse_csi_u_sequence(params),
298
299 _ => ParseResult::Invalid,
300 }
301 }
302
303 fn parse_tilde_sequence(&self, params: &[u8]) -> ParseResult {
305 let params_str = std::str::from_utf8(params).unwrap_or("");
306 let parts: Vec<&str> = params_str.split(';').collect();
307
308 if parts.len() == 3 && parts[0] == "27" {
310 let mods_param: u8 = parts[1].parse().unwrap_or(1);
311 let codepoint: u32 = parts[2].parse().unwrap_or(0);
312 let modifiers = modifiers_from_param(mods_param);
313
314 let keycode = match codepoint {
315 9 => KeyCode::Tab,
316 13 => KeyCode::Enter,
317 27 => KeyCode::Esc,
318 127 => KeyCode::Backspace,
319 cp => match char::from_u32(cp) {
320 Some(c) => KeyCode::Char(c),
321 None => return ParseResult::Invalid,
322 },
323 };
324
325 return ParseResult::Complete(Event::Key(KeyEvent::new(keycode, modifiers)));
326 }
327
328 let (num, modifiers) = self.parse_num_and_modifiers(params);
329
330 if num == 200 {
332 return ParseResult::PasteStart;
333 }
334
335 if num == 201 {
338 return ParseResult::Complete(Event::Key(KeyEvent::new(
339 KeyCode::Null,
340 KeyModifiers::empty(),
341 )));
342 }
343
344 let keycode = match num {
345 1 => KeyCode::Home,
346 2 => KeyCode::Insert,
347 3 => KeyCode::Delete,
348 4 => KeyCode::End,
349 5 => KeyCode::PageUp,
350 6 => KeyCode::PageDown,
351 7 => KeyCode::Home,
352 8 => KeyCode::End,
353 11 => KeyCode::F(1),
354 12 => KeyCode::F(2),
355 13 => KeyCode::F(3),
356 14 => KeyCode::F(4),
357 15 => KeyCode::F(5),
358 17 => KeyCode::F(6),
359 18 => KeyCode::F(7),
360 19 => KeyCode::F(8),
361 20 => KeyCode::F(9),
362 21 => KeyCode::F(10),
363 23 => KeyCode::F(11),
364 24 => KeyCode::F(12),
365 _ => return ParseResult::Invalid,
366 };
367
368 ParseResult::Complete(Event::Key(KeyEvent::new(keycode, modifiers)))
369 }
370
371 fn parse_csi_u_sequence(&self, params: &[u8]) -> ParseResult {
377 let params_str = std::str::from_utf8(params).unwrap_or("");
378 let parts: Vec<&str> = params_str.split(';').collect();
379
380 let codepoint: u32 = parts.first().and_then(|s| s.parse().ok()).unwrap_or(0);
381 let mods_param: u8 = parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(1);
382 let modifiers = modifiers_from_param(mods_param);
383
384 let keycode = match codepoint {
385 9 => KeyCode::Tab,
386 13 => KeyCode::Enter,
387 27 => KeyCode::Esc,
388 127 => KeyCode::Backspace,
389 cp => match char::from_u32(cp) {
390 Some(c) => KeyCode::Char(c),
391 None => return ParseResult::Invalid,
392 },
393 };
394
395 ParseResult::Complete(Event::Key(KeyEvent::new(keycode, modifiers)))
396 }
397
398 fn parse_sgr_mouse(&self, params: &[u8], pressed: bool) -> ParseResult {
400 let params_str = std::str::from_utf8(¶ms[1..]).unwrap_or("");
402 let parts: Vec<&str> = params_str.split(';').collect();
403
404 if parts.len() != 3 {
405 return ParseResult::Invalid;
406 }
407
408 let cb: u16 = parts[0].parse().unwrap_or(0);
409 let cx: u16 = parts[1].parse().unwrap_or(1);
410 let cy: u16 = parts[2].parse().unwrap_or(1);
411
412 let button_bits = cb & 0b11;
413 let button = match button_bits {
414 0 => MouseButton::Left,
415 1 => MouseButton::Middle,
416 2 => MouseButton::Right,
417 _ => MouseButton::Left, };
419
420 let modifiers = KeyModifiers::from_bits_truncate(
421 if cb & 4 != 0 {
422 KeyModifiers::SHIFT.bits()
423 } else {
424 0
425 } | if cb & 8 != 0 {
426 KeyModifiers::ALT.bits()
427 } else {
428 0
429 } | if cb & 16 != 0 {
430 KeyModifiers::CONTROL.bits()
431 } else {
432 0
433 },
434 );
435
436 let kind = if cb & 32 != 0 {
437 if cb & 64 != 0 {
439 if cb & 1 != 0 {
441 MouseEventKind::ScrollDown
442 } else {
443 MouseEventKind::ScrollUp
444 }
445 } else if button_bits == 3 {
446 MouseEventKind::Moved
448 } else {
449 MouseEventKind::Drag(button)
451 }
452 } else if cb & 64 != 0 {
453 if cb & 1 != 0 {
455 MouseEventKind::ScrollDown
456 } else {
457 MouseEventKind::ScrollUp
458 }
459 } else if pressed {
460 MouseEventKind::Down(button)
461 } else {
462 MouseEventKind::Up(button)
463 };
464
465 ParseResult::Complete(Event::Mouse(MouseEvent {
466 kind,
467 column: cx.saturating_sub(1),
468 row: cy.saturating_sub(1),
469 modifiers,
470 }))
471 }
472
473 fn parse_x10_mouse(&self) -> ParseResult {
475 let bytes = &self.buffer;
476
477 if bytes.len() < 6 {
478 return ParseResult::Incomplete;
479 }
480
481 let cb = bytes[3].wrapping_sub(32);
482 let cx = bytes[4].wrapping_sub(32);
483 let cy = bytes[5].wrapping_sub(32);
484
485 let button = match cb & 0b11 {
486 0 => MouseButton::Left,
487 1 => MouseButton::Middle,
488 2 => MouseButton::Right,
489 3 => {
490 return ParseResult::Complete(Event::Mouse(MouseEvent {
492 kind: MouseEventKind::Up(MouseButton::Left),
493 column: cx as u16,
494 row: cy as u16,
495 modifiers: KeyModifiers::empty(),
496 }));
497 }
498 _ => MouseButton::Left,
499 };
500
501 ParseResult::Complete(Event::Mouse(MouseEvent {
502 kind: MouseEventKind::Down(button),
503 column: cx as u16,
504 row: cy as u16,
505 modifiers: KeyModifiers::empty(),
506 }))
507 }
508
509 fn parse_ss3_sequence(&self) -> ParseResult {
511 let bytes = &self.buffer;
512
513 if bytes.len() < 3 {
514 return ParseResult::Incomplete;
515 }
516
517 let keycode = match bytes[2] {
518 b'P' => KeyCode::F(1),
519 b'Q' => KeyCode::F(2),
520 b'R' => KeyCode::F(3),
521 b'S' => KeyCode::F(4),
522 b'A' => KeyCode::Up,
523 b'B' => KeyCode::Down,
524 b'C' => KeyCode::Right,
525 b'D' => KeyCode::Left,
526 b'H' => KeyCode::Home,
527 b'F' => KeyCode::End,
528 _ => return ParseResult::Invalid,
529 };
530
531 ParseResult::Complete(Event::Key(KeyEvent::new(keycode, KeyModifiers::empty())))
532 }
533
534 fn parse_modifiers(&self, params: &[u8]) -> KeyModifiers {
536 let params_str = std::str::from_utf8(params).unwrap_or("");
538 if let Some(idx) = params_str.find(';') {
539 if let Ok(mods) = params_str[idx + 1..].parse::<u8>() {
540 return modifiers_from_param(mods);
541 }
542 }
543 KeyModifiers::empty()
544 }
545
546 fn parse_num_and_modifiers(&self, params: &[u8]) -> (u8, KeyModifiers) {
548 let params_str = std::str::from_utf8(params).unwrap_or("");
549 let parts: Vec<&str> = params_str.split(';').collect();
550
551 let num = parts.first().and_then(|s| s.parse().ok()).unwrap_or(0);
552 let mods = parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(1);
553
554 (num, modifiers_from_param(mods))
555 }
556
557 fn byte_to_event(&self, byte: u8) -> Option<Event> {
559 let keycode = byte_to_keycode(byte);
560 let modifiers = if byte < 32 && byte != 9 && byte != 10 && byte != 13 && byte != 27 {
561 KeyModifiers::CONTROL
563 } else {
564 KeyModifiers::empty()
565 };
566
567 Some(Event::Key(KeyEvent::new(keycode, modifiers)))
568 }
569}
570
571fn is_utf8_start_byte(b: u8) -> bool {
574 matches!(b, 0xC2..=0xDF | 0xE0..=0xEF | 0xF0..=0xF7)
575}
576
577fn utf8_char_width(first_byte: u8) -> usize {
580 match first_byte {
581 0xC2..=0xDF => 2,
582 0xE0..=0xEF => 3,
583 0xF0..=0xF7 => 4,
584 _ => 0,
585 }
586}
587
588enum ParseResult {
590 Complete(Event),
592 PasteStart,
594 Incomplete,
596 Invalid,
598}
599
600fn byte_to_keycode(byte: u8) -> KeyCode {
602 match byte {
603 0 => KeyCode::Char('@'), 9 => KeyCode::Tab,
605 10 | 13 => KeyCode::Enter, 1..=26 => KeyCode::Char((b'a' + byte - 1) as char), 27 => KeyCode::Esc,
608 28..=31 => KeyCode::Char((b'\\' + byte - 28) as char),
609 32 => KeyCode::Char(' '),
610 127 => KeyCode::Backspace,
611 b if (32..127).contains(&b) => KeyCode::Char(b as char),
612 _ => KeyCode::Null,
613 }
614}
615
616fn modifiers_from_param(param: u8) -> KeyModifiers {
618 let param = param.saturating_sub(1);
619 KeyModifiers::from_bits_truncate(
620 if param & 1 != 0 {
621 KeyModifiers::SHIFT.bits()
622 } else {
623 0
624 } | if param & 2 != 0 {
625 KeyModifiers::ALT.bits()
626 } else {
627 0
628 } | if param & 4 != 0 {
629 KeyModifiers::CONTROL.bits()
630 } else {
631 0
632 },
633 )
634}
635
636#[cfg(test)]
637mod tests {
638 use super::*;
639
640 #[test]
641 fn test_simple_characters() {
642 let mut parser = InputParser::new();
643 let events = parser.parse(b"abc");
644 assert_eq!(events.len(), 3);
645 match &events[0] {
646 Event::Key(ke) => assert_eq!(ke.code, KeyCode::Char('a')),
647 _ => panic!("Expected key event"),
648 }
649 }
650
651 #[test]
652 fn test_control_characters_have_ctrl_modifier() {
653 let mut parser = InputParser::new();
654 let events = parser.parse(&[0x03]);
656 match &events[0] {
657 Event::Key(ke) => {
658 assert_eq!(ke.code, KeyCode::Char('c'));
659 assert!(ke.modifiers.contains(KeyModifiers::CONTROL));
660 }
661 _ => panic!("Expected key event"),
662 }
663 }
664
665 #[test]
666 fn test_escape_buffers_until_complete() {
667 let mut parser = InputParser::new();
668 assert!(parser.parse(&[0x1b]).is_empty());
670 assert!(parser.parse(b"[").is_empty());
672 let events = parser.parse(b"A");
674 assert_eq!(events.len(), 1);
675 match &events[0] {
676 Event::Key(ke) => assert_eq!(ke.code, KeyCode::Up),
677 _ => panic!("Expected Up key"),
678 }
679 }
680
681 #[test]
682 fn test_csi_sequences_parse_arrow_keys() {
683 let mut parser = InputParser::new();
684 let events = parser.parse(b"\x1b[A");
686 match &events[0] {
687 Event::Key(ke) => assert_eq!(ke.code, KeyCode::Up),
688 _ => panic!("Expected key event"),
689 }
690 }
691
692 #[test]
693 fn test_ss3_sequences_parse_function_keys() {
694 let mut parser = InputParser::new();
695 let events = parser.parse(b"\x1bOP");
697 match &events[0] {
698 Event::Key(ke) => assert_eq!(ke.code, KeyCode::F(1)),
699 _ => panic!("Expected key event"),
700 }
701 }
702
703 #[test]
704 fn test_alt_key_via_esc_prefix() {
705 let mut parser = InputParser::new();
706 let events = parser.parse(b"\x1ba");
708 match &events[0] {
709 Event::Key(ke) => {
710 assert_eq!(ke.code, KeyCode::Char('a'));
711 assert!(ke.modifiers.contains(KeyModifiers::ALT));
712 }
713 _ => panic!("Expected key event"),
714 }
715 }
716
717 #[test]
718 fn test_csi_modifiers_parsed_correctly() {
719 let mut parser = InputParser::new();
720 let events = parser.parse(b"\x1b[1;2A");
722 match &events[0] {
723 Event::Key(ke) => {
724 assert_eq!(ke.code, KeyCode::Up);
725 assert!(ke.modifiers.contains(KeyModifiers::SHIFT));
726 }
727 _ => panic!("Expected Shift+Up"),
728 }
729 }
730
731 #[test]
732 fn test_sgr_mouse_events_are_1_indexed() {
733 let mut parser = InputParser::new();
734 let events = parser.parse(b"\x1b[<0;10;5M");
737 match &events[0] {
738 Event::Mouse(me) => {
739 assert_eq!(me.column, 9); assert_eq!(me.row, 4); }
742 _ => panic!("Expected mouse event"),
743 }
744 }
745
746 #[test]
747 fn test_focus_events() {
748 let mut parser = InputParser::new();
749 let events = parser.parse(b"\x1b[I");
750 assert!(matches!(&events[0], Event::FocusGained));
751
752 let events = parser.parse(b"\x1b[O");
753 assert!(matches!(&events[0], Event::FocusLost));
754 }
755
756 #[test]
757 fn test_mixed_input_preserves_order() {
758 let mut parser = InputParser::new();
759 let events = parser.parse(b"a\x1b[Ab");
760 assert_eq!(events.len(), 3);
761 assert!(matches!(&events[0], Event::Key(ke) if ke.code == KeyCode::Char('a')));
763 assert!(matches!(&events[1], Event::Key(ke) if ke.code == KeyCode::Up));
764 assert!(matches!(&events[2], Event::Key(ke) if ke.code == KeyCode::Char('b')));
765 }
766
767 #[test]
768 fn test_enter_key() {
769 let mut parser = InputParser::new();
770 let events = parser.parse(&[0x0D]);
772 match &events[0] {
773 Event::Key(ke) => {
774 assert_eq!(ke.code, KeyCode::Enter);
775 assert!(ke.modifiers.is_empty());
776 }
777 _ => panic!("Expected Enter key event"),
778 }
779
780 let events = parser.parse(&[0x0A]);
782 match &events[0] {
783 Event::Key(ke) => {
784 assert_eq!(ke.code, KeyCode::Enter);
785 assert!(ke.modifiers.is_empty());
786 }
787 _ => panic!("Expected Enter key event"),
788 }
789 }
790
791 #[test]
792 fn test_tab_key() {
793 let mut parser = InputParser::new();
794 let events = parser.parse(&[0x09]);
796 match &events[0] {
797 Event::Key(ke) => {
798 assert_eq!(ke.code, KeyCode::Tab);
799 assert!(ke.modifiers.is_empty());
800 }
801 _ => panic!("Expected Tab key event"),
802 }
803 }
804
805 #[test]
806 fn test_mouse_motion_without_button() {
807 let mut parser = InputParser::new();
808 let events = parser.parse(b"\x1b[<35;10;5M");
811 match &events[0] {
812 Event::Mouse(me) => {
813 assert!(matches!(me.kind, MouseEventKind::Moved));
814 assert_eq!(me.column, 9); assert_eq!(me.row, 4); }
817 _ => panic!("Expected mouse motion event"),
818 }
819 }
820
821 #[test]
824 fn test_shift_tab_csi_z() {
825 let mut parser = InputParser::new();
826 let events = parser.parse(b"\x1b[Z");
828 assert_eq!(events.len(), 1);
829 match &events[0] {
830 Event::Key(ke) => {
831 assert_eq!(ke.code, KeyCode::BackTab);
832 assert!(ke.modifiers.contains(KeyModifiers::SHIFT));
833 }
834 _ => panic!("Expected BackTab key event, got {:?}", events[0]),
835 }
836 }
837
838 #[test]
839 fn test_esc_then_mouse_event_same_chunk() {
840 let mut parser = InputParser::new();
841 let events = parser.parse(b"\x1b\x1b[<35;67;18M");
844 assert_eq!(
845 events.len(),
846 2,
847 "Expected Escape + mouse event, got: {:?}",
848 events
849 );
850
851 match &events[0] {
853 Event::Key(ke) => {
854 assert_eq!(ke.code, KeyCode::Esc);
855 assert!(ke.modifiers.is_empty());
856 }
857 _ => panic!("Expected Esc key event, got {:?}", events[0]),
858 }
859
860 match &events[1] {
862 Event::Mouse(me) => {
863 assert!(matches!(me.kind, MouseEventKind::Moved));
864 assert_eq!(me.column, 66); assert_eq!(me.row, 17); }
867 _ => panic!("Expected mouse motion event, got {:?}", events[1]),
868 }
869 }
870
871 #[test]
872 fn test_esc_then_mouse_event_separate_chunks() {
873 let mut parser = InputParser::new();
874
875 let events = parser.parse(&[0x1b]);
877 assert!(events.is_empty(), "ESC should be buffered");
878
879 let events = parser.parse(b"\x1b[<35;67;18M");
881 assert_eq!(
882 events.len(),
883 2,
884 "Expected Escape + mouse event, got: {:?}",
885 events
886 );
887
888 match &events[0] {
890 Event::Key(ke) => {
891 assert_eq!(ke.code, KeyCode::Esc);
892 assert!(ke.modifiers.is_empty());
893 }
894 _ => panic!("Expected Esc key event, got {:?}", events[0]),
895 }
896
897 match &events[1] {
899 Event::Mouse(me) => {
900 assert!(matches!(me.kind, MouseEventKind::Moved));
901 }
902 _ => panic!("Expected mouse motion event, got {:?}", events[1]),
903 }
904 }
905
906 #[test]
907 fn test_esc_then_csi_arrow_separate_chunks() {
908 let mut parser = InputParser::new();
909
910 let events = parser.parse(&[0x1b]);
912 assert!(events.is_empty());
913
914 let events = parser.parse(b"\x1b[A");
916 assert_eq!(events.len(), 2, "Expected Escape + Up, got: {:?}", events);
917
918 match &events[0] {
919 Event::Key(ke) => assert_eq!(ke.code, KeyCode::Esc),
920 _ => panic!("Expected Esc"),
921 }
922 match &events[1] {
923 Event::Key(ke) => assert_eq!(ke.code, KeyCode::Up),
924 _ => panic!("Expected Up"),
925 }
926 }
927
928 #[test]
929 fn test_esc_waits_for_next_byte() {
930 let mut parser = InputParser::new();
931
932 let events = parser.parse(&[0x1b]);
934 assert!(events.is_empty());
935
936 assert_eq!(parser.buffer.len(), 1);
938
939 let events = parser.parse(b"[A");
941 assert_eq!(events.len(), 1);
942 match &events[0] {
943 Event::Key(ke) => assert_eq!(ke.code, KeyCode::Up),
944 _ => panic!("Expected Up"),
945 }
946 }
947
948 #[test]
949 fn test_esc_then_printable_byte_emits_alt_key() {
950 let mut parser = InputParser::new();
951
952 let events = parser.parse(&[0x1b]);
954 assert!(events.is_empty());
955
956 let events = parser.parse(b"a");
958 assert_eq!(events.len(), 1);
959 match &events[0] {
960 Event::Key(ke) => {
961 assert_eq!(ke.code, KeyCode::Char('a'));
962 assert!(ke.modifiers.contains(KeyModifiers::ALT));
963 }
964 _ => panic!("Expected Alt+a"),
965 }
966 }
967
968 #[test]
969 fn test_esc_then_esc_emits_standalone_esc() {
970 let mut parser = InputParser::new();
971
972 let events = parser.parse(&[0x1b]);
974 assert!(events.is_empty());
975
976 let events = parser.parse(&[0x1b]);
978 assert_eq!(events.len(), 1);
979 match &events[0] {
980 Event::Key(ke) => {
981 assert_eq!(ke.code, KeyCode::Esc);
982 assert!(ke.modifiers.is_empty());
983 }
984 _ => panic!("Expected standalone Esc"),
985 }
986 assert_eq!(parser.buffer, vec![0x1b]);
988 }
989
990 #[test]
991 fn test_split_mouse_sequence_across_batches() {
992 let mut parser = InputParser::new();
993
994 let events = parser.parse(&[0x1b]);
996 assert!(events.is_empty());
997 assert_eq!(parser.buffer.len(), 1);
998
999 let events = parser.parse(b"[<35;42;5M");
1001 assert_eq!(events.len(), 1);
1002 match &events[0] {
1003 Event::Mouse(_) => {} other => panic!("Expected mouse event, got {:?}", other),
1005 }
1006 }
1007
1008 #[test]
1009 fn test_partial_csi_sequence_not_flushed() {
1010 let mut parser = InputParser::new();
1011
1012 let events = parser.parse(b"\x1b[<35;");
1014 assert!(events.is_empty());
1015 assert_eq!(parser.buffer.len(), 6);
1016
1017 let events = parser.parse(b"42;5M");
1019 assert_eq!(events.len(), 1);
1020 match &events[0] {
1021 Event::Mouse(me) => {
1022 assert_eq!(me.column, 41); assert_eq!(me.row, 4); }
1025 _ => panic!("Expected mouse event, got {:?}", events[0]),
1026 }
1027 }
1028
1029 #[test]
1030 fn test_esc_then_mouse_click() {
1031 let mut parser = InputParser::new();
1032 let events = parser.parse(b"\x1b\x1b[<0;10;5M");
1034 assert_eq!(
1035 events.len(),
1036 2,
1037 "Expected Escape + mouse click, got: {:?}",
1038 events
1039 );
1040
1041 match &events[0] {
1042 Event::Key(ke) => assert_eq!(ke.code, KeyCode::Esc),
1043 _ => panic!("Expected Esc"),
1044 }
1045 match &events[1] {
1046 Event::Mouse(me) => {
1047 assert!(matches!(me.kind, MouseEventKind::Down(MouseButton::Left)));
1048 }
1049 _ => panic!("Expected mouse down event, got {:?}", events[1]),
1050 }
1051 }
1052
1053 #[test]
1056 fn test_bracketed_paste_simple() {
1057 let mut parser = InputParser::new();
1058 let events = parser.parse(b"\x1b[200~Hello, world!\x1b[201~");
1060 assert_eq!(events.len(), 1, "Expected 1 paste event, got: {:?}", events);
1061 match &events[0] {
1062 Event::Paste(text) => assert_eq!(text, "Hello, world!"),
1063 _ => panic!("Expected Paste event, got {:?}", events[0]),
1064 }
1065 }
1066
1067 #[test]
1068 fn test_bracketed_paste_with_newlines() {
1069 let mut parser = InputParser::new();
1070 let events = parser.parse(b"\x1b[200~line1\nline2\nline3\x1b[201~");
1071 assert_eq!(events.len(), 1);
1072 match &events[0] {
1073 Event::Paste(text) => assert_eq!(text, "line1\nline2\nline3"),
1074 _ => panic!("Expected Paste event"),
1075 }
1076 }
1077
1078 #[test]
1079 fn test_bracketed_paste_split_across_chunks() {
1080 let mut parser = InputParser::new();
1081
1082 let events = parser.parse(b"\x1b[200~Hello");
1084 assert!(events.is_empty(), "Paste not complete yet");
1085
1086 let events = parser.parse(b", world!");
1088 assert!(events.is_empty(), "Paste not complete yet");
1089
1090 let events = parser.parse(b"\x1b[201~");
1092 assert_eq!(events.len(), 1);
1093 match &events[0] {
1094 Event::Paste(text) => assert_eq!(text, "Hello, world!"),
1095 _ => panic!("Expected Paste event"),
1096 }
1097 }
1098
1099 #[test]
1100 fn test_bracketed_paste_followed_by_keypress() {
1101 let mut parser = InputParser::new();
1102 let events = parser.parse(b"\x1b[200~pasted\x1b[201~a");
1104 assert_eq!(
1105 events.len(),
1106 2,
1107 "Expected paste + key event, got: {:?}",
1108 events
1109 );
1110 match &events[0] {
1111 Event::Paste(text) => assert_eq!(text, "pasted"),
1112 _ => panic!("Expected Paste event"),
1113 }
1114 match &events[1] {
1115 Event::Key(ke) => assert_eq!(ke.code, KeyCode::Char('a')),
1116 _ => panic!("Expected key event"),
1117 }
1118 }
1119
1120 #[test]
1121 fn test_bracketed_paste_empty() {
1122 let mut parser = InputParser::new();
1123 let events = parser.parse(b"\x1b[200~\x1b[201~");
1124 assert_eq!(events.len(), 1);
1125 match &events[0] {
1126 Event::Paste(text) => assert_eq!(text, ""),
1127 _ => panic!("Expected empty Paste event"),
1128 }
1129 }
1130
1131 #[test]
1132 fn test_bracketed_paste_with_escape_sequences_inside() {
1133 let mut parser = InputParser::new();
1134 let events = parser.parse(b"\x1b[200~\x1b[31mred text\x1b[0m\x1b[201~");
1136 assert_eq!(events.len(), 1);
1137 match &events[0] {
1138 Event::Paste(text) => assert_eq!(text, "\x1b[31mred text\x1b[0m"),
1139 _ => panic!("Expected Paste event with escape sequences"),
1140 }
1141 }
1142
1143 #[test]
1144 fn test_keypress_then_bracketed_paste() {
1145 let mut parser = InputParser::new();
1146 let events = parser.parse(b"x\x1b[200~pasted\x1b[201~");
1147 assert_eq!(events.len(), 2);
1148 match &events[0] {
1149 Event::Key(ke) => assert_eq!(ke.code, KeyCode::Char('x')),
1150 _ => panic!("Expected key event"),
1151 }
1152 match &events[1] {
1153 Event::Paste(text) => assert_eq!(text, "pasted"),
1154 _ => panic!("Expected Paste event"),
1155 }
1156 }
1157
1158 #[test]
1161 fn test_utf8_three_byte_chinese_char() {
1162 let mut parser = InputParser::new();
1163 let events = parser.parse(&[0xE4, 0xB8, 0xAD]);
1165 assert_eq!(events.len(), 1);
1166 match &events[0] {
1167 Event::Key(ke) => {
1168 assert_eq!(ke.code, KeyCode::Char('中'));
1169 assert!(ke.modifiers.is_empty());
1170 }
1171 _ => panic!("Expected key event for '中'"),
1172 }
1173 }
1174
1175 #[test]
1176 fn test_utf8_two_byte_char() {
1177 let mut parser = InputParser::new();
1178 let events = parser.parse(&[0xC3, 0xA9]);
1180 assert_eq!(events.len(), 1);
1181 match &events[0] {
1182 Event::Key(ke) => {
1183 assert_eq!(ke.code, KeyCode::Char('é'));
1184 assert!(ke.modifiers.is_empty());
1185 }
1186 _ => panic!("Expected key event for 'é'"),
1187 }
1188 }
1189
1190 #[test]
1191 fn test_utf8_four_byte_emoji() {
1192 let mut parser = InputParser::new();
1193 let events = parser.parse(&[0xF0, 0x9F, 0x98, 0x80]);
1195 assert_eq!(events.len(), 1);
1196 match &events[0] {
1197 Event::Key(ke) => {
1198 assert_eq!(ke.code, KeyCode::Char('😀'));
1199 assert!(ke.modifiers.is_empty());
1200 }
1201 _ => panic!("Expected key event for '😀'"),
1202 }
1203 }
1204
1205 #[test]
1206 fn test_utf8_incomplete_sequence_returns_no_events() {
1207 let mut parser = InputParser::new();
1208 let events = parser.parse(&[0xE4]);
1210 assert!(
1211 events.is_empty(),
1212 "Incomplete UTF-8 sequence should produce no events"
1213 );
1214 }
1215
1216 #[test]
1217 fn test_utf8_sequence_split_across_batches() {
1218 let mut parser = InputParser::new();
1219 let events = parser.parse(&[0xE4]);
1221 assert!(events.is_empty(), "Should buffer leading byte");
1222
1223 let events = parser.parse(&[0xB8, 0xAD]);
1225 assert_eq!(events.len(), 1);
1226 match &events[0] {
1227 Event::Key(ke) => assert_eq!(ke.code, KeyCode::Char('中')),
1228 _ => panic!("Expected key event for '中'"),
1229 }
1230 }
1231
1232 #[test]
1233 fn test_utf8_invalid_continuation_byte_does_not_panic() {
1234 let mut parser = InputParser::new();
1235 let events = parser.parse(&[0xE4, 0x00, 0xAD]);
1237 assert!(
1239 !events.is_empty(),
1240 "Invalid sequence should emit events (graceful recovery)"
1241 );
1242 }
1243
1244 #[test]
1245 fn test_overlong_encoding_0xc0_rejected() {
1246 let mut parser = InputParser::new();
1247 let events = parser.parse(&[0xC0, 0x80]);
1250 let _ = events;
1252 }
1253
1254 #[test]
1255 fn test_overlong_encoding_0xc1_rejected() {
1256 let mut parser = InputParser::new();
1257 let events = parser.parse(&[0xC1, 0xA0]);
1259 let _ = events;
1261 }
1262}