ratatui_textarea/input/mod.rs
1#[cfg(feature = "crossterm")]
2mod crossterm;
3#[cfg(feature = "termion")]
4mod termion;
5#[cfg(feature = "termwiz")]
6mod termwiz;
7
8#[cfg(feature = "arbitrary")]
9use arbitrary::Arbitrary;
10#[cfg(feature = "serde")]
11use serde::{Deserialize, Serialize};
12
13/// Backend-agnostic key input kind.
14///
15/// This type is marked as `#[non_exhaustive]` since more keys may be supported in the future.
16#[non_exhaustive]
17#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
18#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20#[derive(Default)]
21pub enum Key {
22 /// Normal letter key input
23 Char(char),
24 /// F1, F2, F3, ... keys
25 F(u8),
26 /// Backspace key
27 Backspace,
28 /// Enter or return key
29 Enter,
30 /// Left arrow key
31 Left,
32 /// Right arrow key
33 Right,
34 /// Up arrow key
35 Up,
36 /// Down arrow key
37 Down,
38 /// Tab key
39 Tab,
40 /// Delete key
41 Delete,
42 /// Home key
43 Home,
44 /// End key
45 End,
46 /// Page up key
47 PageUp,
48 /// Page down key
49 PageDown,
50 /// Escape key
51 Esc,
52 /// Copy key. This key is supported by termwiz only
53 Copy,
54 /// Cut key. This key is supported by termwiz only
55 Cut,
56 /// Paste key. This key is supported by termwiz only
57 Paste,
58 /// Virtual key to scroll down by mouse
59 MouseScrollDown,
60 /// Virtual key to scroll up by mouse
61 MouseScrollUp,
62 /// An invalid key input (this key is always ignored by [`TextArea`](crate::TextArea))
63 #[default]
64 Null,
65}
66
67/// Backend-agnostic key input type.
68///
69/// When `crossterm`, `termion`, `termwiz` features are enabled, converting respective key input types into this
70/// `Input` type is defined.
71/// ```ignore
72/// use ratatui_textarea::{TextArea, Input, Key};
73/// use crossterm::event::{Event, read};
74///
75/// let event = read().unwrap();
76///
77/// // `Input::from` can convert backend-native event into `Input`
78/// let input = Input::from(event.clone());
79/// // or `Into::into`
80/// let input: Input = event.clone().into();
81/// // Conversion from `KeyEvent` value is also available
82/// if let Event::Key(key) = event {
83/// let input = Input::from(key);
84/// }
85/// ```
86///
87/// Creating `Input` instance directly can cause backend-agnostic input as follows.
88///
89/// ```
90/// use ratatui_textarea::{TextArea, Input, Key};
91///
92/// let mut textarea = TextArea::default();
93///
94/// // Input Ctrl+A
95/// textarea.input(Input {
96/// key: Key::Char('a'),
97/// ctrl: true,
98/// alt: false,
99/// shift: false,
100/// });
101/// ```
102#[derive(Debug, Clone, Default, PartialEq, Hash, Eq)]
103#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
104#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
105pub struct Input {
106 /// Typed key.
107 pub key: Key,
108 /// Ctrl modifier key. `true` means Ctrl key was pressed.
109 pub ctrl: bool,
110 /// Alt modifier key. `true` means Alt key was pressed.
111 pub alt: bool,
112 /// Shift modifier key. `true` means Shift key was pressed.
113 pub shift: bool,
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[allow(dead_code)]
121 pub(crate) fn input(key: Key, ctrl: bool, alt: bool, shift: bool) -> Input {
122 Input {
123 key,
124 ctrl,
125 alt,
126 shift,
127 }
128 }
129
130 #[test]
131 #[cfg(feature = "arbitrary")]
132 fn arbitrary_input() {
133 let mut u = arbitrary::Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
134 Input::arbitrary(&mut u).unwrap();
135 }
136
137 #[test]
138 #[cfg(feature = "arbitrary")]
139 fn arbitrary_key() {
140 let mut u = arbitrary::Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
141 Key::arbitrary(&mut u).unwrap();
142 }
143}