-
-
Notifications
You must be signed in to change notification settings - Fork 79
/
event_reader.rs
106 lines (93 loc) · 3.51 KB
/
event_reader.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use crate::app::Task;
use crate::app::{ExternalMsg, InternalMsg, MsgIn};
use crate::input::Key;
use anyhow::Error;
use crossterm::event::{self, Event, MouseEventKind};
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
use std::thread;
use std::time::Duration;
pub(crate) struct EventReader {
task_sender: Sender<Task>,
stopper: Option<(Sender<bool>, Receiver<()>)>,
}
impl EventReader {
pub(crate) fn new(task_sender: Sender<Task>) -> Self {
Self {
task_sender,
stopper: None,
}
}
pub(crate) fn start(&mut self) {
let sender = self.task_sender.clone();
let (tx_stopper, rx_stopper) = mpsc::channel();
let (tx_ack, rx_ack) = mpsc::channel();
self.stopper = Some((tx_stopper, rx_ack));
thread::spawn(move || {
keep_reading(sender, rx_stopper, tx_ack);
});
}
pub(crate) fn stop(&self) {
if let Some((stopper, ack)) = &self.stopper {
stopper.send(true).unwrap_or_default(); // Let's not panic when xplr stops.
ack.recv().unwrap_or_default();
}
}
}
fn keep_reading(
tx_msg_in: Sender<Task>,
rx_stopper: Receiver<bool>,
tx_ack: Sender<()>,
) {
loop {
if rx_stopper.try_recv().unwrap_or(false) {
tx_ack.send(()).unwrap();
break;
} else if event::poll(std::time::Duration::from_millis(150)).unwrap_or_default()
{
// NOTE: The poll timeout need to stay low, else spawning sub subshell
// and start typing immediately will cause panic.
// To reproduce, press `:`, then press and hold `!`.
let res = match event::read() {
Ok(Event::Key(key)) => {
let key = Key::from_event(key);
let msg = MsgIn::Internal(InternalMsg::HandleKey(key));
tx_msg_in
.send(Task::new(msg, Some(key)))
.map_err(Error::new)
}
Ok(Event::Mouse(evt)) => match evt.kind {
MouseEventKind::ScrollUp => {
let msg = MsgIn::External(ExternalMsg::FocusPrevious);
tx_msg_in.send(Task::new(msg, None)).map_err(Error::new)
}
MouseEventKind::ScrollDown => {
let msg = MsgIn::External(ExternalMsg::FocusNext);
tx_msg_in.send(Task::new(msg, None)).map_err(Error::new)
}
_ => Ok(()),
},
Ok(Event::Resize(_, _)) => {
let msg = MsgIn::External(ExternalMsg::Refresh);
tx_msg_in.send(Task::new(msg, None)).map_err(Error::new)
}
Ok(Event::FocusGained) => Ok(()),
Ok(Event::FocusLost) => Ok(()),
Ok(Event::Paste(text)) => {
let msg = MsgIn::External(ExternalMsg::BufferInput(text));
tx_msg_in.send(Task::new(msg, None)).map_err(Error::new)
}
Err(e) => Err(Error::new(e)),
};
if let Err(e) = res {
tx_msg_in
.send(Task::new(
MsgIn::External(ExternalMsg::LogError(e.to_string())),
None,
))
.unwrap_or_default(); // Let's not panic when xplr stops
thread::sleep(Duration::from_secs(1));
}
}
}
}