diff options
author | Akshay <[email protected]> | 2020-07-18 16:36:40 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2020-07-18 16:36:40 +0100 |
commit | 0b4af96a515d51c409c6dafef406542dee9da3d4 (patch) | |
tree | 21acafc98b48988d43627b8b8374ad02358f25d1 /src/command.rs | |
parent | 29d49dddaae57d59a2c99c376a632a0d9560dcfc (diff) |
add smooth error handling
Diffstat (limited to 'src/command.rs')
-rw-r--r-- | src/command.rs | 95 |
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 @@ | |||
1 | use std::fmt; | ||
2 | |||
1 | use cursive::view::Resizable; | 3 | use cursive::view::Resizable; |
2 | use cursive::views::{Dialog, EditView}; | 4 | use cursive::views::{Dialog, EditView}; |
3 | use cursive::Cursive; | 5 | use 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)] |
30 | pub enum Command { | 32 | pub 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)] | ||
44 | pub enum CommandLineError { | ||
45 | InvalidCommand(String), | ||
46 | InvalidArg(u32), // position | ||
47 | NotEnoughArgs(String, u32), | ||
48 | } | ||
49 | |||
50 | impl std::error::Error for CommandLineError {} | ||
51 | |||
52 | impl 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 | |||
64 | type Result<T> = std::result::Result<T, CommandLineError>; | ||
65 | |||
41 | impl Command { | 66 | impl 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 | } |