requestty_ui/events/
movement.rs

1use super::{KeyCode, KeyEvent, KeyModifiers};
2
3/// Movements that can be captured from a [`KeyEvent`]. See the individual variants for
4/// what keys they capture
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum Movement {
7    /// The Up arrow key, and `k` is captured
8    Up,
9    /// The Down arrow key, and `j` is captured
10    Down,
11    /// The Left arrow key, `h`, and `ctrl+b` is captured
12    Left,
13    /// The Right arrow key, `l`, and `ctrl+f` is captured
14    Right,
15    /// The PageUp key is captured
16    PageUp,
17    /// The PageDown key is captured
18    PageDown,
19    /// The Home key, `g`, `ctrl+a`  is captured
20    Home,
21    /// The End key, `G`, `ctrl+e`  is captured
22    End,
23    /// `ctrl+right`, `alt+right`, and `alt+f` are captured
24    NextWord,
25    /// `ctrl+left`, `alt+left`, and `alt+b` are captured
26    PrevWord,
27}
28
29impl Movement {
30    /// Gets the movement (if any) from the current event
31    ///
32    /// It also captures 'h', 'j', 'k', 'l', 'g', and 'G'. If these are required
33    /// for some input, it must be checked before capturing a movement
34    pub fn try_from_key(key: KeyEvent) -> Option<Movement> {
35        let movement = match key.code {
36            KeyCode::Left
37                if key
38                    .modifiers
39                    .intersects(KeyModifiers::CONTROL | KeyModifiers::ALT) =>
40            {
41                Movement::PrevWord
42            }
43            KeyCode::Char('b') if key.modifiers.contains(KeyModifiers::ALT) => Movement::PrevWord,
44
45            KeyCode::Right
46                if key
47                    .modifiers
48                    .intersects(KeyModifiers::CONTROL | KeyModifiers::ALT) =>
49            {
50                Movement::NextWord
51            }
52            KeyCode::Char('f') if key.modifiers.contains(KeyModifiers::ALT) => Movement::NextWord,
53
54            KeyCode::Up => Movement::Up,
55            KeyCode::Char('k') => Movement::Up,
56
57            KeyCode::Down => Movement::Down,
58            KeyCode::Char('j') => Movement::Down,
59
60            KeyCode::Left => Movement::Left,
61            KeyCode::Char('h') => Movement::Left,
62            KeyCode::Char('b') if key.modifiers.contains(KeyModifiers::CONTROL) => Movement::Left,
63
64            KeyCode::Right => Movement::Right,
65            KeyCode::Char('l') => Movement::Right,
66            KeyCode::Char('f') if key.modifiers.contains(KeyModifiers::CONTROL) => Movement::Right,
67
68            KeyCode::PageUp => Movement::PageUp,
69            KeyCode::PageDown => Movement::PageDown,
70
71            KeyCode::Home => Movement::Home,
72            KeyCode::Char('g') => Movement::Home,
73            KeyCode::Char('a') if key.modifiers.contains(KeyModifiers::CONTROL) => Movement::Home,
74
75            KeyCode::End => Movement::End,
76            KeyCode::Char('G') => Movement::End,
77            KeyCode::Char('e') if key.modifiers.contains(KeyModifiers::CONTROL) => Movement::End,
78            _ => return None,
79        };
80
81        Some(movement)
82    }
83}
84
85#[test]
86fn test_movement() {
87    assert_eq!(
88        Movement::try_from_key(KeyEvent::new(KeyCode::Left, KeyModifiers::empty())),
89        Some(Movement::Left)
90    );
91    assert_eq!(
92        Movement::try_from_key(KeyEvent::new(KeyCode::Char('h'), KeyModifiers::empty())),
93        Some(Movement::Left)
94    );
95    assert_eq!(
96        Movement::try_from_key(KeyEvent::new(KeyCode::Char('b'), KeyModifiers::CONTROL)),
97        Some(Movement::Left)
98    );
99
100    assert_eq!(
101        Movement::try_from_key(KeyEvent::new(KeyCode::Left, KeyModifiers::CONTROL,)),
102        Some(Movement::PrevWord)
103    );
104    assert_eq!(
105        Movement::try_from_key(KeyEvent::new(KeyCode::Left, KeyModifiers::ALT)),
106        Some(Movement::PrevWord)
107    );
108    assert_eq!(
109        Movement::try_from_key(KeyEvent::new(KeyCode::Char('b'), KeyModifiers::ALT)),
110        Some(Movement::PrevWord)
111    );
112
113    assert_eq!(
114        Movement::try_from_key(KeyEvent::new(KeyCode::Right, KeyModifiers::empty())),
115        Some(Movement::Right)
116    );
117    assert_eq!(
118        Movement::try_from_key(KeyEvent::new(KeyCode::Char('l'), KeyModifiers::empty())),
119        Some(Movement::Right)
120    );
121    assert_eq!(
122        Movement::try_from_key(KeyEvent::new(KeyCode::Char('f'), KeyModifiers::CONTROL)),
123        Some(Movement::Right)
124    );
125
126    assert_eq!(
127        Movement::try_from_key(KeyEvent::new(KeyCode::Right, KeyModifiers::CONTROL)),
128        Some(Movement::NextWord)
129    );
130    assert_eq!(
131        Movement::try_from_key(KeyEvent::new(KeyCode::Right, KeyModifiers::ALT)),
132        Some(Movement::NextWord)
133    );
134    assert_eq!(
135        Movement::try_from_key(KeyEvent::new(KeyCode::Char('f'), KeyModifiers::ALT)),
136        Some(Movement::NextWord)
137    );
138
139    assert_eq!(
140        Movement::try_from_key(KeyEvent::new(KeyCode::Up, KeyModifiers::empty())),
141        Some(Movement::Up)
142    );
143    assert_eq!(
144        Movement::try_from_key(KeyEvent::new(KeyCode::Char('k'), KeyModifiers::empty())),
145        Some(Movement::Up)
146    );
147
148    assert_eq!(
149        Movement::try_from_key(KeyEvent::new(KeyCode::Down, KeyModifiers::empty())),
150        Some(Movement::Down)
151    );
152    assert_eq!(
153        Movement::try_from_key(KeyEvent::new(KeyCode::Char('j'), KeyModifiers::empty())),
154        Some(Movement::Down)
155    );
156
157    assert_eq!(
158        Movement::try_from_key(KeyEvent::new(KeyCode::PageDown, KeyModifiers::empty())),
159        Some(Movement::PageDown)
160    );
161    assert_eq!(
162        Movement::try_from_key(KeyEvent::new(KeyCode::PageUp, KeyModifiers::empty())),
163        Some(Movement::PageUp)
164    );
165
166    assert_eq!(
167        Movement::try_from_key(KeyEvent::new(KeyCode::Home, KeyModifiers::empty())),
168        Some(Movement::Home)
169    );
170    assert_eq!(
171        Movement::try_from_key(KeyEvent::new(KeyCode::Char('g'), KeyModifiers::empty())),
172        Some(Movement::Home)
173    );
174    assert_eq!(
175        Movement::try_from_key(KeyEvent::new(KeyCode::Char('a'), KeyModifiers::CONTROL)),
176        Some(Movement::Home)
177    );
178
179    assert_eq!(
180        Movement::try_from_key(KeyEvent::new(KeyCode::End, KeyModifiers::empty())),
181        Some(Movement::End)
182    );
183    assert_eq!(
184        Movement::try_from_key(KeyEvent::new(KeyCode::Char('G'), KeyModifiers::empty())),
185        Some(Movement::End)
186    );
187    assert_eq!(
188        Movement::try_from_key(KeyEvent::new(KeyCode::Char('e'), KeyModifiers::CONTROL)),
189        Some(Movement::End)
190    );
191}