1use std::io::{self, Write};
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
22pub struct Modifiers {
23 pub ctrl: bool,
25 pub alt: bool,
27 pub shift: bool,
29}
30
31impl Modifiers {
32 pub const NONE: Self = Self {
34 ctrl: false,
35 alt: false,
36 shift: false,
37 };
38
39 pub const CTRL: Self = Self {
41 ctrl: true,
42 alt: false,
43 shift: false,
44 };
45
46 pub const ALT: Self = Self {
48 ctrl: false,
49 alt: true,
50 shift: false,
51 };
52
53 pub const SHIFT: Self = Self {
55 ctrl: false,
56 alt: false,
57 shift: true,
58 };
59
60 #[must_use]
62 pub const fn any(self) -> bool {
63 self.ctrl || self.alt || self.shift
64 }
65
66 #[must_use]
69 pub fn csi_param(self) -> u8 {
70 let mut param = 1u8;
71 if self.shift {
72 param += 1;
73 }
74 if self.alt {
75 param += 2;
76 }
77 if self.ctrl {
78 param += 4;
79 }
80 param
81 }
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86pub enum Key {
87 Char(char),
89 F(u8),
91 Backspace,
93 Enter,
95 Tab,
97 Escape,
99 Up,
101 Down,
103 Left,
105 Right,
107 Home,
109 End,
111 PageUp,
113 PageDown,
115 Insert,
117 Delete,
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123pub struct KeyEvent {
124 pub key: Key,
126 pub modifiers: Modifiers,
128}
129
130impl KeyEvent {
131 #[must_use]
133 pub const fn new(key: Key, modifiers: Modifiers) -> Self {
134 Self { key, modifiers }
135 }
136
137 #[must_use]
139 pub const fn plain(key: Key) -> Self {
140 Self {
141 key,
142 modifiers: Modifiers::NONE,
143 }
144 }
145}
146
147impl From<char> for KeyEvent {
148 fn from(c: char) -> Self {
149 Self::plain(Key::Char(c))
150 }
151}
152
153#[must_use]
171pub fn key_to_sequence(event: KeyEvent) -> Vec<u8> {
172 let KeyEvent { key, modifiers } = event;
173
174 match key {
175 Key::Char(c) => char_sequence(c, modifiers),
176 Key::F(n) => function_key_sequence(n, modifiers),
177 Key::Backspace => backspace_sequence(modifiers),
178 Key::Enter => enter_sequence(modifiers),
179 Key::Tab => tab_sequence(modifiers),
180 Key::Escape => escape_sequence(modifiers),
181 Key::Up => cursor_key_sequence(b'A', modifiers),
182 Key::Down => cursor_key_sequence(b'B', modifiers),
183 Key::Right => cursor_key_sequence(b'C', modifiers),
184 Key::Left => cursor_key_sequence(b'D', modifiers),
185 Key::Home => home_end_sequence(b'H', modifiers),
186 Key::End => home_end_sequence(b'F', modifiers),
187 Key::PageUp => page_key_sequence(5, modifiers),
188 Key::PageDown => page_key_sequence(6, modifiers),
189 Key::Insert => insert_delete_sequence(2, modifiers),
190 Key::Delete => insert_delete_sequence(3, modifiers),
191 }
192}
193
194fn char_sequence(c: char, modifiers: Modifiers) -> Vec<u8> {
196 if modifiers.ctrl
198 && !modifiers.alt
199 && let Some(ctrl_byte) = ctrl_char(c)
200 {
201 return vec![ctrl_byte];
202 }
203
204 if modifiers.alt && !modifiers.ctrl {
206 let mut seq = vec![0x1b]; let ch = if modifiers.shift {
208 c.to_ascii_uppercase()
209 } else {
210 c
211 };
212 let mut buf = [0u8; 4];
213 seq.extend_from_slice(ch.encode_utf8(&mut buf).as_bytes());
214 return seq;
215 }
216
217 if modifiers.ctrl
219 && modifiers.alt
220 && let Some(ctrl_byte) = ctrl_char(c)
221 {
222 return vec![0x1b, ctrl_byte]; }
224
225 let ch = if modifiers.shift {
227 c.to_ascii_uppercase()
228 } else {
229 c
230 };
231 let mut buf = [0u8; 4];
232 ch.encode_utf8(&mut buf).as_bytes().to_vec()
233}
234
235fn ctrl_char(c: char) -> Option<u8> {
237 match c.to_ascii_lowercase() {
238 'a'..='z' => Some(c.to_ascii_lowercase() as u8 - b'a' + 1),
239 '[' | '3' => Some(0x1b), '\\' | '4' => Some(0x1c), ']' | '5' => Some(0x1d), '^' | '6' => Some(0x1e), '_' | '7' => Some(0x1f), '?' | '8' => Some(0x7f), '@' | '2' | ' ' => Some(0x00), _ => None,
247 }
248}
249
250fn function_key_sequence(n: u8, modifiers: Modifiers) -> Vec<u8> {
252 let (code, use_tilde) = match n {
255 1 => (b'P', false),
256 2 => (b'Q', false),
257 3 => (b'R', false),
258 4 => (b'S', false),
259 5 => (15, true),
260 6 => (17, true),
261 7 => (18, true),
262 8 => (19, true),
263 9 => (20, true),
264 10 => (21, true),
265 11 => (23, true),
266 12 => (24, true),
267 _ => return Vec::new(),
268 };
269
270 if use_tilde {
271 if modifiers.any() {
272 format!("\x1b[{};{}~", code, modifiers.csi_param()).into_bytes()
274 } else {
275 format!("\x1b[{}~", code).into_bytes()
277 }
278 } else if modifiers.any() {
279 format!("\x1b[1;{}{}", modifiers.csi_param(), code as char).into_bytes()
281 } else {
282 vec![0x1b, b'O', code]
284 }
285}
286
287fn backspace_sequence(modifiers: Modifiers) -> Vec<u8> {
289 if modifiers.ctrl {
290 vec![0x08] } else if modifiers.alt {
292 vec![0x1b, 0x7f] } else {
294 vec![0x7f] }
296}
297
298fn enter_sequence(modifiers: Modifiers) -> Vec<u8> {
300 if modifiers.alt {
301 vec![0x1b, 0x0d] } else {
303 vec![0x0d] }
305}
306
307fn tab_sequence(modifiers: Modifiers) -> Vec<u8> {
309 if modifiers.shift {
310 b"\x1b[Z".to_vec() } else if modifiers.alt {
312 vec![0x1b, 0x09] } else {
314 vec![0x09] }
316}
317
318fn escape_sequence(modifiers: Modifiers) -> Vec<u8> {
320 if modifiers.alt {
321 vec![0x1b, 0x1b] } else {
323 vec![0x1b] }
325}
326
327fn cursor_key_sequence(code: u8, modifiers: Modifiers) -> Vec<u8> {
329 if modifiers.any() {
330 format!("\x1b[1;{}{}", modifiers.csi_param(), code as char).into_bytes()
332 } else {
333 vec![0x1b, b'[', code]
335 }
336}
337
338fn home_end_sequence(code: u8, modifiers: Modifiers) -> Vec<u8> {
340 if modifiers.any() {
341 format!("\x1b[1;{}{}", modifiers.csi_param(), code as char).into_bytes()
343 } else {
344 vec![0x1b, b'[', code]
346 }
347}
348
349fn page_key_sequence(code: u8, modifiers: Modifiers) -> Vec<u8> {
351 if modifiers.any() {
352 format!("\x1b[{};{}~", code, modifiers.csi_param()).into_bytes()
354 } else {
355 format!("\x1b[{}~", code).into_bytes()
357 }
358}
359
360fn insert_delete_sequence(code: u8, modifiers: Modifiers) -> Vec<u8> {
362 if modifiers.any() {
363 format!("\x1b[{};{}~", code, modifiers.csi_param()).into_bytes()
365 } else {
366 format!("\x1b[{}~", code).into_bytes()
368 }
369}
370
371#[derive(Debug, Clone)]
376pub struct BracketedPaste {
377 enabled: bool,
378}
379
380impl Default for BracketedPaste {
381 fn default() -> Self {
382 Self::new()
383 }
384}
385
386impl BracketedPaste {
387 pub const START: &'static [u8] = b"\x1b[200~";
389 pub const END: &'static [u8] = b"\x1b[201~";
391
392 #[must_use]
394 pub const fn new() -> Self {
395 Self { enabled: false }
396 }
397
398 #[must_use]
400 pub const fn is_enabled(&self) -> bool {
401 self.enabled
402 }
403
404 pub fn enable(&mut self) {
406 self.enabled = true;
407 }
408
409 pub fn disable(&mut self) {
411 self.enabled = false;
412 }
413
414 pub fn set_enabled(&mut self, enabled: bool) {
416 self.enabled = enabled;
417 }
418
419 #[must_use]
421 pub fn wrap(&self, text: &[u8]) -> Vec<u8> {
422 if self.enabled {
423 let mut result = Vec::with_capacity(Self::START.len() + text.len() + Self::END.len());
424 result.extend_from_slice(Self::START);
425 result.extend_from_slice(text);
426 result.extend_from_slice(Self::END);
427 result
428 } else {
429 text.to_vec()
430 }
431 }
432}
433
434pub struct InputForwarder<W: Write> {
436 writer: W,
437 bracketed_paste: BracketedPaste,
438}
439
440impl<W: Write> InputForwarder<W> {
441 pub fn new(writer: W) -> Self {
443 Self {
444 writer,
445 bracketed_paste: BracketedPaste::new(),
446 }
447 }
448
449 #[must_use]
451 pub const fn bracketed_paste(&self) -> &BracketedPaste {
452 &self.bracketed_paste
453 }
454
455 pub fn bracketed_paste_mut(&mut self) -> &mut BracketedPaste {
457 &mut self.bracketed_paste
458 }
459
460 pub fn set_bracketed_paste(&mut self, enabled: bool) {
462 self.bracketed_paste.set_enabled(enabled);
463 }
464
465 pub fn forward_key(&mut self, event: KeyEvent) -> io::Result<()> {
467 let seq = key_to_sequence(event);
468 if !seq.is_empty() {
469 self.writer.write_all(&seq)?;
470 self.writer.flush()?;
471 }
472 Ok(())
473 }
474
475 pub fn forward_keys(&mut self, events: &[KeyEvent]) -> io::Result<()> {
477 for event in events {
478 let seq = key_to_sequence(*event);
479 if !seq.is_empty() {
480 self.writer.write_all(&seq)?;
481 }
482 }
483 self.writer.flush()
484 }
485
486 pub fn forward_raw(&mut self, data: &[u8]) -> io::Result<()> {
488 self.writer.write_all(data)?;
489 self.writer.flush()
490 }
491
492 pub fn forward_paste(&mut self, text: &str) -> io::Result<()> {
494 let data = self.bracketed_paste.wrap(text.as_bytes());
495 self.writer.write_all(&data)?;
496 self.writer.flush()
497 }
498
499 pub fn writer_mut(&mut self) -> &mut W {
501 &mut self.writer
502 }
503
504 pub fn into_writer(self) -> W {
506 self.writer
507 }
508}
509
510#[cfg(test)]
511mod tests {
512 use super::*;
513
514 #[test]
515 fn test_plain_char() {
516 let event = KeyEvent::plain(Key::Char('a'));
517 assert_eq!(key_to_sequence(event), b"a");
518 }
519
520 #[test]
521 fn test_shift_char() {
522 let event = KeyEvent::new(Key::Char('a'), Modifiers::SHIFT);
523 assert_eq!(key_to_sequence(event), b"A");
524 }
525
526 #[test]
527 fn test_ctrl_char() {
528 let event = KeyEvent::new(Key::Char('c'), Modifiers::CTRL);
529 assert_eq!(key_to_sequence(event), vec![0x03]); }
531
532 #[test]
533 fn test_ctrl_a() {
534 let event = KeyEvent::new(Key::Char('a'), Modifiers::CTRL);
535 assert_eq!(key_to_sequence(event), vec![0x01]); }
537
538 #[test]
539 fn test_ctrl_z() {
540 let event = KeyEvent::new(Key::Char('z'), Modifiers::CTRL);
541 assert_eq!(key_to_sequence(event), vec![0x1a]); }
543
544 #[test]
545 fn test_alt_char() {
546 let event = KeyEvent::new(Key::Char('x'), Modifiers::ALT);
547 assert_eq!(key_to_sequence(event), vec![0x1b, b'x']);
548 }
549
550 #[test]
551 fn test_ctrl_alt_char() {
552 let event = KeyEvent::new(
553 Key::Char('c'),
554 Modifiers {
555 ctrl: true,
556 alt: true,
557 shift: false,
558 },
559 );
560 assert_eq!(key_to_sequence(event), vec![0x1b, 0x03]);
561 }
562
563 #[test]
564 fn test_arrow_keys() {
565 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Up)), b"\x1b[A");
566 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Down)), b"\x1b[B");
567 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Right)), b"\x1b[C");
568 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Left)), b"\x1b[D");
569 }
570
571 #[test]
572 fn test_arrow_with_modifiers() {
573 let event = KeyEvent::new(Key::Up, Modifiers::CTRL);
574 assert_eq!(key_to_sequence(event), b"\x1b[1;5A");
575
576 let event = KeyEvent::new(Key::Down, Modifiers::SHIFT);
577 assert_eq!(key_to_sequence(event), b"\x1b[1;2B");
578
579 let event = KeyEvent::new(Key::Left, Modifiers::ALT);
580 assert_eq!(key_to_sequence(event), b"\x1b[1;3D");
581 }
582
583 #[test]
584 fn test_function_keys_f1_f4() {
585 assert_eq!(key_to_sequence(KeyEvent::plain(Key::F(1))), b"\x1bOP");
586 assert_eq!(key_to_sequence(KeyEvent::plain(Key::F(2))), b"\x1bOQ");
587 assert_eq!(key_to_sequence(KeyEvent::plain(Key::F(3))), b"\x1bOR");
588 assert_eq!(key_to_sequence(KeyEvent::plain(Key::F(4))), b"\x1bOS");
589 }
590
591 #[test]
592 fn test_function_keys_f5_f12() {
593 assert_eq!(key_to_sequence(KeyEvent::plain(Key::F(5))), b"\x1b[15~");
594 assert_eq!(key_to_sequence(KeyEvent::plain(Key::F(6))), b"\x1b[17~");
595 assert_eq!(key_to_sequence(KeyEvent::plain(Key::F(10))), b"\x1b[21~");
596 assert_eq!(key_to_sequence(KeyEvent::plain(Key::F(12))), b"\x1b[24~");
597 }
598
599 #[test]
600 fn test_function_keys_with_modifiers() {
601 let event = KeyEvent::new(Key::F(1), Modifiers::SHIFT);
602 assert_eq!(key_to_sequence(event), b"\x1b[1;2P");
603
604 let event = KeyEvent::new(Key::F(5), Modifiers::CTRL);
605 assert_eq!(key_to_sequence(event), b"\x1b[15;5~");
606 }
607
608 #[test]
609 fn test_backspace() {
610 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Backspace)), vec![0x7f]);
611 }
612
613 #[test]
614 fn test_enter() {
615 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Enter)), vec![0x0d]);
616 }
617
618 #[test]
619 fn test_tab() {
620 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Tab)), vec![0x09]);
621 }
622
623 #[test]
624 fn test_shift_tab() {
625 let event = KeyEvent::new(Key::Tab, Modifiers::SHIFT);
626 assert_eq!(key_to_sequence(event), b"\x1b[Z");
627 }
628
629 #[test]
630 fn test_escape() {
631 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Escape)), vec![0x1b]);
632 }
633
634 #[test]
635 fn test_home_end() {
636 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Home)), b"\x1b[H");
637 assert_eq!(key_to_sequence(KeyEvent::plain(Key::End)), b"\x1b[F");
638 }
639
640 #[test]
641 fn test_page_keys() {
642 assert_eq!(key_to_sequence(KeyEvent::plain(Key::PageUp)), b"\x1b[5~");
643 assert_eq!(key_to_sequence(KeyEvent::plain(Key::PageDown)), b"\x1b[6~");
644 }
645
646 #[test]
647 fn test_insert_delete() {
648 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Insert)), b"\x1b[2~");
649 assert_eq!(key_to_sequence(KeyEvent::plain(Key::Delete)), b"\x1b[3~");
650 }
651
652 #[test]
653 fn test_modifiers_csi_param() {
654 assert_eq!(Modifiers::NONE.csi_param(), 1);
655 assert_eq!(Modifiers::SHIFT.csi_param(), 2);
656 assert_eq!(Modifiers::ALT.csi_param(), 3);
657 assert_eq!(Modifiers::CTRL.csi_param(), 5);
658
659 let ctrl_shift = Modifiers {
660 ctrl: true,
661 alt: false,
662 shift: true,
663 };
664 assert_eq!(ctrl_shift.csi_param(), 6);
665
666 let all = Modifiers {
667 ctrl: true,
668 alt: true,
669 shift: true,
670 };
671 assert_eq!(all.csi_param(), 8);
672 }
673
674 #[test]
675 fn test_bracketed_paste_disabled() {
676 let bp = BracketedPaste::new();
677 assert!(!bp.is_enabled());
678 assert_eq!(bp.wrap(b"hello"), b"hello");
679 }
680
681 #[test]
682 fn test_bracketed_paste_enabled() {
683 let mut bp = BracketedPaste::new();
684 bp.enable();
685 assert!(bp.is_enabled());
686
687 let wrapped = bp.wrap(b"hello");
688 assert!(wrapped.starts_with(BracketedPaste::START));
689 assert!(wrapped.ends_with(BracketedPaste::END));
690 assert!(wrapped[BracketedPaste::START.len()..].starts_with(b"hello"));
691 }
692
693 #[test]
694 fn test_input_forwarder() {
695 let mut buffer = Vec::new();
696
697 {
698 let mut forwarder = InputForwarder::new(&mut buffer);
699 forwarder
700 .forward_key(KeyEvent::plain(Key::Char('a')))
701 .unwrap();
702 forwarder.forward_key(KeyEvent::plain(Key::Enter)).unwrap();
703 }
704
705 assert_eq!(buffer, vec![b'a', 0x0d]);
706 }
707
708 #[test]
709 fn test_input_forwarder_paste() {
710 let mut buffer = Vec::new();
711
712 {
713 let mut forwarder = InputForwarder::new(&mut buffer);
714 forwarder.forward_paste("text").unwrap();
715 }
716
717 assert_eq!(buffer, b"text");
718 }
719
720 #[test]
721 fn test_input_forwarder_bracketed_paste() {
722 let mut buffer = Vec::new();
723
724 {
725 let mut forwarder = InputForwarder::new(&mut buffer);
726 forwarder.set_bracketed_paste(true);
727 forwarder.forward_paste("text").unwrap();
728 }
729
730 let expected = [BracketedPaste::START, b"text", BracketedPaste::END].concat();
731 assert_eq!(buffer, expected);
732 }
733
734 #[test]
735 fn test_utf8_char() {
736 let event = KeyEvent::plain(Key::Char('日'));
737 let seq = key_to_sequence(event);
738 assert_eq!(std::str::from_utf8(&seq).unwrap(), "日");
739 }
740
741 #[test]
742 fn test_emoji_char() {
743 let event = KeyEvent::plain(Key::Char('🎉'));
744 let seq = key_to_sequence(event);
745 assert_eq!(std::str::from_utf8(&seq).unwrap(), "🎉");
746 }
747
748 #[test]
749 fn test_ctrl_special_chars() {
750 let event = KeyEvent::new(Key::Char('['), Modifiers::CTRL);
752 assert_eq!(key_to_sequence(event), vec![0x1b]);
753
754 let event = KeyEvent::new(Key::Char('@'), Modifiers::CTRL);
756 assert_eq!(key_to_sequence(event), vec![0x00]);
757
758 let event = KeyEvent::new(Key::Char('?'), Modifiers::CTRL);
760 assert_eq!(key_to_sequence(event), vec![0x7f]);
761 }
762}