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
|
use textmode::Textmode as _;
pub struct Readline {
prompt: String,
input_line: String,
action: async_std::channel::Sender<crate::action::Action>,
}
impl Readline {
pub fn new(
action: async_std::channel::Sender<crate::action::Action>,
) -> Self {
Self {
prompt: "$ ".into(),
input_line: "".into(),
action,
}
}
pub async fn handle_key(&mut self, key: textmode::Key) -> bool {
match key {
textmode::Key::String(s) => self.add_input(&s),
textmode::Key::Char(c) => {
self.add_input(&c.to_string());
}
textmode::Key::Ctrl(b'c') => self.clear_input(),
textmode::Key::Ctrl(b'd') => {
return true;
}
textmode::Key::Ctrl(b'm') => {
self.action
.send(crate::action::Action::Run(self.input()))
.await
.unwrap();
self.clear_input();
}
textmode::Key::Backspace => self.backspace(),
_ => {}
}
self.action
.send(crate::action::Action::Render)
.await
.unwrap();
false
}
pub fn lines(&self) -> usize {
1 // XXX handle wrapping, multiline prompts
}
pub async fn render(
&self,
out: &mut textmode::Output,
) -> anyhow::Result<()> {
out.move_to(23, 0);
out.write_str(&self.prompt);
out.write_str(&self.input_line);
Ok(())
}
fn input(&self) -> String {
self.input_line.clone()
}
fn add_input(&mut self, s: &str) {
self.input_line.push_str(s);
}
fn backspace(&mut self) {
self.input_line.pop();
}
fn clear_input(&mut self) {
self.input_line.clear();
}
}
|