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 => Key::Delete,
51 KeyCode::F(_) | KeyCode::Unknown => return None,
52 };
53 Some(key)
54}
55
56#[derive(Debug, Clone, PartialEq, Eq)]
58pub enum InputOutcome {
59 Key(Key),
61 Resized { width: u32, height: u32 },
63 Focus(bool),
65 Quit,
67 None,
69}
70
71#[must_use]
72pub fn translate_app_event(event: &AppEvent) -> InputOutcome {
73 match event {
74 AppEvent::Key(ke) => translate_key(ke).map_or(InputOutcome::None, InputOutcome::Key),
75 AppEvent::Resized { width, height } => InputOutcome::Resized {
76 width: *width,
77 height: *height,
78 },
79 AppEvent::Focused(f) => InputOutcome::Focus(*f),
80 AppEvent::CloseRequested => InputOutcome::Quit,
81 _ => InputOutcome::None,
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use madori::event::Modifiers;
90
91 fn key(kc: KeyCode, mods: Modifiers) -> KeyEvent {
92 KeyEvent {
93 key: kc,
94 pressed: true,
95 modifiers: mods,
96 text: None,
97 }
98 }
99
100 #[test]
101 fn char_without_modifiers() {
102 let k = translate_key(&key(KeyCode::Char('h'), Modifiers::default())).unwrap();
103 assert_eq!(k, Key::Char('h'));
104 }
105
106 #[test]
107 fn ctrl_char_becomes_ctrl_key() {
108 let mods = Modifiers {
109 ctrl: true,
110 ..Modifiers::default()
111 };
112 let k = translate_key(&key(KeyCode::Char('R'), mods)).unwrap();
113 assert_eq!(k, Key::Ctrl('r'));
114 }
115
116 #[test]
117 fn alt_char_becomes_alt_key() {
118 let mods = Modifiers {
119 alt: true,
120 ..Modifiers::default()
121 };
122 let k = translate_key(&key(KeyCode::Char('f'), mods)).unwrap();
123 assert_eq!(k, Key::Alt('f'));
124 }
125
126 #[test]
127 fn named_keys_map() {
128 assert_eq!(
129 translate_key(&key(KeyCode::Escape, Modifiers::default())).unwrap(),
130 Key::Esc
131 );
132 assert_eq!(
133 translate_key(&key(KeyCode::Enter, Modifiers::default())).unwrap(),
134 Key::Enter
135 );
136 assert_eq!(
137 translate_key(&key(KeyCode::Space, Modifiers::default())).unwrap(),
138 Key::Char(' ')
139 );
140 }
141
142 #[test]
143 fn release_returns_none() {
144 let mut e = key(KeyCode::Char('a'), Modifiers::default());
145 e.pressed = false;
146 assert!(translate_key(&e).is_none());
147 }
148
149 #[test]
150 fn close_event_quits() {
151 assert_eq!(
152 translate_app_event(&AppEvent::CloseRequested),
153 InputOutcome::Quit
154 );
155 }
156}