aboutsummaryrefslogtreecommitdiff
path: root/src/command.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/command.rs')
-rw-r--r--src/command.rs95
1 files changed, 73 insertions, 22 deletions
diff --git a/src/command.rs b/src/command.rs
index 79d0fe5..d285138 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -1,3 +1,5 @@
1use std::fmt;
2
1use cursive::view::Resizable; 3use cursive::view::Resizable;
2use cursive::views::{Dialog, EditView}; 4use cursive::views::{Dialog, EditView};
3use cursive::Cursive; 5use cursive::Cursive;
@@ -19,7 +21,7 @@ fn call_on_app(s: &mut Cursive, input: &str) {
19 // our main cursive object, has to be parsed again 21 // our main cursive object, has to be parsed again
20 // here 22 // here
21 // TODO: fix this somehow 23 // TODO: fix this somehow
22 if Command::from_string(input) == Command::Quit { 24 if let Ok(Command::Quit) = Command::from_string(input) {
23 s.quit(); 25 s.quit();
24 } 26 }
25 27
@@ -28,7 +30,7 @@ fn call_on_app(s: &mut Cursive, input: &str) {
28 30
29#[derive(PartialEq)] 31#[derive(PartialEq)]
30pub enum Command { 32pub enum Command {
31 Add(String, Option<u32>, Option<bool>), // habit name, habit type, optional goal, auto tracked 33 Add(String, Option<u32>, bool),
32 MonthPrev, 34 MonthPrev,
33 MonthNext, 35 MonthNext,
34 Delete(String), 36 Delete(String),
@@ -38,46 +40,95 @@ pub enum Command {
38 Blank, 40 Blank,
39} 41}
40 42
43#[derive(Debug)]
44pub enum CommandLineError {
45 InvalidCommand(String),
46 InvalidArg(u32), // position
47 NotEnoughArgs(String, u32),
48}
49
50impl std::error::Error for CommandLineError {}
51
52impl fmt::Display for CommandLineError {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 match self {
55 CommandLineError::InvalidCommand(s) => write!(f, "Invalid command: `{}`", s),
56 CommandLineError::InvalidArg(p) => write!(f, "Invalid argument at position {}", p),
57 CommandLineError::NotEnoughArgs(s, n) => {
58 write!(f, "Command `{}` requires atleast {} argument(s)!", s, n)
59 }
60 }
61 }
62}
63
64type Result<T> = std::result::Result<T, CommandLineError>;
65
41impl Command { 66impl Command {
42 pub fn from_string<P: AsRef<str>>(input: P) -> Self { 67 pub fn from_string<P: AsRef<str>>(input: P) -> Result<Command> {
43 let mut strings: Vec<&str> = input.as_ref().trim().split(' ').collect(); 68 let mut strings: Vec<&str> = input.as_ref().trim().split(' ').collect();
44 if strings.is_empty() { 69 if strings.is_empty() {
45 return Command::Blank; 70 return Ok(Command::Blank);
46 } 71 }
47 72
48 let first = strings.first().unwrap().to_string(); 73 let first = strings.first().unwrap().to_string();
49 let mut args: Vec<String> = strings.iter_mut().skip(1).map(|s| s.to_string()).collect(); 74 let mut args: Vec<String> = strings.iter_mut().skip(1).map(|s| s.to_string()).collect();
50 match first.as_ref() { 75 match first.as_ref() {
51 "add" | "a" => { 76 "add" | "a" => {
52 if args.len() < 2 { 77 if args.is_empty() {
53 return Command::Blank; 78 return Err(CommandLineError::NotEnoughArgs(first, 1));
79 }
80 let goal = args
81 .get(1)
82 .map(|x| {
83 x.parse::<u32>()
84 .map_err(|_| CommandLineError::InvalidArg(1))
85 })
86 .transpose()?;
87 return Ok(Command::Add(
88 args.get_mut(0).unwrap().to_string(),
89 goal,
90 false,
91 ));
92 }
93 "add-auto" | "aa" => {
94 if args.is_empty() {
95 return Err(CommandLineError::NotEnoughArgs(first, 1));
54 } 96 }
55 let goal = args.get(1).map(|g| g.parse::<u32>().ok()).flatten(); 97 let goal = args
56 let auto = args.get(2).map(|g| if g == "auto" { true } else { false }); 98 .get(1)
57 return Command::Add(args.get_mut(0).unwrap().to_string(), goal, auto); 99 .map(|x| {
100 x.parse::<u32>()
101 .map_err(|_| CommandLineError::InvalidArg(1))
102 })
103 .transpose()?;
104 return Ok(Command::Add(
105 args.get_mut(0).unwrap().to_string(),
106 goal,
107 true,
108 ));
58 } 109 }
59 "delete" | "d" => { 110 "delete" | "d" => {
60 if args.len() < 1 { 111 if args.is_empty() {
61 return Command::Blank; 112 return Err(CommandLineError::NotEnoughArgs(first, 1));
62 } 113 }
63 return Command::Delete(args[0].to_string()); 114 return Ok(Command::Delete(args[0].to_string()));
64 } 115 }
65 "track-up" | "tup" => { 116 "track-up" | "tup" => {
66 if args.len() < 1 { 117 if args.is_empty() {
67 return Command::Blank; 118 return Err(CommandLineError::NotEnoughArgs(first, 1));
68 } 119 }
69 return Command::TrackUp(args[0].to_string()); 120 return Ok(Command::TrackUp(args[0].to_string()));
70 } 121 }
71 "track-down" | "tdown" => { 122 "track-down" | "tdown" => {
72 if args.len() < 1 { 123 if args.is_empty() {
73 return Command::Blank; 124 return Err(CommandLineError::NotEnoughArgs(first, 1));
74 } 125 }
75 return Command::TrackDown(args[0].to_string()); 126 return Ok(Command::TrackDown(args[0].to_string()));
76 } 127 }
77 "mprev" | "month-prev" => return Command::MonthPrev, 128 "mprev" | "month-prev" => return Ok(Command::MonthPrev),
78 "mnext" | "month-next" => return Command::MonthNext, 129 "mnext" | "month-next" => return Ok(Command::MonthNext),
79 "q" | "quit" => return Command::Quit, 130 "q" | "quit" => return Ok(Command::Quit),
80 _ => return Command::Blank, 131 s => return Err(CommandLineError::InvalidCommand(s.into())),
81 } 132 }
82 } 133 }
83} 134}