1use escriba_keymap::Key;
12use madori::AppEvent;
13use madori::event::{KeyCode, KeyEvent};
14
15#[must_use]
20pub fn translate_key(event: &KeyEvent) -> Option<Key> {
21 if !event.pressed {
22 return None;
23 }
24 let mods = event.modifiers;
25 let key = match event.key {
26 KeyCode::Enter => Key::Enter,
27 KeyCode::Escape => Key::Esc,
28 KeyCode::Backspace => Key::Backspace,
29 KeyCode::Tab => Key::Tab,
30 KeyCode::Up => Key::Up,
31 KeyCode::Down => Key::Down,
32 KeyCode::Left => Key::Left,
33 KeyCode::Right => Key::Right,
34 KeyCode::Home => Key::Home,
35 KeyCode::End => Key::End,
36 KeyCode::PageUp => Key::PageUp,
37 KeyCode::PageDown => Key::PageDown,
38 KeyCode::Space => Key::Char(' '),
39 KeyCode::Char(c) => {
40 if mods.ctrl && !mods.alt {
41 return Some(Key::Ctrl(c.to_ascii_lowercase()));
42 }
43 if mods.alt && !mods.ctrl {
44 return Some(Key::Alt(c.to_ascii_lowercase()));
45 }
46 Key::Char(c)
47 }
48 KeyCode::Delete | KeyCode::F(_) | KeyCode::Unknown => return None,
49 };
50 Some(key)
51}
52
53#[derive(Debug, Clone, PartialEq, Eq)]
55pub enum InputOutcome {
56 Key(Key),
58 Resized { width: u32, height: u32 },
60 Focus(bool),
62 Quit,
64 None,
66}
67
68#[must_use]
69pub fn translate_app_event(event: &AppEvent) -> InputOutcome {
70 match event {
71 AppEvent::Key(ke) => translate_key(ke).map_or(InputOutcome::None, InputOutcome::Key),
72 AppEvent::Resized { width, height } => InputOutcome::Resized {
73 width: *width,
74 height: *height,
75 },
76 AppEvent::Focused(f) => InputOutcome::Focus(*f),
77 AppEvent::CloseRequested => InputOutcome::Quit,
78 _ => InputOutcome::None,
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use madori::event::Modifiers;
87
88 fn key(kc: KeyCode, mods: Modifiers) -> KeyEvent {
89 KeyEvent {
90 key: kc,
91 pressed: true,
92 modifiers: mods,
93 text: None,
94 }
95 }
96
97 #[test]
98 fn char_without_modifiers() {
99 let k = translate_key(&key(KeyCode::Char('h'), Modifiers::default())).unwrap();
100 assert_eq!(k, Key::Char('h'));
101 }
102
103 #[test]
104 fn ctrl_char_becomes_ctrl_key() {
105 let mods = Modifiers {
106 ctrl: true,
107 ..Modifiers::default()
108 };
109 let k = translate_key(&key(KeyCode::Char('R'), mods)).unwrap();
110 assert_eq!(k, Key::Ctrl('r'));
111 }
112
113 #[test]
114 fn alt_char_becomes_alt_key() {
115 let mods = Modifiers {
116 alt: true,
117 ..Modifiers::default()
118 };
119 let k = translate_key(&key(KeyCode::Char('f'), mods)).unwrap();
120 assert_eq!(k, Key::Alt('f'));
121 }
122
123 #[test]
124 fn named_keys_map() {
125 assert_eq!(
126 translate_key(&key(KeyCode::Escape, Modifiers::default())).unwrap(),
127 Key::Esc
128 );
129 assert_eq!(
130 translate_key(&key(KeyCode::Enter, Modifiers::default())).unwrap(),
131 Key::Enter
132 );
133 assert_eq!(
134 translate_key(&key(KeyCode::Space, Modifiers::default())).unwrap(),
135 Key::Char(' ')
136 );
137 }
138
139 #[test]
140 fn release_returns_none() {
141 let mut e = key(KeyCode::Char('a'), Modifiers::default());
142 e.pressed = false;
143 assert!(translate_key(&e).is_none());
144 }
145
146 #[test]
147 fn close_event_quits() {
148 assert_eq!(
149 translate_app_event(&AppEvent::CloseRequested),
150 InputOutcome::Quit
151 );
152 }
153}