requestty_ui/events/
mod.rs1use std::io;
4
5#[cfg(feature = "crossterm")]
6mod crossterm;
7#[cfg(feature = "termion")]
8mod termion;
9
10#[cfg(feature = "crossterm")]
11pub use self::crossterm::CrosstermEvents;
12
13#[cfg(feature = "termion")]
14pub use self::termion::TermionEvents;
15
16mod keys;
17mod movement;
18
19pub use keys::{KeyCode, KeyEvent, KeyModifiers};
20pub use movement::Movement;
21
22#[cfg(any(feature = "crossterm", feature = "termion"))]
24#[cfg_attr(docsrs, doc(cfg(any(feature = "crossterm", feature = "termion"))))]
25pub fn get_events() -> impl EventIterator {
26 #[cfg(feature = "crossterm")]
27 return CrosstermEvents::new();
28
29 #[cfg(not(feature = "crossterm"))]
34 return TermionEvents::new();
35}
36
37pub trait EventIterator {
39 fn next_event(&mut self) -> io::Result<KeyEvent>;
41}
42
43#[derive(Debug, Clone)]
57pub struct TestEvents<E: Iterator<Item = KeyEvent>> {
58 events: E,
59}
60
61impl<E: Iterator<Item = KeyEvent>> TestEvents<E> {
62 pub fn new<I: IntoIterator<IntoIter = E, Item = KeyEvent>>(iter: I) -> Self {
64 Self {
65 events: iter.into_iter(),
66 }
67 }
68}
69
70impl TestEvents<std::iter::Empty<KeyEvent>> {
71 pub fn empty() -> Self {
73 Self {
74 events: std::iter::empty(),
75 }
76 }
77}
78
79impl<E: Iterator<Item = KeyEvent>> EventIterator for TestEvents<E> {
80 fn next_event(&mut self) -> io::Result<KeyEvent> {
81 Ok(self
82 .events
83 .next()
84 .expect("Events ran out, but another one was requested"))
85 }
86}
87
88impl<E: Iterator<Item = KeyEvent>> Drop for TestEvents<E> {
89 fn drop(&mut self) {
90 let mut count = 0;
91
92 while self.events.next().is_some() {
93 count += 1
94 }
95
96 assert_eq!(
97 count, 0,
98 "Events did not fully run out, {} events have not been consumed",
99 count
100 );
101 }
102}