tui_textarea/input/
termwiz.rs

1use super::{Input, Key};
2use termwiz::input::{
3    InputEvent, KeyCode, KeyEvent, Modifiers, MouseButtons, MouseEvent, PixelMouseEvent,
4};
5
6impl From<InputEvent> for Input {
7    /// Convert [`termwiz::input::InputEvent`] into [`Input`].
8    fn from(input: InputEvent) -> Self {
9        match input {
10            InputEvent::Key(key) => Self::from(key),
11            InputEvent::Mouse(mouse) => Self::from(mouse),
12            InputEvent::PixelMouse(mouse) => Self::from(mouse),
13            _ => Self::default(),
14        }
15    }
16}
17
18impl From<KeyCode> for Key {
19    /// Convert [`termwiz::input::KeyCode`] into [`Key`].
20    fn from(key: KeyCode) -> Self {
21        match key {
22            KeyCode::Char(c) => Key::Char(c),
23            KeyCode::Backspace => Key::Backspace,
24            KeyCode::Tab => Key::Tab,
25            KeyCode::Enter => Key::Enter,
26            KeyCode::Escape => Key::Esc,
27            KeyCode::PageUp => Key::PageUp,
28            KeyCode::PageDown => Key::PageDown,
29            KeyCode::End => Key::End,
30            KeyCode::Home => Key::Home,
31            KeyCode::LeftArrow => Key::Left,
32            KeyCode::RightArrow => Key::Right,
33            KeyCode::UpArrow => Key::Up,
34            KeyCode::DownArrow => Key::Down,
35            KeyCode::Delete => Key::Delete,
36            KeyCode::Function(x) => Key::F(x),
37            KeyCode::Copy => Key::Copy,
38            KeyCode::Cut => Key::Cut,
39            KeyCode::Paste => Key::Paste,
40            _ => Key::Null,
41        }
42    }
43}
44
45impl From<KeyEvent> for Input {
46    /// Convert [`termwiz::input::KeyEvent`] into [`Input`].
47    fn from(key: KeyEvent) -> Self {
48        let KeyEvent { key, modifiers } = key;
49        let key = Key::from(key);
50        let ctrl = modifiers.contains(Modifiers::CTRL);
51        let alt = modifiers.contains(Modifiers::ALT);
52        let shift = modifiers.contains(Modifiers::SHIFT);
53
54        Self {
55            key,
56            ctrl,
57            alt,
58            shift,
59        }
60    }
61}
62
63impl From<MouseButtons> for Key {
64    /// Convert [`termwiz::input::MouseButtons`] into [`Key`].
65    fn from(buttons: MouseButtons) -> Self {
66        if buttons.contains(MouseButtons::VERT_WHEEL) {
67            if buttons.contains(MouseButtons::WHEEL_POSITIVE) {
68                Key::MouseScrollUp
69            } else {
70                Key::MouseScrollDown
71            }
72        } else {
73            Key::Null
74        }
75    }
76}
77
78impl From<MouseEvent> for Input {
79    /// Convert [`termwiz::input::MouseEvent`] into [`Input`].
80    fn from(mouse: MouseEvent) -> Self {
81        let MouseEvent {
82            mouse_buttons,
83            modifiers,
84            ..
85        } = mouse;
86        let key = Key::from(mouse_buttons);
87        let ctrl = modifiers.contains(Modifiers::CTRL);
88        let alt = modifiers.contains(Modifiers::ALT);
89        let shift = modifiers.contains(Modifiers::SHIFT);
90
91        Self {
92            key,
93            ctrl,
94            alt,
95            shift,
96        }
97    }
98}
99
100impl From<PixelMouseEvent> for Input {
101    /// Convert [`termwiz::input::PixelMouseEvent`] into [`Input`].
102    fn from(mouse: PixelMouseEvent) -> Self {
103        let PixelMouseEvent {
104            mouse_buttons,
105            modifiers,
106            ..
107        } = mouse;
108
109        let key = Key::from(mouse_buttons);
110        let ctrl = modifiers.contains(Modifiers::CTRL);
111        let alt = modifiers.contains(Modifiers::ALT);
112        let shift = modifiers.contains(Modifiers::SHIFT);
113
114        Self {
115            key,
116            ctrl,
117            alt,
118            shift,
119        }
120    }
121}
122
123#[cfg(test)]
124mod tests {
125    use super::*;
126    use crate::input::tests::input;
127
128    fn key_event(key: KeyCode, modifiers: Modifiers) -> KeyEvent {
129        KeyEvent { key, modifiers }
130    }
131
132    fn mouse_event(mouse_buttons: MouseButtons, modifiers: Modifiers) -> MouseEvent {
133        MouseEvent {
134            mouse_buttons,
135            modifiers,
136            x: 1,
137            y: 1,
138        }
139    }
140
141    fn pixel_mouse_event(mouse_buttons: MouseButtons, modifiers: Modifiers) -> PixelMouseEvent {
142        PixelMouseEvent {
143            mouse_buttons,
144            modifiers,
145            x_pixels: 1,
146            y_pixels: 1,
147        }
148    }
149
150    #[test]
151    fn key_to_input() {
152        for (from, to) in [
153            (
154                key_event(KeyCode::Char('a'), Modifiers::empty()),
155                input(Key::Char('a'), false, false, false),
156            ),
157            (
158                key_event(KeyCode::Enter, Modifiers::empty()),
159                input(Key::Enter, false, false, false),
160            ),
161            (
162                key_event(KeyCode::LeftArrow, Modifiers::CTRL),
163                input(Key::Left, true, false, false),
164            ),
165            (
166                key_event(KeyCode::RightArrow, Modifiers::SHIFT),
167                input(Key::Right, false, false, true),
168            ),
169            (
170                key_event(KeyCode::Home, Modifiers::ALT),
171                input(Key::Home, false, true, false),
172            ),
173            (
174                key_event(
175                    KeyCode::Function(1),
176                    Modifiers::ALT | Modifiers::CTRL | Modifiers::SHIFT,
177                ),
178                input(Key::F(1), true, true, true),
179            ),
180            (
181                key_event(KeyCode::NumLock, Modifiers::CTRL),
182                input(Key::Null, true, false, false),
183            ),
184        ] {
185            assert_eq!(Input::from(from.clone()), to, "{:?} -> {:?}", from, to);
186        }
187    }
188
189    #[test]
190    fn mouse_to_input() {
191        for (from, to) in [
192            (
193                mouse_event(MouseButtons::VERT_WHEEL, Modifiers::empty()),
194                input(Key::MouseScrollDown, false, false, false),
195            ),
196            (
197                mouse_event(
198                    MouseButtons::VERT_WHEEL | MouseButtons::WHEEL_POSITIVE,
199                    Modifiers::empty(),
200                ),
201                input(Key::MouseScrollUp, false, false, false),
202            ),
203            (
204                mouse_event(MouseButtons::VERT_WHEEL, Modifiers::CTRL),
205                input(Key::MouseScrollDown, true, false, false),
206            ),
207            (
208                mouse_event(MouseButtons::VERT_WHEEL, Modifiers::SHIFT),
209                input(Key::MouseScrollDown, false, false, true),
210            ),
211            (
212                mouse_event(MouseButtons::VERT_WHEEL, Modifiers::ALT),
213                input(Key::MouseScrollDown, false, true, false),
214            ),
215            (
216                mouse_event(
217                    MouseButtons::VERT_WHEEL,
218                    Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
219                ),
220                input(Key::MouseScrollDown, true, true, true),
221            ),
222            (
223                mouse_event(MouseButtons::LEFT, Modifiers::empty()),
224                input(Key::Null, false, false, false),
225            ),
226        ] {
227            assert_eq!(Input::from(from.clone()), to, "{:?} -> {:?}", from, to);
228
229            let from = pixel_mouse_event(from.mouse_buttons, from.modifiers);
230            assert_eq!(Input::from(from.clone()), to, "{:?} -> {:?}", from, to);
231        }
232    }
233
234    #[test]
235    fn event_to_input() {
236        for (from, to) in [
237            (
238                InputEvent::Key(key_event(KeyCode::Char('a'), Modifiers::empty())),
239                input(Key::Char('a'), false, false, false),
240            ),
241            (
242                InputEvent::Mouse(mouse_event(MouseButtons::VERT_WHEEL, Modifiers::empty())),
243                input(Key::MouseScrollDown, false, false, false),
244            ),
245            (
246                InputEvent::PixelMouse(pixel_mouse_event(
247                    MouseButtons::VERT_WHEEL,
248                    Modifiers::empty(),
249                )),
250                input(Key::MouseScrollDown, false, false, false),
251            ),
252            (
253                InputEvent::Paste("x".into()),
254                input(Key::Null, false, false, false),
255            ),
256        ] {
257            assert_eq!(Input::from(from.clone()), to, "{:?} -> {:?}", from, to);
258        }
259    }
260}