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
|
#[derive(Debug)]
pub enum Action {
Render,
Run(String),
UpdateFocus(crate::state::Focus),
Resize((u16, u16)),
}
pub struct Debouncer {
pending: async_std::sync::Mutex<Pending>,
cvar: async_std::sync::Condvar,
}
impl Debouncer {
pub async fn recv(&self) -> Option<Action> {
let mut pending = self
.cvar
.wait_until(self.pending.lock().await, |pending| {
pending.has_event()
})
.await;
pending.get_event()
}
async fn send(&self, action: Option<Action>) {
let mut pending = self.pending.lock().await;
pending.new_event(&action);
self.cvar.notify_one();
}
}
#[derive(Default)]
struct Pending {
render: Option<()>,
run: std::collections::VecDeque<String>,
focus: Option<crate::state::Focus>,
size: Option<(u16, u16)>,
done: bool,
}
impl Pending {
fn new() -> Self {
Self::default()
}
fn has_event(&self) -> bool {
self.render.is_some()
|| !self.run.is_empty()
|| self.focus.is_some()
|| self.size.is_some()
}
fn get_event(&mut self) -> Option<Action> {
if self.size.is_some() {
return Some(Action::Resize(self.size.take().unwrap()));
}
if !self.run.is_empty() {
return Some(Action::Run(self.run.pop_front().unwrap()));
}
if self.focus.is_some() {
return Some(Action::UpdateFocus(self.focus.take().unwrap()));
}
if self.render.is_some() {
self.render.take();
return Some(Action::Render);
}
if self.done {
return None;
}
unreachable!()
}
fn new_event(&mut self, action: &Option<Action>) {
match action {
Some(Action::Run(cmd)) => self.run.push_back(cmd.to_string()),
Some(Action::UpdateFocus(focus)) => self.focus = Some(*focus),
Some(Action::Render) => self.render = Some(()),
Some(Action::Resize(size)) => self.size = Some(*size),
None => self.done = true,
}
}
}
pub fn debounce(
input: async_std::channel::Receiver<Action>,
) -> async_std::sync::Arc<Debouncer> {
let debouncer = std::sync::Arc::new(Debouncer {
pending: async_std::sync::Mutex::new(Pending::new()),
cvar: async_std::sync::Condvar::new(),
});
{
let debouncer = std::sync::Arc::clone(&debouncer);
async_std::task::spawn(async move {
while let Ok(action) = input.recv().await {
debouncer.send(Some(action)).await;
}
debouncer.send(None).await;
});
}
debouncer
}
|