diff options
-rw-r--r-- | src/command.rs | 98 |
1 files changed, 80 insertions, 18 deletions
diff --git a/src/command.rs b/src/command.rs index 38d48e9..a893430 100644 --- a/src/command.rs +++ b/src/command.rs | |||
@@ -122,7 +122,6 @@ pub enum Command { | |||
122 | #[derive(Debug)] | 122 | #[derive(Debug)] |
123 | pub enum CommandLineError { | 123 | pub enum CommandLineError { |
124 | InvalidCommand(String), // command name | 124 | InvalidCommand(String), // command name |
125 | InvalidArg(u32), // position | ||
126 | NotEnoughArgs(String, u32), // command name, required no. of args | 125 | NotEnoughArgs(String, u32), // command name, required no. of args |
127 | } | 126 | } |
128 | 127 | ||
@@ -132,7 +131,6 @@ impl fmt::Display for CommandLineError { | |||
132 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 131 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
133 | match self { | 132 | match self { |
134 | CommandLineError::InvalidCommand(s) => write!(f, "Invalid command: `{}`", s), | 133 | CommandLineError::InvalidCommand(s) => write!(f, "Invalid command: `{}`", s), |
135 | CommandLineError::InvalidArg(p) => write!(f, "Invalid argument at position {}", p), | ||
136 | CommandLineError::NotEnoughArgs(s, n) => { | 134 | CommandLineError::NotEnoughArgs(s, n) => { |
137 | write!(f, "Command `{}` requires atleast {} argument(s)!", s, n) | 135 | write!(f, "Command `{}` requires atleast {} argument(s)!", s, n) |
138 | } | 136 | } |
@@ -150,23 +148,9 @@ impl Command { | |||
150 | } | 148 | } |
151 | 149 | ||
152 | let first = strings.first().unwrap().to_string(); | 150 | let first = strings.first().unwrap().to_string(); |
153 | let mut args: Vec<String> = strings.iter_mut().skip(1).map(|s| s.to_string()).collect(); | 151 | let args: Vec<String> = strings.iter_mut().skip(1).map(|s| s.to_string()).collect(); |
154 | let mut _add = |auto: bool, first: String| { | 152 | let mut _add = |auto: bool, first: String| { |
155 | if args.is_empty() { | 153 | return parse_add(first, args.clone(), auto); |
156 | return Err(CommandLineError::NotEnoughArgs(first, 1)); | ||
157 | } | ||
158 | let goal = args | ||
159 | .get(1) | ||
160 | .map(|x| { | ||
161 | x.parse::<u32>() | ||
162 | .map_err(|_| CommandLineError::InvalidArg(2)) | ||
163 | }) | ||
164 | .transpose()?; | ||
165 | return Ok(Command::Add( | ||
166 | args.get_mut(0).unwrap().to_string(), | ||
167 | goal, | ||
168 | auto, | ||
169 | )); | ||
170 | }; | 154 | }; |
171 | 155 | ||
172 | match first.as_ref() { | 156 | match first.as_ref() { |
@@ -205,3 +189,81 @@ impl Command { | |||
205 | } | 189 | } |
206 | } | 190 | } |
207 | } | 191 | } |
192 | |||
193 | fn parse_add(verb: String, args: Vec<String>, auto: bool) -> Result<Command> { | ||
194 | if args.is_empty() { | ||
195 | return Err(CommandLineError::NotEnoughArgs(verb, 1)); | ||
196 | } | ||
197 | |||
198 | let mut pos = 1; | ||
199 | let mut acc = "".to_owned(); | ||
200 | let mut new_goal: Option<u32> = None; | ||
201 | for s1 in args { | ||
202 | if pos == 1 { | ||
203 | acc.push_str(&s1); | ||
204 | } else { | ||
205 | if let Ok(n) = s1.parse::<u32>() { | ||
206 | new_goal = Some(n); | ||
207 | } else { | ||
208 | acc.push(' '); | ||
209 | acc.push_str(&s1); | ||
210 | } | ||
211 | } | ||
212 | pos = pos + 1; | ||
213 | } | ||
214 | |||
215 | return Ok(Command::Add(acc, new_goal, auto)); | ||
216 | } | ||
217 | |||
218 | #[cfg(test)] | ||
219 | mod tests { | ||
220 | use super::*; | ||
221 | |||
222 | #[test] | ||
223 | fn parse_add_command_with_goal() { | ||
224 | let command: Vec<String> = "eat healthy 3" | ||
225 | .trim() | ||
226 | .split(' ') | ||
227 | .into_iter() | ||
228 | .map(|s| s.to_string()) | ||
229 | .collect(); | ||
230 | |||
231 | let verb = "add".to_owned(); | ||
232 | let auto = false; | ||
233 | |||
234 | let result = parse_add(verb, command, auto); | ||
235 | |||
236 | match result.unwrap() { | ||
237 | Command::Add(name, goal, a) => { | ||
238 | assert_eq!(name, "eat healthy".to_owned()); | ||
239 | assert_eq!(goal.unwrap(), 3); | ||
240 | assert_eq!(a, auto); | ||
241 | } | ||
242 | _ => panic!(), | ||
243 | } | ||
244 | } | ||
245 | |||
246 | #[test] | ||
247 | fn parse_add_command_without_goal() { | ||
248 | let command: Vec<String> = "eat healthy" | ||
249 | .trim() | ||
250 | .split(' ') | ||
251 | .into_iter() | ||
252 | .map(|s| s.to_string()) | ||
253 | .collect(); | ||
254 | |||
255 | let verb = "add".to_owned(); | ||
256 | let auto = false; | ||
257 | |||
258 | let result = parse_add(verb, command, auto); | ||
259 | |||
260 | match result.unwrap() { | ||
261 | Command::Add(name, goal, a) => { | ||
262 | assert_eq!(name, "eat healthy".to_owned()); | ||
263 | assert!(goal.is_none()); | ||
264 | assert_eq!(a, auto); | ||
265 | } | ||
266 | _ => panic!(), | ||
267 | } | ||
268 | } | ||
269 | } | ||