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
|
use cursive::view::Resizable;
use cursive::views::{Dialog, EditView};
use cursive::Cursive;
use crate::app::App;
pub fn open_command_window(s: &mut Cursive) {
let command_window = Dialog::around(EditView::new().on_submit(call_on_app).fixed_width(40));
s.add_layer(command_window);
}
fn call_on_app(s: &mut Cursive, input: &str) {
s.call_on_name("Main", |view: &mut App| {
view.parse_command(input);
});
// special command that requires access to
// our main cursive object, has to be parsed again
// here
// TODO: fix this somehow
if Command::from_string(input) == Command::Quit {
s.quit();
}
s.pop_layer();
}
#[derive(PartialEq)]
pub enum Command {
Add(String, String, Option<u32>, Option<bool>), // habit name, habit type, optional goal, auto tracked
MonthPrev,
MonthNext,
Delete(String),
Quit,
Blank,
}
impl Command {
pub fn from_string<P: AsRef<str>>(input: P) -> Self {
let mut strings: Vec<&str> = input.as_ref().trim().split(' ').collect();
if strings.is_empty() {
return Command::Blank;
}
let first = strings.first().unwrap().to_string();
let mut args: Vec<String> = strings.iter_mut().skip(1).map(|s| s.to_string()).collect();
match first.as_ref() {
"add" | "a" => {
if args.len() < 2 {
return Command::Blank;
}
let goal = args.get(2).map(|g| g.parse::<u32>().ok()).flatten();
let auto = args.get(3).map(|g| g.parse::<bool>().ok()).flatten();
return Command::Add(
args.get_mut(0).unwrap().to_string(),
args.get_mut(1).unwrap().to_string(),
goal,
auto,
);
}
"delete" | "d" => {
if args.len() < 1 {
return Command::Blank;
}
return Command::Delete(args[0].to_string());
}
"mprev" | "month-prev" => return Command::MonthPrev,
"mnext" | "month-next" => return Command::MonthNext,
"q" | "quit" => return Command::Quit,
_ => return Command::Blank,
}
}
}
|