1use std::io;
2
3use crate::event::{
4 Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers, KeyboardEnhancementFlags,
5 MediaKeyCode, ModifierKeyCode, MouseButton, MouseEvent, MouseEventKind,
6};
7
8use super::super::super::InternalEvent;
9
10// Event parsing
11//
12// This code (& previous one) are kind of ugly. We have to think about this,
13// because it's really not maintainable, no tests, etc.
14//
15// Every fn returns Result<Option<InputEvent>>
16//
17// Ok(None) -> wait for more bytes
18// Err(_) -> failed to parse event, clear the buffer
19// Ok(Some(event)) -> we have event, clear the buffer
20//
21
22fn could_not_parse_event_error() -> io::Error {
23 io::Error::new(kind:io::ErrorKind::Other, error:"Could not parse an event.")
24}
25
26pub(crate) fn parse_event(
27 buffer: &[u8],
28 input_available: bool,
29) -> io::Result<Option<InternalEvent>> {
30 if buffer.is_empty() {
31 return Ok(None);
32 }
33
34 match buffer[0] {
35 b'\x1B' => {
36 if buffer.len() == 1 {
37 if input_available {
38 // Possible Esc sequence
39 Ok(None)
40 } else {
41 Ok(Some(InternalEvent::Event(Event::Key(KeyCode::Esc.into()))))
42 }
43 } else {
44 match buffer[1] {
45 b'O' => {
46 if buffer.len() == 2 {
47 Ok(None)
48 } else {
49 match buffer[2] {
50 b'D' => {
51 Ok(Some(InternalEvent::Event(Event::Key(KeyCode::Left.into()))))
52 }
53 b'C' => Ok(Some(InternalEvent::Event(Event::Key(
54 KeyCode::Right.into(),
55 )))),
56 b'A' => {
57 Ok(Some(InternalEvent::Event(Event::Key(KeyCode::Up.into()))))
58 }
59 b'B' => {
60 Ok(Some(InternalEvent::Event(Event::Key(KeyCode::Down.into()))))
61 }
62 b'H' => {
63 Ok(Some(InternalEvent::Event(Event::Key(KeyCode::Home.into()))))
64 }
65 b'F' => {
66 Ok(Some(InternalEvent::Event(Event::Key(KeyCode::End.into()))))
67 }
68 // F1-F4
69 val @ b'P'..=b'S' => Ok(Some(InternalEvent::Event(Event::Key(
70 KeyCode::F(1 + val - b'P').into(),
71 )))),
72 _ => Err(could_not_parse_event_error()),
73 }
74 }
75 }
76 b'[' => parse_csi(buffer),
77 b'\x1B' => Ok(Some(InternalEvent::Event(Event::Key(KeyCode::Esc.into())))),
78 _ => parse_event(&buffer[1..], input_available).map(|event_option| {
79 event_option.map(|event| {
80 if let InternalEvent::Event(Event::Key(key_event)) = event {
81 let mut alt_key_event = key_event;
82 alt_key_event.modifiers |= KeyModifiers::ALT;
83 InternalEvent::Event(Event::Key(alt_key_event))
84 } else {
85 event
86 }
87 })
88 }),
89 }
90 }
91 }
92 b'\r' => Ok(Some(InternalEvent::Event(Event::Key(
93 KeyCode::Enter.into(),
94 )))),
95 // Issue #371: \n = 0xA, which is also the keycode for Ctrl+J. The only reason we get
96 // newlines as input is because the terminal converts \r into \n for us. When we
97 // enter raw mode, we disable that, so \n no longer has any meaning - it's better to
98 // use Ctrl+J. Waiting to handle it here means it gets picked up later
99 b'\n' if !crate::terminal::sys::is_raw_mode_enabled() => Ok(Some(InternalEvent::Event(
100 Event::Key(KeyCode::Enter.into()),
101 ))),
102 b'\t' => Ok(Some(InternalEvent::Event(Event::Key(KeyCode::Tab.into())))),
103 b'\x7F' => Ok(Some(InternalEvent::Event(Event::Key(
104 KeyCode::Backspace.into(),
105 )))),
106 c @ b'\x01'..=b'\x1A' => Ok(Some(InternalEvent::Event(Event::Key(KeyEvent::new(
107 KeyCode::Char((c - 0x1 + b'a') as char),
108 KeyModifiers::CONTROL,
109 ))))),
110 c @ b'\x1C'..=b'\x1F' => Ok(Some(InternalEvent::Event(Event::Key(KeyEvent::new(
111 KeyCode::Char((c - 0x1C + b'4') as char),
112 KeyModifiers::CONTROL,
113 ))))),
114 b'\0' => Ok(Some(InternalEvent::Event(Event::Key(KeyEvent::new(
115 KeyCode::Char(' '),
116 KeyModifiers::CONTROL,
117 ))))),
118 _ => parse_utf8_char(buffer).map(|maybe_char| {
119 maybe_char
120 .map(KeyCode::Char)
121 .map(char_code_to_event)
122 .map(Event::Key)
123 .map(InternalEvent::Event)
124 }),
125 }
126}
127
128// converts KeyCode to KeyEvent (adds shift modifier in case of uppercase characters)
129fn char_code_to_event(code: KeyCode) -> KeyEvent {
130 let modifiers: KeyModifiers = match code {
131 KeyCode::Char(c: char) if c.is_uppercase() => KeyModifiers::SHIFT,
132 _ => KeyModifiers::empty(),
133 };
134 KeyEvent::new(code, modifiers)
135}
136
137pub(crate) fn parse_csi(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
138 assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
139
140 if buffer.len() == 2 {
141 return Ok(None);
142 }
143
144 let input_event = match buffer[2] {
145 b'[' => {
146 if buffer.len() == 3 {
147 None
148 } else {
149 match buffer[3] {
150 // NOTE (@imdaveho): cannot find when this occurs;
151 // having another '[' after ESC[ not a likely scenario
152 val @ b'A'..=b'E' => Some(Event::Key(KeyCode::F(1 + val - b'A').into())),
153 _ => return Err(could_not_parse_event_error()),
154 }
155 }
156 }
157 b'D' => Some(Event::Key(KeyCode::Left.into())),
158 b'C' => Some(Event::Key(KeyCode::Right.into())),
159 b'A' => Some(Event::Key(KeyCode::Up.into())),
160 b'B' => Some(Event::Key(KeyCode::Down.into())),
161 b'H' => Some(Event::Key(KeyCode::Home.into())),
162 b'F' => Some(Event::Key(KeyCode::End.into())),
163 b'Z' => Some(Event::Key(KeyEvent::new_with_kind(
164 KeyCode::BackTab,
165 KeyModifiers::SHIFT,
166 KeyEventKind::Press,
167 ))),
168 b'M' => return parse_csi_normal_mouse(buffer),
169 b'<' => return parse_csi_sgr_mouse(buffer),
170 b'I' => Some(Event::FocusGained),
171 b'O' => Some(Event::FocusLost),
172 b';' => return parse_csi_modifier_key_code(buffer),
173 // P, Q, and S for compatibility with Kitty keyboard protocol,
174 // as the 1 in 'CSI 1 P' etc. must be omitted if there are no
175 // modifiers pressed:
176 // https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-functional-keys
177 b'P' => Some(Event::Key(KeyCode::F(1).into())),
178 b'Q' => Some(Event::Key(KeyCode::F(2).into())),
179 b'S' => Some(Event::Key(KeyCode::F(4).into())),
180 b'?' => match buffer[buffer.len() - 1] {
181 b'u' => return parse_csi_keyboard_enhancement_flags(buffer),
182 b'c' => return parse_csi_primary_device_attributes(buffer),
183 _ => None,
184 },
185 b'0'..=b'9' => {
186 // Numbered escape code.
187 if buffer.len() == 3 {
188 None
189 } else {
190 // The final byte of a CSI sequence can be in the range 64-126, so
191 // let's keep reading anything else.
192 let last_byte = buffer[buffer.len() - 1];
193 if !(64..=126).contains(&last_byte) {
194 None
195 } else {
196 #[cfg(feature = "bracketed-paste")]
197 if buffer.starts_with(b"\x1B[200~") {
198 return parse_csi_bracketed_paste(buffer);
199 }
200 match last_byte {
201 b'M' => return parse_csi_rxvt_mouse(buffer),
202 b'~' => return parse_csi_special_key_code(buffer),
203 b'u' => return parse_csi_u_encoded_key_code(buffer),
204 b'R' => return parse_csi_cursor_position(buffer),
205 _ => return parse_csi_modifier_key_code(buffer),
206 }
207 }
208 }
209 }
210 _ => return Err(could_not_parse_event_error()),
211 };
212
213 Ok(input_event.map(InternalEvent::Event))
214}
215
216pub(crate) fn next_parsed<T>(iter: &mut dyn Iterator<Item = &str>) -> io::Result<T>
217where
218 T: std::str::FromStr,
219{
220 iter.next()
221 .ok_or_else(could_not_parse_event_error)?
222 .parse::<T>()
223 .map_err(|_| could_not_parse_event_error())
224}
225
226fn modifier_and_kind_parsed(iter: &mut dyn Iterator<Item = &str>) -> io::Result<(u8, u8)> {
227 let mut sub_split: Split<'_, char> = iter&str
228 .next()
229 .ok_or_else(err:could_not_parse_event_error)?
230 .split(':');
231
232 let modifier_mask: u8 = next_parsed::<u8>(&mut sub_split)?;
233
234 if let Ok(kind_code: u8) = next_parsed::<u8>(&mut sub_split) {
235 Ok((modifier_mask, kind_code))
236 } else {
237 Ok((modifier_mask, 1))
238 }
239}
240
241pub(crate) fn parse_csi_cursor_position(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
242 // ESC [ Cy ; Cx R
243 // Cy - cursor row number (starting from 1)
244 // Cx - cursor column number (starting from 1)
245 assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
246 assert!(buffer.ends_with(&[b'R']));
247
248 let s: &str = std::str::from_utf8(&buffer[2..buffer.len() - 1])
249 .map_err(|_| could_not_parse_event_error())?;
250
251 let mut split: Split<'_, char> = s.split(';');
252
253 let y: u16 = next_parsed::<u16>(&mut split)? - 1;
254 let x: u16 = next_parsed::<u16>(&mut split)? - 1;
255
256 Ok(Some(InternalEvent::CursorPosition(x, y)))
257}
258
259fn parse_csi_keyboard_enhancement_flags(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
260 // ESC [ ? flags u
261 assert!(buffer.starts_with(&[b'\x1B', b'[', b'?'])); // ESC [ ?
262 assert!(buffer.ends_with(&[b'u']));
263
264 if buffer.len() < 5 {
265 return Ok(None);
266 }
267
268 let bits = buffer[3];
269 let mut flags = KeyboardEnhancementFlags::empty();
270
271 if bits & 1 != 0 {
272 flags |= KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES;
273 }
274 if bits & 2 != 0 {
275 flags |= KeyboardEnhancementFlags::REPORT_EVENT_TYPES;
276 }
277 if bits & 4 != 0 {
278 flags |= KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS;
279 }
280 if bits & 8 != 0 {
281 flags |= KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES;
282 }
283 // *Note*: this is not yet supported by crossterm.
284 // if bits & 16 != 0 {
285 // flags |= KeyboardEnhancementFlags::REPORT_ASSOCIATED_TEXT;
286 // }
287
288 Ok(Some(InternalEvent::KeyboardEnhancementFlags(flags)))
289}
290
291fn parse_csi_primary_device_attributes(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
292 // ESC [ 64 ; attr1 ; attr2 ; ... ; attrn ; c
293 assert!(buffer.starts_with(&[b'\x1B', b'[', b'?']));
294 assert!(buffer.ends_with(&[b'c']));
295
296 // This is a stub for parsing the primary device attributes. This response is not
297 // exposed in the crossterm API so we don't need to parse the individual attributes yet.
298 // See <https://vt100.net/docs/vt510-rm/DA1.html>
299
300 Ok(Some(InternalEvent::PrimaryDeviceAttributes))
301}
302
303fn parse_modifiers(mask: u8) -> KeyModifiers {
304 let modifier_mask: u8 = mask.saturating_sub(1);
305 let mut modifiers: KeyModifiers = KeyModifiers::empty();
306 if modifier_mask & 1 != 0 {
307 modifiers |= KeyModifiers::SHIFT;
308 }
309 if modifier_mask & 2 != 0 {
310 modifiers |= KeyModifiers::ALT;
311 }
312 if modifier_mask & 4 != 0 {
313 modifiers |= KeyModifiers::CONTROL;
314 }
315 if modifier_mask & 8 != 0 {
316 modifiers |= KeyModifiers::SUPER;
317 }
318 if modifier_mask & 16 != 0 {
319 modifiers |= KeyModifiers::HYPER;
320 }
321 if modifier_mask & 32 != 0 {
322 modifiers |= KeyModifiers::META;
323 }
324 modifiers
325}
326
327fn parse_modifiers_to_state(mask: u8) -> KeyEventState {
328 let modifier_mask: u8 = mask.saturating_sub(1);
329 let mut state: KeyEventState = KeyEventState::empty();
330 if modifier_mask & 64 != 0 {
331 state |= KeyEventState::CAPS_LOCK;
332 }
333 if modifier_mask & 128 != 0 {
334 state |= KeyEventState::NUM_LOCK;
335 }
336 state
337}
338
339fn parse_key_event_kind(kind: u8) -> KeyEventKind {
340 match kind {
341 1 => KeyEventKind::Press,
342 2 => KeyEventKind::Repeat,
343 3 => KeyEventKind::Release,
344 _ => KeyEventKind::Press,
345 }
346}
347
348pub(crate) fn parse_csi_modifier_key_code(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
349 assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
350 //
351 let s = std::str::from_utf8(&buffer[2..buffer.len() - 1])
352 .map_err(|_| could_not_parse_event_error())?;
353 let mut split = s.split(';');
354
355 split.next();
356
357 let (modifiers, kind) =
358 if let Ok((modifier_mask, kind_code)) = modifier_and_kind_parsed(&mut split) {
359 (
360 parse_modifiers(modifier_mask),
361 parse_key_event_kind(kind_code),
362 )
363 } else if buffer.len() > 3 {
364 (
365 parse_modifiers(
366 (buffer[buffer.len() - 2] as char)
367 .to_digit(10)
368 .ok_or_else(could_not_parse_event_error)? as u8,
369 ),
370 KeyEventKind::Press,
371 )
372 } else {
373 (KeyModifiers::NONE, KeyEventKind::Press)
374 };
375 let key = buffer[buffer.len() - 1];
376
377 let keycode = match key {
378 b'A' => KeyCode::Up,
379 b'B' => KeyCode::Down,
380 b'C' => KeyCode::Right,
381 b'D' => KeyCode::Left,
382 b'F' => KeyCode::End,
383 b'H' => KeyCode::Home,
384 b'P' => KeyCode::F(1),
385 b'Q' => KeyCode::F(2),
386 b'R' => KeyCode::F(3),
387 b'S' => KeyCode::F(4),
388 _ => return Err(could_not_parse_event_error()),
389 };
390
391 let input_event = Event::Key(KeyEvent::new_with_kind(keycode, modifiers, kind));
392
393 Ok(Some(InternalEvent::Event(input_event)))
394}
395
396fn translate_functional_key_code(codepoint: u32) -> Option<(KeyCode, KeyEventState)> {
397 if let Some(keycode) = match codepoint {
398 57399 => Some(KeyCode::Char('0')),
399 57400 => Some(KeyCode::Char('1')),
400 57401 => Some(KeyCode::Char('2')),
401 57402 => Some(KeyCode::Char('3')),
402 57403 => Some(KeyCode::Char('4')),
403 57404 => Some(KeyCode::Char('5')),
404 57405 => Some(KeyCode::Char('6')),
405 57406 => Some(KeyCode::Char('7')),
406 57407 => Some(KeyCode::Char('8')),
407 57408 => Some(KeyCode::Char('9')),
408 57409 => Some(KeyCode::Char('.')),
409 57410 => Some(KeyCode::Char('/')),
410 57411 => Some(KeyCode::Char('*')),
411 57412 => Some(KeyCode::Char('-')),
412 57413 => Some(KeyCode::Char('+')),
413 57414 => Some(KeyCode::Enter),
414 57415 => Some(KeyCode::Char('=')),
415 57416 => Some(KeyCode::Char(',')),
416 57417 => Some(KeyCode::Left),
417 57418 => Some(KeyCode::Right),
418 57419 => Some(KeyCode::Up),
419 57420 => Some(KeyCode::Down),
420 57421 => Some(KeyCode::PageUp),
421 57422 => Some(KeyCode::PageDown),
422 57423 => Some(KeyCode::Home),
423 57424 => Some(KeyCode::End),
424 57425 => Some(KeyCode::Insert),
425 57426 => Some(KeyCode::Delete),
426 57427 => Some(KeyCode::KeypadBegin),
427 _ => None,
428 } {
429 return Some((keycode, KeyEventState::KEYPAD));
430 }
431
432 if let Some(keycode) = match codepoint {
433 57358 => Some(KeyCode::CapsLock),
434 57359 => Some(KeyCode::ScrollLock),
435 57360 => Some(KeyCode::NumLock),
436 57361 => Some(KeyCode::PrintScreen),
437 57362 => Some(KeyCode::Pause),
438 57363 => Some(KeyCode::Menu),
439 57376 => Some(KeyCode::F(13)),
440 57377 => Some(KeyCode::F(14)),
441 57378 => Some(KeyCode::F(15)),
442 57379 => Some(KeyCode::F(16)),
443 57380 => Some(KeyCode::F(17)),
444 57381 => Some(KeyCode::F(18)),
445 57382 => Some(KeyCode::F(19)),
446 57383 => Some(KeyCode::F(20)),
447 57384 => Some(KeyCode::F(21)),
448 57385 => Some(KeyCode::F(22)),
449 57386 => Some(KeyCode::F(23)),
450 57387 => Some(KeyCode::F(24)),
451 57388 => Some(KeyCode::F(25)),
452 57389 => Some(KeyCode::F(26)),
453 57390 => Some(KeyCode::F(27)),
454 57391 => Some(KeyCode::F(28)),
455 57392 => Some(KeyCode::F(29)),
456 57393 => Some(KeyCode::F(30)),
457 57394 => Some(KeyCode::F(31)),
458 57395 => Some(KeyCode::F(32)),
459 57396 => Some(KeyCode::F(33)),
460 57397 => Some(KeyCode::F(34)),
461 57398 => Some(KeyCode::F(35)),
462 57428 => Some(KeyCode::Media(MediaKeyCode::Play)),
463 57429 => Some(KeyCode::Media(MediaKeyCode::Pause)),
464 57430 => Some(KeyCode::Media(MediaKeyCode::PlayPause)),
465 57431 => Some(KeyCode::Media(MediaKeyCode::Reverse)),
466 57432 => Some(KeyCode::Media(MediaKeyCode::Stop)),
467 57433 => Some(KeyCode::Media(MediaKeyCode::FastForward)),
468 57434 => Some(KeyCode::Media(MediaKeyCode::Rewind)),
469 57435 => Some(KeyCode::Media(MediaKeyCode::TrackNext)),
470 57436 => Some(KeyCode::Media(MediaKeyCode::TrackPrevious)),
471 57437 => Some(KeyCode::Media(MediaKeyCode::Record)),
472 57438 => Some(KeyCode::Media(MediaKeyCode::LowerVolume)),
473 57439 => Some(KeyCode::Media(MediaKeyCode::RaiseVolume)),
474 57440 => Some(KeyCode::Media(MediaKeyCode::MuteVolume)),
475 57441 => Some(KeyCode::Modifier(ModifierKeyCode::LeftShift)),
476 57442 => Some(KeyCode::Modifier(ModifierKeyCode::LeftControl)),
477 57443 => Some(KeyCode::Modifier(ModifierKeyCode::LeftAlt)),
478 57444 => Some(KeyCode::Modifier(ModifierKeyCode::LeftSuper)),
479 57445 => Some(KeyCode::Modifier(ModifierKeyCode::LeftHyper)),
480 57446 => Some(KeyCode::Modifier(ModifierKeyCode::LeftMeta)),
481 57447 => Some(KeyCode::Modifier(ModifierKeyCode::RightShift)),
482 57448 => Some(KeyCode::Modifier(ModifierKeyCode::RightControl)),
483 57449 => Some(KeyCode::Modifier(ModifierKeyCode::RightAlt)),
484 57450 => Some(KeyCode::Modifier(ModifierKeyCode::RightSuper)),
485 57451 => Some(KeyCode::Modifier(ModifierKeyCode::RightHyper)),
486 57452 => Some(KeyCode::Modifier(ModifierKeyCode::RightMeta)),
487 57453 => Some(KeyCode::Modifier(ModifierKeyCode::IsoLevel3Shift)),
488 57454 => Some(KeyCode::Modifier(ModifierKeyCode::IsoLevel5Shift)),
489 _ => None,
490 } {
491 return Some((keycode, KeyEventState::empty()));
492 }
493
494 None
495}
496
497pub(crate) fn parse_csi_u_encoded_key_code(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
498 assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
499 assert!(buffer.ends_with(&[b'u']));
500
501 // This function parses `CSI … u` sequences. These are sequences defined in either
502 // the `CSI u` (a.k.a. "Fix Keyboard Input on Terminals - Please", https://www.leonerd.org.uk/hacks/fixterms/)
503 // or Kitty Keyboard Protocol (https://sw.kovidgoyal.net/kitty/keyboard-protocol/) specifications.
504 // This CSI sequence is a tuple of semicolon-separated numbers.
505 let s = std::str::from_utf8(&buffer[2..buffer.len() - 1])
506 .map_err(|_| could_not_parse_event_error())?;
507 let mut split = s.split(';');
508
509 // In `CSI u`, this is parsed as:
510 //
511 // CSI codepoint ; modifiers u
512 // codepoint: ASCII Dec value
513 //
514 // The Kitty Keyboard Protocol extends this with optional components that can be
515 // enabled progressively. The full sequence is parsed as:
516 //
517 // CSI unicode-key-code:alternate-key-codes ; modifiers:event-type ; text-as-codepoints u
518 let mut codepoints = split
519 .next()
520 .ok_or_else(could_not_parse_event_error)?
521 .split(':');
522
523 let codepoint = codepoints
524 .next()
525 .ok_or_else(could_not_parse_event_error)?
526 .parse::<u32>()
527 .map_err(|_| could_not_parse_event_error())?;
528
529 let (mut modifiers, kind, state_from_modifiers) =
530 if let Ok((modifier_mask, kind_code)) = modifier_and_kind_parsed(&mut split) {
531 (
532 parse_modifiers(modifier_mask),
533 parse_key_event_kind(kind_code),
534 parse_modifiers_to_state(modifier_mask),
535 )
536 } else {
537 (KeyModifiers::NONE, KeyEventKind::Press, KeyEventState::NONE)
538 };
539
540 let (mut keycode, state_from_keycode) = {
541 if let Some((special_key_code, state)) = translate_functional_key_code(codepoint) {
542 (special_key_code, state)
543 } else if let Some(c) = char::from_u32(codepoint) {
544 (
545 match c {
546 '\x1B' => KeyCode::Esc,
547 '\r' => KeyCode::Enter,
548 // Issue #371: \n = 0xA, which is also the keycode for Ctrl+J. The only reason we get
549 // newlines as input is because the terminal converts \r into \n for us. When we
550 // enter raw mode, we disable that, so \n no longer has any meaning - it's better to
551 // use Ctrl+J. Waiting to handle it here means it gets picked up later
552 '\n' if !crate::terminal::sys::is_raw_mode_enabled() => KeyCode::Enter,
553 '\t' => {
554 if modifiers.contains(KeyModifiers::SHIFT) {
555 KeyCode::BackTab
556 } else {
557 KeyCode::Tab
558 }
559 }
560 '\x7F' => KeyCode::Backspace,
561 _ => KeyCode::Char(c),
562 },
563 KeyEventState::empty(),
564 )
565 } else {
566 return Err(could_not_parse_event_error());
567 }
568 };
569
570 if let KeyCode::Modifier(modifier_keycode) = keycode {
571 match modifier_keycode {
572 ModifierKeyCode::LeftAlt | ModifierKeyCode::RightAlt => {
573 modifiers.set(KeyModifiers::ALT, true)
574 }
575 ModifierKeyCode::LeftControl | ModifierKeyCode::RightControl => {
576 modifiers.set(KeyModifiers::CONTROL, true)
577 }
578 ModifierKeyCode::LeftShift | ModifierKeyCode::RightShift => {
579 modifiers.set(KeyModifiers::SHIFT, true)
580 }
581 ModifierKeyCode::LeftSuper | ModifierKeyCode::RightSuper => {
582 modifiers.set(KeyModifiers::SUPER, true)
583 }
584 ModifierKeyCode::LeftHyper | ModifierKeyCode::RightHyper => {
585 modifiers.set(KeyModifiers::HYPER, true)
586 }
587 ModifierKeyCode::LeftMeta | ModifierKeyCode::RightMeta => {
588 modifiers.set(KeyModifiers::META, true)
589 }
590 _ => {}
591 }
592 }
593
594 // When the "report alternate keys" flag is enabled in the Kitty Keyboard Protocol
595 // and the terminal sends a keyboard event containing shift, the sequence will
596 // contain an additional codepoint separated by a ':' character which contains
597 // the shifted character according to the keyboard layout.
598 if modifiers.contains(KeyModifiers::SHIFT) {
599 if let Some(shifted_c) = codepoints
600 .next()
601 .and_then(|codepoint| codepoint.parse::<u32>().ok())
602 .and_then(char::from_u32)
603 {
604 keycode = KeyCode::Char(shifted_c);
605 modifiers.set(KeyModifiers::SHIFT, false);
606 }
607 }
608
609 let input_event = Event::Key(KeyEvent::new_with_kind_and_state(
610 keycode,
611 modifiers,
612 kind,
613 state_from_keycode | state_from_modifiers,
614 ));
615
616 Ok(Some(InternalEvent::Event(input_event)))
617}
618
619pub(crate) fn parse_csi_special_key_code(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
620 assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
621 assert!(buffer.ends_with(&[b'~']));
622
623 let s = std::str::from_utf8(&buffer[2..buffer.len() - 1])
624 .map_err(|_| could_not_parse_event_error())?;
625 let mut split = s.split(';');
626
627 // This CSI sequence can be a list of semicolon-separated numbers.
628 let first = next_parsed::<u8>(&mut split)?;
629
630 let (modifiers, kind, state) =
631 if let Ok((modifier_mask, kind_code)) = modifier_and_kind_parsed(&mut split) {
632 (
633 parse_modifiers(modifier_mask),
634 parse_key_event_kind(kind_code),
635 parse_modifiers_to_state(modifier_mask),
636 )
637 } else {
638 (KeyModifiers::NONE, KeyEventKind::Press, KeyEventState::NONE)
639 };
640
641 let keycode = match first {
642 1 | 7 => KeyCode::Home,
643 2 => KeyCode::Insert,
644 3 => KeyCode::Delete,
645 4 | 8 => KeyCode::End,
646 5 => KeyCode::PageUp,
647 6 => KeyCode::PageDown,
648 v @ 11..=15 => KeyCode::F(v - 10),
649 v @ 17..=21 => KeyCode::F(v - 11),
650 v @ 23..=26 => KeyCode::F(v - 12),
651 v @ 28..=29 => KeyCode::F(v - 15),
652 v @ 31..=34 => KeyCode::F(v - 17),
653 _ => return Err(could_not_parse_event_error()),
654 };
655
656 let input_event = Event::Key(KeyEvent::new_with_kind_and_state(
657 keycode, modifiers, kind, state,
658 ));
659
660 Ok(Some(InternalEvent::Event(input_event)))
661}
662
663pub(crate) fn parse_csi_rxvt_mouse(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
664 // rxvt mouse encoding:
665 // ESC [ Cb ; Cx ; Cy ; M
666
667 assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
668 assert!(buffer.ends_with(&[b'M']));
669
670 let s = std::str::from_utf8(&buffer[2..buffer.len() - 1])
671 .map_err(|_| could_not_parse_event_error())?;
672 let mut split = s.split(';');
673
674 let cb = next_parsed::<u8>(&mut split)?
675 .checked_sub(32)
676 .ok_or_else(could_not_parse_event_error)?;
677 let (kind, modifiers) = parse_cb(cb)?;
678
679 let cx = next_parsed::<u16>(&mut split)? - 1;
680 let cy = next_parsed::<u16>(&mut split)? - 1;
681
682 Ok(Some(InternalEvent::Event(Event::Mouse(MouseEvent {
683 kind,
684 column: cx,
685 row: cy,
686 modifiers,
687 }))))
688}
689
690pub(crate) fn parse_csi_normal_mouse(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
691 // Normal mouse encoding: ESC [ M CB Cx Cy (6 characters only).
692
693 assert!(buffer.starts_with(&[b'\x1B', b'[', b'M'])); // ESC [ M
694
695 if buffer.len() < 6 {
696 return Ok(None);
697 }
698
699 let cb = buffer[3]
700 .checked_sub(32)
701 .ok_or_else(could_not_parse_event_error)?;
702 let (kind, modifiers) = parse_cb(cb)?;
703
704 // See http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking
705 // The upper left character position on the terminal is denoted as 1,1.
706 // Subtract 1 to keep it synced with cursor
707 let cx = u16::from(buffer[4].saturating_sub(32)) - 1;
708 let cy = u16::from(buffer[5].saturating_sub(32)) - 1;
709
710 Ok(Some(InternalEvent::Event(Event::Mouse(MouseEvent {
711 kind,
712 column: cx,
713 row: cy,
714 modifiers,
715 }))))
716}
717
718pub(crate) fn parse_csi_sgr_mouse(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
719 // ESC [ < Cb ; Cx ; Cy (;) (M or m)
720
721 assert!(buffer.starts_with(&[b'\x1B', b'[', b'<'])); // ESC [ <
722
723 if !buffer.ends_with(&[b'm']) && !buffer.ends_with(&[b'M']) {
724 return Ok(None);
725 }
726
727 let s = std::str::from_utf8(&buffer[3..buffer.len() - 1])
728 .map_err(|_| could_not_parse_event_error())?;
729 let mut split = s.split(';');
730
731 let cb = next_parsed::<u8>(&mut split)?;
732 let (kind, modifiers) = parse_cb(cb)?;
733
734 // See http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking
735 // The upper left character position on the terminal is denoted as 1,1.
736 // Subtract 1 to keep it synced with cursor
737 let cx = next_parsed::<u16>(&mut split)? - 1;
738 let cy = next_parsed::<u16>(&mut split)? - 1;
739
740 // When button 3 in Cb is used to represent mouse release, you can't tell which button was
741 // released. SGR mode solves this by having the sequence end with a lowercase m if it's a
742 // button release and an uppercase M if it's a button press.
743 //
744 // We've already checked that the last character is a lowercase or uppercase M at the start of
745 // this function, so we just need one if.
746 let kind = if buffer.last() == Some(&b'm') {
747 match kind {
748 MouseEventKind::Down(button) => MouseEventKind::Up(button),
749 other => other,
750 }
751 } else {
752 kind
753 };
754
755 Ok(Some(InternalEvent::Event(Event::Mouse(MouseEvent {
756 kind,
757 column: cx,
758 row: cy,
759 modifiers,
760 }))))
761}
762
763/// Cb is the byte of a mouse input that contains the button being used, the key modifiers being
764/// held and whether the mouse is dragging or not.
765///
766/// Bit layout of cb, from low to high:
767///
768/// - button number
769/// - button number
770/// - shift
771/// - meta (alt)
772/// - control
773/// - mouse is dragging
774/// - button number
775/// - button number
776fn parse_cb(cb: u8) -> io::Result<(MouseEventKind, KeyModifiers)> {
777 let button_number = (cb & 0b0000_0011) | ((cb & 0b1100_0000) >> 4);
778 let dragging = cb & 0b0010_0000 == 0b0010_0000;
779
780 let kind = match (button_number, dragging) {
781 (0, false) => MouseEventKind::Down(MouseButton::Left),
782 (1, false) => MouseEventKind::Down(MouseButton::Middle),
783 (2, false) => MouseEventKind::Down(MouseButton::Right),
784 (0, true) => MouseEventKind::Drag(MouseButton::Left),
785 (1, true) => MouseEventKind::Drag(MouseButton::Middle),
786 (2, true) => MouseEventKind::Drag(MouseButton::Right),
787 (3, false) => MouseEventKind::Up(MouseButton::Left),
788 (3, true) | (4, true) | (5, true) => MouseEventKind::Moved,
789 (4, false) => MouseEventKind::ScrollUp,
790 (5, false) => MouseEventKind::ScrollDown,
791 (6, false) => MouseEventKind::ScrollLeft,
792 (7, false) => MouseEventKind::ScrollRight,
793 // We do not support other buttons.
794 _ => return Err(could_not_parse_event_error()),
795 };
796
797 let mut modifiers = KeyModifiers::empty();
798
799 if cb & 0b0000_0100 == 0b0000_0100 {
800 modifiers |= KeyModifiers::SHIFT;
801 }
802 if cb & 0b0000_1000 == 0b0000_1000 {
803 modifiers |= KeyModifiers::ALT;
804 }
805 if cb & 0b0001_0000 == 0b0001_0000 {
806 modifiers |= KeyModifiers::CONTROL;
807 }
808
809 Ok((kind, modifiers))
810}
811
812#[cfg(feature = "bracketed-paste")]
813pub(crate) fn parse_csi_bracketed_paste(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
814 // ESC [ 2 0 0 ~ pasted text ESC 2 0 1 ~
815 assert!(buffer.starts_with(b"\x1B[200~"));
816
817 if !buffer.ends_with(needle:b"\x1b[201~") {
818 Ok(None)
819 } else {
820 let paste: String = String::from_utf8_lossy(&buffer[6..buffer.len() - 6]).to_string();
821 Ok(Some(InternalEvent::Event(Event::Paste(paste))))
822 }
823}
824
825pub(crate) fn parse_utf8_char(buffer: &[u8]) -> io::Result<Option<char>> {
826 match std::str::from_utf8(buffer) {
827 Ok(s) => {
828 let ch = s.chars().next().ok_or_else(could_not_parse_event_error)?;
829
830 Ok(Some(ch))
831 }
832 Err(_) => {
833 // from_utf8 failed, but we have to check if we need more bytes for code point
834 // and if all the bytes we have no are valid
835
836 let required_bytes = match buffer[0] {
837 // https://en.wikipedia.org/wiki/UTF-8#Description
838 (0x00..=0x7F) => 1, // 0xxxxxxx
839 (0xC0..=0xDF) => 2, // 110xxxxx 10xxxxxx
840 (0xE0..=0xEF) => 3, // 1110xxxx 10xxxxxx 10xxxxxx
841 (0xF0..=0xF7) => 4, // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
842 (0x80..=0xBF) | (0xF8..=0xFF) => return Err(could_not_parse_event_error()),
843 };
844
845 // More than 1 byte, check them for 10xxxxxx pattern
846 if required_bytes > 1 && buffer.len() > 1 {
847 for byte in &buffer[1..] {
848 if byte & !0b0011_1111 != 0b1000_0000 {
849 return Err(could_not_parse_event_error());
850 }
851 }
852 }
853
854 if buffer.len() < required_bytes {
855 // All bytes looks good so far, but we need more of them
856 Ok(None)
857 } else {
858 Err(could_not_parse_event_error())
859 }
860 }
861 }
862}
863
864#[cfg(test)]
865mod tests {
866 use crate::event::{KeyEventState, KeyModifiers, MouseButton, MouseEvent};
867
868 use super::*;
869
870 #[test]
871 fn test_esc_key() {
872 assert_eq!(
873 parse_event(b"\x1B", false).unwrap(),
874 Some(InternalEvent::Event(Event::Key(KeyCode::Esc.into()))),
875 );
876 }
877
878 #[test]
879 fn test_possible_esc_sequence() {
880 assert_eq!(parse_event(b"\x1B", true).unwrap(), None,);
881 }
882
883 #[test]
884 fn test_alt_key() {
885 assert_eq!(
886 parse_event(b"\x1Bc", false).unwrap(),
887 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
888 KeyCode::Char('c'),
889 KeyModifiers::ALT
890 )))),
891 );
892 }
893
894 #[test]
895 fn test_alt_shift() {
896 assert_eq!(
897 parse_event(b"\x1BH", false).unwrap(),
898 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
899 KeyCode::Char('H'),
900 KeyModifiers::ALT | KeyModifiers::SHIFT
901 )))),
902 );
903 }
904
905 #[test]
906 fn test_alt_ctrl() {
907 assert_eq!(
908 parse_event(b"\x1B\x14", false).unwrap(),
909 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
910 KeyCode::Char('t'),
911 KeyModifiers::ALT | KeyModifiers::CONTROL
912 )))),
913 );
914 }
915
916 #[test]
917 fn test_parse_event_subsequent_calls() {
918 // The main purpose of this test is to check if we're passing
919 // correct slice to other parse_ functions.
920
921 // parse_csi_cursor_position
922 assert_eq!(
923 parse_event(b"\x1B[20;10R", false).unwrap(),
924 Some(InternalEvent::CursorPosition(9, 19))
925 );
926
927 // parse_csi
928 assert_eq!(
929 parse_event(b"\x1B[D", false).unwrap(),
930 Some(InternalEvent::Event(Event::Key(KeyCode::Left.into()))),
931 );
932
933 // parse_csi_modifier_key_code
934 assert_eq!(
935 parse_event(b"\x1B[2D", false).unwrap(),
936 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
937 KeyCode::Left,
938 KeyModifiers::SHIFT
939 ))))
940 );
941
942 // parse_csi_special_key_code
943 assert_eq!(
944 parse_event(b"\x1B[3~", false).unwrap(),
945 Some(InternalEvent::Event(Event::Key(KeyCode::Delete.into()))),
946 );
947
948 // parse_csi_bracketed_paste
949 #[cfg(feature = "bracketed-paste")]
950 assert_eq!(
951 parse_event(b"\x1B[200~on and on and on\x1B[201~", false).unwrap(),
952 Some(InternalEvent::Event(Event::Paste(
953 "on and on and on".to_string()
954 ))),
955 );
956
957 // parse_csi_rxvt_mouse
958 assert_eq!(
959 parse_event(b"\x1B[32;30;40;M", false).unwrap(),
960 Some(InternalEvent::Event(Event::Mouse(MouseEvent {
961 kind: MouseEventKind::Down(MouseButton::Left),
962 column: 29,
963 row: 39,
964 modifiers: KeyModifiers::empty(),
965 })))
966 );
967
968 // parse_csi_normal_mouse
969 assert_eq!(
970 parse_event(b"\x1B[M0\x60\x70", false).unwrap(),
971 Some(InternalEvent::Event(Event::Mouse(MouseEvent {
972 kind: MouseEventKind::Down(MouseButton::Left),
973 column: 63,
974 row: 79,
975 modifiers: KeyModifiers::CONTROL,
976 })))
977 );
978
979 // parse_csi_sgr_mouse
980 assert_eq!(
981 parse_event(b"\x1B[<0;20;10;M", false).unwrap(),
982 Some(InternalEvent::Event(Event::Mouse(MouseEvent {
983 kind: MouseEventKind::Down(MouseButton::Left),
984 column: 19,
985 row: 9,
986 modifiers: KeyModifiers::empty(),
987 })))
988 );
989
990 // parse_utf8_char
991 assert_eq!(
992 parse_event("Ž".as_bytes(), false).unwrap(),
993 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
994 KeyCode::Char('Ž'),
995 KeyModifiers::SHIFT
996 )))),
997 );
998 }
999
1000 #[test]
1001 fn test_parse_event() {
1002 assert_eq!(
1003 parse_event(b"\t", false).unwrap(),
1004 Some(InternalEvent::Event(Event::Key(KeyCode::Tab.into()))),
1005 );
1006 }
1007
1008 #[test]
1009 fn test_parse_csi_cursor_position() {
1010 assert_eq!(
1011 parse_csi_cursor_position(b"\x1B[20;10R").unwrap(),
1012 Some(InternalEvent::CursorPosition(9, 19))
1013 );
1014 }
1015
1016 #[test]
1017 fn test_parse_csi() {
1018 assert_eq!(
1019 parse_csi(b"\x1B[D").unwrap(),
1020 Some(InternalEvent::Event(Event::Key(KeyCode::Left.into()))),
1021 );
1022 }
1023
1024 #[test]
1025 fn test_parse_csi_modifier_key_code() {
1026 assert_eq!(
1027 parse_csi_modifier_key_code(b"\x1B[2D").unwrap(),
1028 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1029 KeyCode::Left,
1030 KeyModifiers::SHIFT
1031 )))),
1032 );
1033 }
1034
1035 #[test]
1036 fn test_parse_csi_special_key_code() {
1037 assert_eq!(
1038 parse_csi_special_key_code(b"\x1B[3~").unwrap(),
1039 Some(InternalEvent::Event(Event::Key(KeyCode::Delete.into()))),
1040 );
1041 }
1042
1043 #[test]
1044 fn test_parse_csi_special_key_code_multiple_values_not_supported() {
1045 assert_eq!(
1046 parse_csi_special_key_code(b"\x1B[3;2~").unwrap(),
1047 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1048 KeyCode::Delete,
1049 KeyModifiers::SHIFT
1050 )))),
1051 );
1052 }
1053
1054 #[cfg(feature = "bracketed-paste")]
1055 #[test]
1056 fn test_parse_csi_bracketed_paste() {
1057 //
1058 assert_eq!(
1059 parse_event(b"\x1B[200~o", false).unwrap(),
1060 None,
1061 "A partial bracketed paste isn't parsed"
1062 );
1063 assert_eq!(
1064 parse_event(b"\x1B[200~o\x1B[2D", false).unwrap(),
1065 None,
1066 "A partial bracketed paste containing another escape code isn't parsed"
1067 );
1068 assert_eq!(
1069 parse_event(b"\x1B[200~o\x1B[2D\x1B[201~", false).unwrap(),
1070 Some(InternalEvent::Event(Event::Paste("o\x1B[2D".to_string())))
1071 );
1072 }
1073
1074 #[test]
1075 fn test_parse_csi_focus() {
1076 assert_eq!(
1077 parse_csi(b"\x1B[O").unwrap(),
1078 Some(InternalEvent::Event(Event::FocusLost))
1079 );
1080 }
1081
1082 #[test]
1083 fn test_parse_csi_rxvt_mouse() {
1084 assert_eq!(
1085 parse_csi_rxvt_mouse(b"\x1B[32;30;40;M").unwrap(),
1086 Some(InternalEvent::Event(Event::Mouse(MouseEvent {
1087 kind: MouseEventKind::Down(MouseButton::Left),
1088 column: 29,
1089 row: 39,
1090 modifiers: KeyModifiers::empty(),
1091 })))
1092 );
1093 }
1094
1095 #[test]
1096 fn test_parse_csi_normal_mouse() {
1097 assert_eq!(
1098 parse_csi_normal_mouse(b"\x1B[M0\x60\x70").unwrap(),
1099 Some(InternalEvent::Event(Event::Mouse(MouseEvent {
1100 kind: MouseEventKind::Down(MouseButton::Left),
1101 column: 63,
1102 row: 79,
1103 modifiers: KeyModifiers::CONTROL,
1104 })))
1105 );
1106 }
1107
1108 #[test]
1109 fn test_parse_csi_sgr_mouse() {
1110 assert_eq!(
1111 parse_csi_sgr_mouse(b"\x1B[<0;20;10;M").unwrap(),
1112 Some(InternalEvent::Event(Event::Mouse(MouseEvent {
1113 kind: MouseEventKind::Down(MouseButton::Left),
1114 column: 19,
1115 row: 9,
1116 modifiers: KeyModifiers::empty(),
1117 })))
1118 );
1119 assert_eq!(
1120 parse_csi_sgr_mouse(b"\x1B[<0;20;10M").unwrap(),
1121 Some(InternalEvent::Event(Event::Mouse(MouseEvent {
1122 kind: MouseEventKind::Down(MouseButton::Left),
1123 column: 19,
1124 row: 9,
1125 modifiers: KeyModifiers::empty(),
1126 })))
1127 );
1128 assert_eq!(
1129 parse_csi_sgr_mouse(b"\x1B[<0;20;10;m").unwrap(),
1130 Some(InternalEvent::Event(Event::Mouse(MouseEvent {
1131 kind: MouseEventKind::Up(MouseButton::Left),
1132 column: 19,
1133 row: 9,
1134 modifiers: KeyModifiers::empty(),
1135 })))
1136 );
1137 assert_eq!(
1138 parse_csi_sgr_mouse(b"\x1B[<0;20;10m").unwrap(),
1139 Some(InternalEvent::Event(Event::Mouse(MouseEvent {
1140 kind: MouseEventKind::Up(MouseButton::Left),
1141 column: 19,
1142 row: 9,
1143 modifiers: KeyModifiers::empty(),
1144 })))
1145 );
1146 }
1147
1148 #[test]
1149 fn test_utf8() {
1150 // https://www.php.net/manual/en/reference.pcre.pattern.modifiers.php#54805
1151
1152 // 'Valid ASCII' => "a",
1153 assert_eq!(parse_utf8_char(b"a").unwrap(), Some('a'),);
1154
1155 // 'Valid 2 Octet Sequence' => "\xc3\xb1",
1156 assert_eq!(parse_utf8_char(&[0xC3, 0xB1]).unwrap(), Some('ñ'),);
1157
1158 // 'Invalid 2 Octet Sequence' => "\xc3\x28",
1159 assert!(parse_utf8_char(&[0xC3, 0x28]).is_err());
1160
1161 // 'Invalid Sequence Identifier' => "\xa0\xa1",
1162 assert!(parse_utf8_char(&[0xA0, 0xA1]).is_err());
1163
1164 // 'Valid 3 Octet Sequence' => "\xe2\x82\xa1",
1165 assert_eq!(
1166 parse_utf8_char(&[0xE2, 0x81, 0xA1]).unwrap(),
1167 Some('\u{2061}'),
1168 );
1169
1170 // 'Invalid 3 Octet Sequence (in 2nd Octet)' => "\xe2\x28\xa1",
1171 assert!(parse_utf8_char(&[0xE2, 0x28, 0xA1]).is_err());
1172
1173 // 'Invalid 3 Octet Sequence (in 3rd Octet)' => "\xe2\x82\x28",
1174 assert!(parse_utf8_char(&[0xE2, 0x82, 0x28]).is_err());
1175
1176 // 'Valid 4 Octet Sequence' => "\xf0\x90\x8c\xbc",
1177 assert_eq!(
1178 parse_utf8_char(&[0xF0, 0x90, 0x8C, 0xBC]).unwrap(),
1179 Some('𐌼'),
1180 );
1181
1182 // 'Invalid 4 Octet Sequence (in 2nd Octet)' => "\xf0\x28\x8c\xbc",
1183 assert!(parse_utf8_char(&[0xF0, 0x28, 0x8C, 0xBC]).is_err());
1184
1185 // 'Invalid 4 Octet Sequence (in 3rd Octet)' => "\xf0\x90\x28\xbc",
1186 assert!(parse_utf8_char(&[0xF0, 0x90, 0x28, 0xBC]).is_err());
1187
1188 // 'Invalid 4 Octet Sequence (in 4th Octet)' => "\xf0\x28\x8c\x28",
1189 assert!(parse_utf8_char(&[0xF0, 0x28, 0x8C, 0x28]).is_err());
1190 }
1191
1192 #[test]
1193 fn test_parse_char_event_lowercase() {
1194 assert_eq!(
1195 parse_event(b"c", false).unwrap(),
1196 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1197 KeyCode::Char('c'),
1198 KeyModifiers::empty()
1199 )))),
1200 );
1201 }
1202
1203 #[test]
1204 fn test_parse_char_event_uppercase() {
1205 assert_eq!(
1206 parse_event(b"C", false).unwrap(),
1207 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1208 KeyCode::Char('C'),
1209 KeyModifiers::SHIFT
1210 )))),
1211 );
1212 }
1213
1214 #[test]
1215 fn test_parse_basic_csi_u_encoded_key_code() {
1216 assert_eq!(
1217 parse_csi_u_encoded_key_code(b"\x1B[97u").unwrap(),
1218 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1219 KeyCode::Char('a'),
1220 KeyModifiers::empty()
1221 )))),
1222 );
1223 assert_eq!(
1224 parse_csi_u_encoded_key_code(b"\x1B[97;2u").unwrap(),
1225 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1226 KeyCode::Char('A'),
1227 KeyModifiers::SHIFT
1228 )))),
1229 );
1230 assert_eq!(
1231 parse_csi_u_encoded_key_code(b"\x1B[97;7u").unwrap(),
1232 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1233 KeyCode::Char('a'),
1234 KeyModifiers::ALT | KeyModifiers::CONTROL
1235 )))),
1236 );
1237 }
1238
1239 #[test]
1240 fn test_parse_basic_csi_u_encoded_key_code_special_keys() {
1241 assert_eq!(
1242 parse_csi_u_encoded_key_code(b"\x1B[13u").unwrap(),
1243 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1244 KeyCode::Enter,
1245 KeyModifiers::empty()
1246 )))),
1247 );
1248 assert_eq!(
1249 parse_csi_u_encoded_key_code(b"\x1B[27u").unwrap(),
1250 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1251 KeyCode::Esc,
1252 KeyModifiers::empty()
1253 )))),
1254 );
1255 assert_eq!(
1256 parse_csi_u_encoded_key_code(b"\x1B[57358u").unwrap(),
1257 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1258 KeyCode::CapsLock,
1259 KeyModifiers::empty()
1260 )))),
1261 );
1262 assert_eq!(
1263 parse_csi_u_encoded_key_code(b"\x1B[57376u").unwrap(),
1264 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1265 KeyCode::F(13),
1266 KeyModifiers::empty()
1267 )))),
1268 );
1269 assert_eq!(
1270 parse_csi_u_encoded_key_code(b"\x1B[57428u").unwrap(),
1271 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1272 KeyCode::Media(MediaKeyCode::Play),
1273 KeyModifiers::empty()
1274 )))),
1275 );
1276 assert_eq!(
1277 parse_csi_u_encoded_key_code(b"\x1B[57441u").unwrap(),
1278 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1279 KeyCode::Modifier(ModifierKeyCode::LeftShift),
1280 KeyModifiers::SHIFT,
1281 )))),
1282 );
1283 }
1284
1285 #[test]
1286 fn test_parse_csi_u_encoded_keypad_code() {
1287 assert_eq!(
1288 parse_csi_u_encoded_key_code(b"\x1B[57399u").unwrap(),
1289 Some(InternalEvent::Event(Event::Key(
1290 KeyEvent::new_with_kind_and_state(
1291 KeyCode::Char('0'),
1292 KeyModifiers::empty(),
1293 KeyEventKind::Press,
1294 KeyEventState::KEYPAD,
1295 )
1296 ))),
1297 );
1298 assert_eq!(
1299 parse_csi_u_encoded_key_code(b"\x1B[57419u").unwrap(),
1300 Some(InternalEvent::Event(Event::Key(
1301 KeyEvent::new_with_kind_and_state(
1302 KeyCode::Up,
1303 KeyModifiers::empty(),
1304 KeyEventKind::Press,
1305 KeyEventState::KEYPAD,
1306 )
1307 ))),
1308 );
1309 }
1310
1311 #[test]
1312 fn test_parse_csi_u_encoded_key_code_with_types() {
1313 assert_eq!(
1314 parse_csi_u_encoded_key_code(b"\x1B[97;1u").unwrap(),
1315 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1316 KeyCode::Char('a'),
1317 KeyModifiers::empty(),
1318 KeyEventKind::Press,
1319 )))),
1320 );
1321 assert_eq!(
1322 parse_csi_u_encoded_key_code(b"\x1B[97;1:1u").unwrap(),
1323 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1324 KeyCode::Char('a'),
1325 KeyModifiers::empty(),
1326 KeyEventKind::Press,
1327 )))),
1328 );
1329 assert_eq!(
1330 parse_csi_u_encoded_key_code(b"\x1B[97;5:1u").unwrap(),
1331 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1332 KeyCode::Char('a'),
1333 KeyModifiers::CONTROL,
1334 KeyEventKind::Press,
1335 )))),
1336 );
1337 assert_eq!(
1338 parse_csi_u_encoded_key_code(b"\x1B[97;1:2u").unwrap(),
1339 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1340 KeyCode::Char('a'),
1341 KeyModifiers::empty(),
1342 KeyEventKind::Repeat,
1343 )))),
1344 );
1345 assert_eq!(
1346 parse_csi_u_encoded_key_code(b"\x1B[97;1:3u").unwrap(),
1347 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1348 KeyCode::Char('a'),
1349 KeyModifiers::empty(),
1350 KeyEventKind::Release,
1351 )))),
1352 );
1353 }
1354
1355 #[test]
1356 fn test_parse_csi_u_encoded_key_code_has_modifier_on_modifier_press() {
1357 assert_eq!(
1358 parse_csi_u_encoded_key_code(b"\x1B[57449u").unwrap(),
1359 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1360 KeyCode::Modifier(ModifierKeyCode::RightAlt),
1361 KeyModifiers::ALT,
1362 KeyEventKind::Press,
1363 )))),
1364 );
1365 assert_eq!(
1366 parse_csi_u_encoded_key_code(b"\x1B[57449;3:3u").unwrap(),
1367 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1368 KeyCode::Modifier(ModifierKeyCode::RightAlt),
1369 KeyModifiers::ALT,
1370 KeyEventKind::Release,
1371 )))),
1372 );
1373 assert_eq!(
1374 parse_csi_u_encoded_key_code(b"\x1B[57450u").unwrap(),
1375 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1376 KeyCode::Modifier(ModifierKeyCode::RightSuper),
1377 KeyModifiers::SUPER,
1378 )))),
1379 );
1380 assert_eq!(
1381 parse_csi_u_encoded_key_code(b"\x1B[57451u").unwrap(),
1382 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1383 KeyCode::Modifier(ModifierKeyCode::RightHyper),
1384 KeyModifiers::HYPER,
1385 )))),
1386 );
1387 assert_eq!(
1388 parse_csi_u_encoded_key_code(b"\x1B[57452u").unwrap(),
1389 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1390 KeyCode::Modifier(ModifierKeyCode::RightMeta),
1391 KeyModifiers::META,
1392 )))),
1393 );
1394 }
1395
1396 #[test]
1397 fn test_parse_csi_u_encoded_key_code_with_extra_modifiers() {
1398 assert_eq!(
1399 parse_csi_u_encoded_key_code(b"\x1B[97;9u").unwrap(),
1400 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1401 KeyCode::Char('a'),
1402 KeyModifiers::SUPER
1403 )))),
1404 );
1405 assert_eq!(
1406 parse_csi_u_encoded_key_code(b"\x1B[97;17u").unwrap(),
1407 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1408 KeyCode::Char('a'),
1409 KeyModifiers::HYPER,
1410 )))),
1411 );
1412 assert_eq!(
1413 parse_csi_u_encoded_key_code(b"\x1B[97;33u").unwrap(),
1414 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1415 KeyCode::Char('a'),
1416 KeyModifiers::META,
1417 )))),
1418 );
1419 }
1420
1421 #[test]
1422 fn test_parse_csi_u_encoded_key_code_with_extra_state() {
1423 assert_eq!(
1424 parse_csi_u_encoded_key_code(b"\x1B[97;65u").unwrap(),
1425 Some(InternalEvent::Event(Event::Key(
1426 KeyEvent::new_with_kind_and_state(
1427 KeyCode::Char('a'),
1428 KeyModifiers::empty(),
1429 KeyEventKind::Press,
1430 KeyEventState::CAPS_LOCK,
1431 )
1432 ))),
1433 );
1434 assert_eq!(
1435 parse_csi_u_encoded_key_code(b"\x1B[49;129u").unwrap(),
1436 Some(InternalEvent::Event(Event::Key(
1437 KeyEvent::new_with_kind_and_state(
1438 KeyCode::Char('1'),
1439 KeyModifiers::empty(),
1440 KeyEventKind::Press,
1441 KeyEventState::NUM_LOCK,
1442 )
1443 ))),
1444 );
1445 }
1446
1447 #[test]
1448 fn test_parse_csi_u_with_shifted_keycode() {
1449 assert_eq!(
1450 // A-S-9 is equivalent to A-(
1451 parse_event(b"\x1B[57:40;4u", false).unwrap(),
1452 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1453 KeyCode::Char('('),
1454 KeyModifiers::ALT,
1455 )))),
1456 );
1457 assert_eq!(
1458 // A-S-minus is equivalent to A-_
1459 parse_event(b"\x1B[45:95;4u", false).unwrap(),
1460 Some(InternalEvent::Event(Event::Key(KeyEvent::new(
1461 KeyCode::Char('_'),
1462 KeyModifiers::ALT,
1463 )))),
1464 );
1465 }
1466
1467 #[test]
1468 fn test_parse_csi_special_key_code_with_types() {
1469 assert_eq!(
1470 parse_event(b"\x1B[;1:3B", false).unwrap(),
1471 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1472 KeyCode::Down,
1473 KeyModifiers::empty(),
1474 KeyEventKind::Release,
1475 )))),
1476 );
1477 assert_eq!(
1478 parse_event(b"\x1B[1;1:3B", false).unwrap(),
1479 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1480 KeyCode::Down,
1481 KeyModifiers::empty(),
1482 KeyEventKind::Release,
1483 )))),
1484 );
1485 }
1486
1487 #[test]
1488 fn test_parse_csi_numbered_escape_code_with_types() {
1489 assert_eq!(
1490 parse_event(b"\x1B[5;1:3~", false).unwrap(),
1491 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1492 KeyCode::PageUp,
1493 KeyModifiers::empty(),
1494 KeyEventKind::Release,
1495 )))),
1496 );
1497 assert_eq!(
1498 parse_event(b"\x1B[6;5:3~", false).unwrap(),
1499 Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
1500 KeyCode::PageDown,
1501 KeyModifiers::CONTROL,
1502 KeyEventKind::Release,
1503 )))),
1504 );
1505 }
1506}
1507