1use std::{thread, time};
4use std::sync::mpsc;
5use std::error::Error;
6
7use futures::{select, pin_mut, future::FutureExt};
8use futures::StreamExt;
9use futures::executor::block_on;
10use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
11use crossterm::event; use crossterm::event::{Event, EventStream, KeyCode, KeyModifiers};
13pub struct NbStdin {
19 reader: EventStream
20}
21
22impl NbStdin {
24
25pub fn start() -> Self {
27 let nb = NbStdin{reader: EventStream::new()};
28 enable_raw_mode().unwrap();
29 nb
30}
31
32pub fn stop(&self) {
34 disable_raw_mode().unwrap();
35}
36
37pub fn break_with_esc(e: Event) -> bool {
39 match e {
40 Event::Key(ke) => {
41 if ke.code == KeyCode::Esc { return true; }
42 if ke.modifiers == KeyModifiers::CONTROL {
43 if ke.code == KeyCode::Char('c') { return true; } }
45 if ke.modifiers == KeyModifiers::CONTROL | KeyModifiers::SHIFT {
46 if ke.code == KeyCode::Char('C') { return true; } }
48 ()
49 },
50 _ => ()
51 }
52 false
53}
54
55pub async fn async_stdin(&mut self, lambda: fn (e: Event) -> bool) -> Result<bool, Box<dyn Error>> {
57 match self.reader.next().await { None => (),
59 Some(Err(e)) => { println!("Error: {:?}", e); () },
60 Some(Ok(e)) => { if lambda(e) { return Ok(true); } }
61 }
62 Ok(false)
63}
64
65pub async fn select_stdin(timeout: time::Duration) -> Result<Option<Event>, Box<dyn Error>> {
67 let now = time::Instant::now();
68 let mut reader = EventStream::new();
69 loop {
70 let c = reader.next().fuse();
71 pin_mut!(c);
72 select! {
73 e = c => {
74 match e {
75 None => (),
76 Some(Err(e)) => { println!("Error: {:?}", e); () },
77 Some(Ok(e)) => { return Ok(Some(e)); }
78 }
79 },
80 complete => break,
81 default => {
82 if now.elapsed() < timeout { () } else { break; } }
84 }
85 }
86 Ok(None)
87}
88
89pub fn async_non_blocking_stdin(timeout: time::Duration, lambda: fn (e: Event) -> bool) -> bool {
91 let (tx, rx) = mpsc::channel();
92 let _handle = thread::spawn(move || {
93 loop {
94 match block_on(NbStdin::select_stdin(timeout)).unwrap() { None => (),
96 Some(e) => {
97 match tx.send(e) {
98 Ok(()) => break,
99 Err(_) => ()
100 }
101 }
102 }
103 }
104 ()
105 });
106 match rx.recv_timeout(timeout) {
107 Ok(e) => { if lambda(e) { return true; } },
108 Err(mpsc::RecvTimeoutError::Timeout) => (),
109 Err(mpsc::RecvTimeoutError::Disconnected) => { println!("disconnected"); () } }
111 false
112}
113
114pub fn non_blocking_stdin(timeout: time::Duration, lambda: fn (e: Event) -> bool) -> bool {
116 let (tx, rx) = mpsc::channel();
117 let _handle = thread::spawn(move || {
118 loop {
119 if !event::poll(timeout).unwrap() { break; } else {
121 match event::read().unwrap() { e => {
123 match tx.send(e) {
124 Ok(()) => (),
125 Err(_) => ()
126 }
127 break;
128 }
129 }
130 }
131 }
132 ()
133 });
134 match rx.recv_timeout(timeout) {
135 Ok(e) => { if lambda(e) { return true; } },
136 Err(mpsc::RecvTimeoutError::Timeout) => (),
137 Err(mpsc::RecvTimeoutError::Disconnected) => { println!("disconnected"); () } }
139 false
140}
141
142}