glues_tui/
input.rs

1use tui_textarea::Input as TextAreaInput;
2
3#[derive(Clone, Debug)]
4pub enum Input {
5    Key(KeyEvent),
6    Paste(String),
7    Resize(u16, u16),
8}
9
10#[derive(Clone, Debug)]
11pub struct KeyEvent {
12    pub code: KeyCode,
13    pub modifiers: KeyModifiers,
14    pub kind: KeyEventKind,
15}
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub enum KeyCode {
19    Char(char),
20    F(u8),
21    Backspace,
22    Enter,
23    Left,
24    Right,
25    Up,
26    Down,
27    Tab,
28    Delete,
29    Home,
30    End,
31    PageUp,
32    PageDown,
33    Esc,
34    Null,
35}
36
37#[derive(Clone, Copy, Debug, PartialEq, Eq)]
38pub enum KeyEventKind {
39    Press,
40    Release,
41    Repeat,
42}
43
44#[derive(Clone, Copy, Debug, PartialEq, Eq)]
45pub struct KeyModifiers {
46    pub ctrl: bool,
47    pub alt: bool,
48    pub shift: bool,
49}
50
51impl KeyModifiers {
52    pub const NONE: Self = Self {
53        ctrl: false,
54        alt: false,
55        shift: false,
56    };
57
58    pub const CONTROL: Self = Self {
59        ctrl: true,
60        alt: false,
61        shift: false,
62    };
63
64    pub fn new(ctrl: bool, alt: bool, shift: bool) -> Self {
65        Self { ctrl, alt, shift }
66    }
67}
68
69impl Default for KeyModifiers {
70    fn default() -> Self {
71        Self::NONE
72    }
73}
74
75#[cfg(not(target_arch = "wasm32"))]
76mod native {
77    use super::*;
78    use ratatui::crossterm::event as ct;
79
80    impl From<ct::Event> for Input {
81        fn from(event: ct::Event) -> Self {
82            match event {
83                ct::Event::Key(key) => Input::Key(key.into()),
84                ct::Event::Paste(paste) => Input::Paste(paste),
85                ct::Event::Resize(w, h) => Input::Resize(w, h),
86                _ => Input::Resize(0, 0),
87            }
88        }
89    }
90
91    impl From<ct::KeyEvent> for KeyEvent {
92        fn from(key: ct::KeyEvent) -> Self {
93            let modifiers = KeyModifiers::new(
94                key.modifiers.contains(ct::KeyModifiers::CONTROL),
95                key.modifiers.contains(ct::KeyModifiers::ALT),
96                key.modifiers.contains(ct::KeyModifiers::SHIFT),
97            );
98
99            let code = match key.code {
100                ct::KeyCode::Char(c) => KeyCode::Char(c),
101                ct::KeyCode::F(n) => KeyCode::F(n),
102                ct::KeyCode::Backspace => KeyCode::Backspace,
103                ct::KeyCode::Enter => KeyCode::Enter,
104                ct::KeyCode::Left => KeyCode::Left,
105                ct::KeyCode::Right => KeyCode::Right,
106                ct::KeyCode::Up => KeyCode::Up,
107                ct::KeyCode::Down => KeyCode::Down,
108                ct::KeyCode::Tab => KeyCode::Tab,
109                ct::KeyCode::Delete => KeyCode::Delete,
110                ct::KeyCode::Home => KeyCode::Home,
111                ct::KeyCode::End => KeyCode::End,
112                ct::KeyCode::PageUp => KeyCode::PageUp,
113                ct::KeyCode::PageDown => KeyCode::PageDown,
114                ct::KeyCode::Esc => KeyCode::Esc,
115                _ => KeyCode::Null,
116            };
117
118            let kind = match key.kind {
119                ct::KeyEventKind::Press => KeyEventKind::Press,
120                ct::KeyEventKind::Release => KeyEventKind::Release,
121                ct::KeyEventKind::Repeat => KeyEventKind::Repeat,
122            };
123
124            KeyEvent {
125                code,
126                modifiers,
127                kind,
128            }
129        }
130    }
131}
132
133#[cfg(target_arch = "wasm32")]
134mod wasm {
135    use super::*;
136    use ratzilla::event as rz;
137
138    impl From<rz::KeyEvent> for KeyEvent {
139        fn from(event: rz::KeyEvent) -> Self {
140            let code = match event.code {
141                rz::KeyCode::Char(c) => KeyCode::Char(c),
142                rz::KeyCode::F(n) => KeyCode::F(n),
143                rz::KeyCode::Backspace => KeyCode::Backspace,
144                rz::KeyCode::Enter => KeyCode::Enter,
145                rz::KeyCode::Left => KeyCode::Left,
146                rz::KeyCode::Right => KeyCode::Right,
147                rz::KeyCode::Up => KeyCode::Up,
148                rz::KeyCode::Down => KeyCode::Down,
149                rz::KeyCode::Tab => KeyCode::Tab,
150                rz::KeyCode::Delete => KeyCode::Delete,
151                rz::KeyCode::Home => KeyCode::Home,
152                rz::KeyCode::End => KeyCode::End,
153                rz::KeyCode::PageUp => KeyCode::PageUp,
154                rz::KeyCode::PageDown => KeyCode::PageDown,
155                rz::KeyCode::Esc => KeyCode::Esc,
156                rz::KeyCode::Unidentified => KeyCode::Null,
157            };
158
159            KeyEvent {
160                code,
161                modifiers: KeyModifiers::new(event.ctrl, event.alt, event.shift),
162                kind: KeyEventKind::Press,
163            }
164        }
165    }
166}
167
168pub fn to_textarea_input(input: &Input) -> Option<TextAreaInput> {
169    match input {
170        Input::Key(key) => Some(key_to_textarea_input(key)),
171        _ => None,
172    }
173}
174
175pub fn key_to_textarea_input(key: &KeyEvent) -> TextAreaInput {
176    use tui_textarea::Key;
177
178    let key_code = match key.code {
179        KeyCode::Char(c) => Key::Char(c),
180        KeyCode::F(n) => Key::F(n),
181        KeyCode::Backspace => Key::Backspace,
182        KeyCode::Enter => Key::Enter,
183        KeyCode::Left => Key::Left,
184        KeyCode::Right => Key::Right,
185        KeyCode::Up => Key::Up,
186        KeyCode::Down => Key::Down,
187        KeyCode::Tab => Key::Tab,
188        KeyCode::Delete => Key::Delete,
189        KeyCode::Home => Key::Home,
190        KeyCode::End => Key::End,
191        KeyCode::PageUp => Key::PageUp,
192        KeyCode::PageDown => Key::PageDown,
193        KeyCode::Esc => Key::Esc,
194        KeyCode::Null => Key::Null,
195    };
196
197    TextAreaInput {
198        key: key_code,
199        ctrl: key.modifiers.ctrl,
200        alt: key.modifiers.alt,
201        shift: key.modifiers.shift,
202    }
203}