terminput/
lib.rs

1#![no_std]
2#![deny(missing_docs, clippy::unwrap_used)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![doc = include_str!("../README.md")]
5
6extern crate alloc;
7#[cfg(feature = "std")]
8extern crate std;
9
10#[cfg(feature = "std")]
11mod encoder;
12mod key;
13mod mouse;
14#[cfg(feature = "std")]
15mod parser;
16
17use alloc::string::String;
18use core::error::Error;
19use core::fmt;
20
21#[cfg(feature = "std")]
22pub use encoder::*;
23pub use key::*;
24pub use mouse::*;
25
26/// The supplied event could not be converted into the requested type.
27#[derive(Debug)]
28pub struct UnsupportedEvent(pub String);
29
30impl fmt::Display for UnsupportedEvent {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        write!(f, "Unsupported event: {}", self.0)
33    }
34}
35
36impl Error for UnsupportedEvent {}
37
38/// An application event.
39#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Hash)]
40#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
41pub enum Event {
42    /// The application gained focus.
43    FocusGained,
44    /// The application lost focus.
45    FocusLost,
46    /// A keyboard input event.
47    Key(KeyEvent),
48    /// A mouse input event.
49    Mouse(MouseEvent),
50    /// A string that was pasted into the application.
51    Paste(String),
52    /// An resize event with new dimensions after resize.
53    Resize {
54        /// New number of rows.
55        rows: u32,
56        /// New number of columns.
57        cols: u32,
58    },
59}
60
61/// Whether to include [`KeyEventKind::Repeat`] when checking for key down events.
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum Repeats {
64    /// Include key repeat events.
65    Include,
66    /// Exclude key repeat events.
67    Exclude,
68}
69
70impl Event {
71    /// Returns the contained event if this is a [`KeyEvent`].
72    pub fn as_key(&self) -> Option<KeyEvent> {
73        if let Self::Key(key_event) = self {
74            Some(*key_event)
75        } else {
76            None
77        }
78    }
79
80    /// Returns whether the event is a [`KeyEvent`].
81    pub fn is_key(&self) -> bool {
82        self.as_key().is_some()
83    }
84
85    /// Returns the contained event if it is a key press event.
86    ///
87    /// If [`Repeats::Include`] is passed, both [`KeyEventKind::Press`] and [`KeyEventKind::Repeat`]
88    /// are considered press events.
89    ///
90    /// If [`Repeats::Exclude`] is passed, only [`KeyEventKind::Press`] is considered.
91    pub fn as_key_press(&self, repeats: Repeats) -> Option<KeyEvent> {
92        if repeats == Repeats::Include {
93            if let Self::Key(
94                key_event @ KeyEvent {
95                    kind: KeyEventKind::Press | KeyEventKind::Repeat,
96                    ..
97                },
98            ) = self
99            {
100                Some(*key_event)
101            } else {
102                None
103            }
104        } else if let Self::Key(
105            key_event @ KeyEvent {
106                kind: KeyEventKind::Press,
107                ..
108            },
109        ) = self
110        {
111            Some(*key_event)
112        } else {
113            None
114        }
115    }
116
117    /// Returns whether the contained event is a key press event.
118    ///
119    /// If [`Repeats::Include`] is passed, both [`KeyEventKind::Press`] and [`KeyEventKind::Repeat`]
120    /// are considered press events.
121    ///
122    /// If [`Repeats::Exclude`] is passed, only [`KeyEventKind::Press`] is considered.
123    pub fn is_key_press(&self, repeats: Repeats) -> bool {
124        self.as_key_press(repeats).is_some()
125    }
126
127    /// Returns the contained event if it is a [`KeyEventKind::Repeat`] key event.
128    pub fn as_key_repeat(&self) -> Option<KeyEvent> {
129        if let Self::Key(
130            key_event @ KeyEvent {
131                kind: KeyEventKind::Repeat,
132                ..
133            },
134        ) = self
135        {
136            Some(*key_event)
137        } else {
138            None
139        }
140    }
141
142    /// Returns whether the contained event is a [`KeyEventKind::Repeat`] key event.
143    pub fn is_key_repeat(&self) -> bool {
144        self.as_key_repeat().is_some()
145    }
146
147    /// Returns the contained event if it is a [`KeyEventKind::Release`] key event.
148    pub fn as_key_release(&self) -> Option<KeyEvent> {
149        if let Self::Key(
150            key_event @ KeyEvent {
151                kind: KeyEventKind::Release,
152                ..
153            },
154        ) = self
155        {
156            Some(*key_event)
157        } else {
158            None
159        }
160    }
161
162    /// Returns whether the contained event is a [`KeyEventKind::Release`] key event.
163    pub fn is_key_release(&self) -> bool {
164        self.as_key_release().is_some()
165    }
166
167    /// Returns the contained event if it is a [`MouseEvent`].
168    pub fn as_mouse(&self) -> Option<MouseEvent> {
169        if let Self::Mouse(mouse_event) = self {
170            Some(*mouse_event)
171        } else {
172            None
173        }
174    }
175
176    /// Returns whether the contained event is a [`MouseEvent`].
177    pub fn is_mouse(&self) -> bool {
178        self.as_mouse().is_some()
179    }
180
181    /// Returns the contained event if it is a [`MouseEventKind::Down`] mouse event.
182    pub fn as_mouse_down(&self) -> Option<(MouseEvent, MouseButton)> {
183        if let Self::Mouse(
184            mouse_event @ MouseEvent {
185                kind: MouseEventKind::Down(button),
186                ..
187            },
188        ) = self
189        {
190            Some((*mouse_event, *button))
191        } else {
192            None
193        }
194    }
195
196    /// Returns whether the event is a [`MouseEventKind::Down`] mouse event.
197    pub fn is_mouse_down(&self) -> bool {
198        self.as_mouse_down().is_some()
199    }
200
201    /// Returns the contained event if it is a [`MouseEventKind::Up`] mouse event.
202    pub fn as_mouse_up(&self) -> Option<(MouseEvent, MouseButton)> {
203        if let Self::Mouse(
204            mouse_event @ MouseEvent {
205                kind: MouseEventKind::Up(button),
206                ..
207            },
208        ) = self
209        {
210            Some((*mouse_event, *button))
211        } else {
212            None
213        }
214    }
215
216    /// Returns whether the event is a [`MouseEventKind::Up`] mouse event.
217    pub fn is_mouse_up(&self) -> bool {
218        self.as_mouse_up().is_some()
219    }
220
221    /// Returns the contained event if it is a [`MouseEventKind::Drag`] mouse event.
222    pub fn as_mouse_drag(&self) -> Option<(MouseEvent, MouseButton)> {
223        if let Self::Mouse(
224            mouse_event @ MouseEvent {
225                kind: MouseEventKind::Drag(button),
226                ..
227            },
228        ) = self
229        {
230            Some((*mouse_event, *button))
231        } else {
232            None
233        }
234    }
235
236    /// Returns whether the event is a [`MouseEventKind::Drag`] mouse event.
237    pub fn is_mouse_drag(&self) -> bool {
238        self.as_mouse_drag().is_some()
239    }
240
241    /// Returns the contained event if it is a [`MouseEventKind::Moved`] mouse event.
242    pub fn as_mouse_move(&self) -> Option<MouseEvent> {
243        if let Self::Mouse(
244            mouse_event @ MouseEvent {
245                kind: MouseEventKind::Moved,
246                ..
247            },
248        ) = self
249        {
250            Some(*mouse_event)
251        } else {
252            None
253        }
254    }
255
256    /// Returns whether the event is a [`MouseEventKind::Moved`] mouse event.
257    pub fn is_mouse_move(&self) -> bool {
258        self.as_mouse_move().is_some()
259    }
260
261    /// Returns the contained event if it is a [`MouseEventKind::Scroll`] mouse event.
262    pub fn as_mouse_scroll(&self) -> Option<(MouseEvent, ScrollDirection)> {
263        if let Self::Mouse(
264            mouse_event @ MouseEvent {
265                kind: MouseEventKind::Scroll(direction),
266                ..
267            },
268        ) = self
269        {
270            Some((*mouse_event, *direction))
271        } else {
272            None
273        }
274    }
275
276    /// Returns whether the event is a [`MouseEventKind::Scroll`] mouse event.
277    pub fn is_mouse_scroll(&self) -> bool {
278        self.as_mouse_scroll().is_some()
279    }
280
281    /// Returns whether the event is [`Event::FocusGained`].
282    pub fn is_focus_gained(&self) -> bool {
283        *self == Self::FocusGained
284    }
285
286    /// Returns whether the event is [`Event::FocusLost`].
287    pub fn is_focus_lost(&self) -> bool {
288        *self == Self::FocusLost
289    }
290
291    /// Returns the pasted text if the event is [`Event::Paste`].
292    pub fn as_paste(&self) -> Option<&str> {
293        if let Self::Paste(text) = self {
294            Some(text)
295        } else {
296            None
297        }
298    }
299
300    /// Returns whether the event is [`Event::Paste`].
301    pub fn is_paste(&self) -> bool {
302        self.as_paste().is_some()
303    }
304
305    /// Returns the `(rows, cols)` from the contained event if it is a [`Event::Resize`] event.
306    pub fn as_resize(&self) -> Option<(u32, u32)> {
307        if let Self::Resize { rows, cols } = self {
308            Some((*rows, *cols))
309        } else {
310            None
311        }
312    }
313
314    /// Returns whether the event is [`Event::Resize`].
315    pub fn is_resize(&self) -> bool {
316        self.as_resize().is_some()
317    }
318}