Skip to main content

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}