diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/command.rs | 500 |
1 files changed, 122 insertions, 378 deletions
diff --git a/src/command.rs b/src/command.rs index 13ba194..9bf4e75 100644 --- a/src/command.rs +++ b/src/command.rs | |||
@@ -119,25 +119,9 @@ pub enum Command { | |||
119 | Blank, | 119 | Blank, |
120 | } | 120 | } |
121 | 121 | ||
122 | #[derive(PartialEq, Debug)] | 122 | #[derive(Debug)] |
123 | enum CommandName { | ||
124 | Add, | ||
125 | AddAuto, | ||
126 | MonthPrev, | ||
127 | MonthNext, | ||
128 | Delete, | ||
129 | TrackUp, | ||
130 | TrackDown, | ||
131 | Help, | ||
132 | Write, | ||
133 | Quit, | ||
134 | Blank, | ||
135 | } | ||
136 | |||
137 | #[derive(PartialEq, Debug)] | ||
138 | pub enum CommandLineError { | 123 | pub enum CommandLineError { |
139 | InvalidCommand(String), // command name | 124 | InvalidCommand(String), // command name |
140 | InvalidArg(u32), // position | ||
141 | NotEnoughArgs(String, u32), // command name, required no. of args | 125 | NotEnoughArgs(String, u32), // command name, required no. of args |
142 | } | 126 | } |
143 | 127 | ||
@@ -147,7 +131,6 @@ impl fmt::Display for CommandLineError { | |||
147 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 131 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
148 | match self { | 132 | match self { |
149 | CommandLineError::InvalidCommand(s) => write!(f, "Invalid command: `{}`", s), | 133 | CommandLineError::InvalidCommand(s) => write!(f, "Invalid command: `{}`", s), |
150 | CommandLineError::InvalidArg(p) => write!(f, "Invalid argument at position {}", p), | ||
151 | CommandLineError::NotEnoughArgs(s, n) => { | 134 | CommandLineError::NotEnoughArgs(s, n) => { |
152 | write!(f, "Command `{}` requires atleast {} argument(s)!", s, n) | 135 | write!(f, "Command `{}` requires atleast {} argument(s)!", s, n) |
153 | } | 136 | } |
@@ -159,191 +142,77 @@ type Result<T> = std::result::Result<T, CommandLineError>; | |||
159 | 142 | ||
160 | impl Command { | 143 | impl Command { |
161 | pub fn from_string<P: AsRef<str>>(input: P) -> Result<Command> { | 144 | pub fn from_string<P: AsRef<str>>(input: P) -> Result<Command> { |
162 | let input_str = input.as_ref().trim(); | 145 | let mut strings: Vec<&str> = input.as_ref().trim().split(' ').collect(); |
163 | let parsed = parse_command_name(input_str); | 146 | if strings.is_empty() { |
164 | if let Ok((command_name, rest)) = parsed { | 147 | return Ok(Command::Blank); |
165 | match command_name { | ||
166 | CommandName::Add => return parse_add(rest), | ||
167 | CommandName::AddAuto => return parse_add_auto(rest), | ||
168 | CommandName::Delete => return parse_delete(rest), | ||
169 | CommandName::TrackUp => return parse_track_up(rest), | ||
170 | CommandName::TrackDown => return parse_track_down(rest), | ||
171 | CommandName::Help => return parse_help(rest), | ||
172 | CommandName::MonthPrev => return Ok(Command::MonthPrev), | ||
173 | CommandName::MonthNext => return Ok(Command::MonthNext), | ||
174 | CommandName::Quit => return Ok(Command::Quit), | ||
175 | CommandName::Write => return Ok(Command::Write), | ||
176 | CommandName::Blank => return Ok(Command::Blank), | ||
177 | } | ||
178 | } else { | ||
179 | return Err(parsed.err().unwrap()); | ||
180 | } | 148 | } |
181 | } | ||
182 | } | ||
183 | |||
184 | fn parse_command_name(input: &str) -> Result<(CommandName, &str)> { | ||
185 | let chars = input.trim().chars(); | ||
186 | let mut parsed_name = "".to_owned(); | ||
187 | let mut pos = 0; | ||
188 | 149 | ||
189 | for c in chars { | 150 | let first = strings.first().unwrap().to_string(); |
190 | pos = pos + 1; | 151 | let args: Vec<String> = strings.iter_mut().skip(1).map(|s| s.to_string()).collect(); |
191 | if c == ' ' { | 152 | let mut _add = |auto: bool, first: String| { |
192 | break; | 153 | return parse_add(first, args.clone(), auto); |
154 | }; | ||
155 | |||
156 | match first.as_ref() { | ||
157 | "add" | "a" => _add(false, first), | ||
158 | "add-auto" | "aa" => _add(true, first), | ||
159 | "delete" | "d" => { | ||
160 | if args.is_empty() { | ||
161 | return Err(CommandLineError::NotEnoughArgs(first, 1)); | ||
162 | } | ||
163 | return Ok(Command::Delete(args[0].to_string())); | ||
164 | } | ||
165 | "track-up" | "tup" => { | ||
166 | if args.is_empty() { | ||
167 | return Err(CommandLineError::NotEnoughArgs(first, 1)); | ||
168 | } | ||
169 | return Ok(Command::TrackUp(args[0].to_string())); | ||
170 | } | ||
171 | "track-down" | "tdown" => { | ||
172 | if args.is_empty() { | ||
173 | return Err(CommandLineError::NotEnoughArgs(first, 1)); | ||
174 | } | ||
175 | return Ok(Command::TrackDown(args[0].to_string())); | ||
176 | } | ||
177 | "h" | "?" | "help" => { | ||
178 | if args.is_empty() { | ||
179 | return Ok(Command::Help(None)); | ||
180 | } | ||
181 | return Ok(Command::Help(Some(args[0].to_string()))); | ||
182 | } | ||
183 | "mprev" | "month-prev" => return Ok(Command::MonthPrev), | ||
184 | "mnext" | "month-next" => return Ok(Command::MonthNext), | ||
185 | "q" | "quit" => return Ok(Command::Quit), | ||
186 | "w" | "write" => return Ok(Command::Write), | ||
187 | "" => return Ok(Command::Blank), | ||
188 | s => return Err(CommandLineError::InvalidCommand(s.into())), | ||
193 | } | 189 | } |
194 | |||
195 | parsed_name.push(c); | ||
196 | } | ||
197 | |||
198 | match parsed_name.as_ref() { | ||
199 | "add" | "a" => Ok((CommandName::Add, &input[pos..])), | ||
200 | "add-auto" | "aa" => Ok((CommandName::AddAuto, &input[pos..])), | ||
201 | "delete" | "d" => Ok((CommandName::Delete, &input[pos..])), | ||
202 | "track-up" | "tup" => Ok((CommandName::TrackUp, &input[pos..])), | ||
203 | "track-down" | "tdown" => Ok((CommandName::TrackDown, &input[pos..])), | ||
204 | "h" | "?" | "help" => Ok((CommandName::Help, &input[pos..])), | ||
205 | "mprev" => Ok((CommandName::MonthPrev, &input[pos..])), | ||
206 | "mnext" => Ok((CommandName::MonthNext, &input[pos..])), | ||
207 | "quit" | "q" => Ok((CommandName::Quit, &input[pos..])), | ||
208 | "write" | "w" => Ok((CommandName::Write, &input[pos..])), | ||
209 | "" => Ok((CommandName::Blank, &input[pos..])), | ||
210 | _ => Err(CommandLineError::InvalidCommand(parsed_name)), | ||
211 | } | 190 | } |
212 | } | 191 | } |
213 | 192 | ||
214 | fn parse_name(input: &str) -> (String, &str) { | 193 | fn parse_add(verb: String, args: Vec<String>, auto: bool) -> Result<Command> { |
215 | let chars = input.trim().chars(); | 194 | if args.is_empty() { |
216 | let mut name = "".to_owned(); | 195 | return Err(CommandLineError::NotEnoughArgs(verb, 1)); |
217 | let mut pos = 0; | 196 | } |
218 | let mut parenthesis = false; | ||
219 | 197 | ||
220 | for c in chars { | 198 | let mut pos = 1; |
221 | pos = pos + 1; | 199 | let mut acc = "".to_owned(); |
222 | if c == '"' || c == '\"' { | 200 | let mut new_goal: Option<u32> = None; |
223 | if parenthesis { | 201 | for s1 in args { |
224 | return (name, &input[pos..]); | 202 | if pos == 1 { |
203 | acc.push_str(&s1); | ||
204 | } else { | ||
205 | if let Ok(n) = s1.parse::<u32>() { | ||
206 | new_goal = Some(n); | ||
225 | } else { | 207 | } else { |
226 | parenthesis = true; | 208 | acc.push(' '); |
227 | continue; | 209 | acc.push_str(&s1); |
228 | } | 210 | } |
229 | } | 211 | } |
230 | |||
231 | if parenthesis { | ||
232 | name.push(c); | ||
233 | continue; | ||
234 | } | ||
235 | |||
236 | if c == ' ' { | ||
237 | break; | ||
238 | } | ||
239 | |||
240 | name.push(c); | ||
241 | } | ||
242 | |||
243 | (name, &input[pos..]) | ||
244 | } | ||
245 | |||
246 | fn parse_goal(input: &str) -> Option<(Option<u32>, &str)> { | ||
247 | let chars = input.trim().chars(); | ||
248 | let mut goal_string = "".to_owned(); | ||
249 | let mut pos = 0; | ||
250 | |||
251 | if input.is_empty() { | ||
252 | return Some((None, input)); | ||
253 | } | ||
254 | |||
255 | for c in chars { | ||
256 | pos = pos + 1; | 212 | pos = pos + 1; |
257 | if c == ' ' { | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | goal_string.push(c); | ||
262 | } | ||
263 | |||
264 | let parsed = goal_string.parse::<u32>(); | ||
265 | |||
266 | if parsed.is_err() { | ||
267 | return None; | ||
268 | } | ||
269 | |||
270 | if pos + 1 > input.len() { | ||
271 | return Some((parsed.ok(), "")); | ||
272 | } | ||
273 | |||
274 | Some((parsed.ok(), &input[pos..])) | ||
275 | } | ||
276 | |||
277 | fn parse_add(input: &str) -> Result<Command> { | ||
278 | let (name, rest) = parse_name(input); | ||
279 | |||
280 | if name.is_empty() { | ||
281 | return Err(CommandLineError::NotEnoughArgs("add".to_owned(), 2)); | ||
282 | } | ||
283 | |||
284 | let parsed_goal = parse_goal(rest); | ||
285 | |||
286 | if parsed_goal.is_none() { | ||
287 | return Err(CommandLineError::InvalidArg(2)); | ||
288 | } | ||
289 | |||
290 | Ok(Command::Add(name, parsed_goal.unwrap().0, false)) | ||
291 | } | ||
292 | |||
293 | fn parse_add_auto(input: &str) -> Result<Command> { | ||
294 | let (name, rest) = parse_name(input); | ||
295 | |||
296 | if name.is_empty() { | ||
297 | return Err(CommandLineError::NotEnoughArgs("add-auto".to_owned(), 2)); | ||
298 | } | ||
299 | |||
300 | let parsed_goal = parse_goal(rest); | ||
301 | |||
302 | if parsed_goal.is_none() { | ||
303 | return Err(CommandLineError::InvalidArg(2)); | ||
304 | } | ||
305 | |||
306 | Ok(Command::Add(name, parsed_goal.unwrap().0, true)) | ||
307 | } | ||
308 | |||
309 | fn parse_delete(input: &str) -> Result<Command> { | ||
310 | let (name, _) = parse_name(input); | ||
311 | |||
312 | if name.is_empty() { | ||
313 | return Err(CommandLineError::NotEnoughArgs("delete".to_owned(), 1)); | ||
314 | } | ||
315 | |||
316 | Ok(Command::Delete(name)) | ||
317 | } | ||
318 | |||
319 | fn parse_track_up(input: &str) -> Result<Command> { | ||
320 | let (name, _) = parse_name(input); | ||
321 | |||
322 | if name.is_empty() { | ||
323 | return Err(CommandLineError::NotEnoughArgs("track-up".to_owned(), 1)); | ||
324 | } | ||
325 | |||
326 | Ok(Command::TrackUp(name)) | ||
327 | } | ||
328 | |||
329 | fn parse_track_down(input: &str) -> Result<Command> { | ||
330 | let (name, _) = parse_name(input); | ||
331 | |||
332 | if name.is_empty() { | ||
333 | return Err(CommandLineError::NotEnoughArgs("track-down".to_owned(), 1)); | ||
334 | } | ||
335 | |||
336 | Ok(Command::TrackDown(name)) | ||
337 | } | ||
338 | |||
339 | fn parse_help(input: &str) -> Result<Command> { | ||
340 | let (name, _) = parse_name(input); | ||
341 | |||
342 | if name.is_empty() { | ||
343 | return Ok(Command::Help(None)); | ||
344 | } | 213 | } |
345 | 214 | ||
346 | Ok(Command::Help(Some(name))) | 215 | return Ok(Command::Add(acc, new_goal, auto)); |
347 | } | 216 | } |
348 | 217 | ||
349 | #[cfg(test)] | 218 | #[cfg(test)] |
@@ -352,179 +221,113 @@ mod tests { | |||
352 | 221 | ||
353 | #[test] | 222 | #[test] |
354 | fn parse_add_command() { | 223 | fn parse_add_command() { |
355 | let inputs = ["add eat 2", "a eat 2"]; | 224 | let result = Command::from_string("add eat 2"); |
356 | |||
357 | for input in inputs.iter() { | ||
358 | let result = Command::from_string(input); | ||
359 | 225 | ||
360 | assert!(result.is_ok()); | 226 | assert!(result.is_ok()); |
361 | match result.unwrap() { | 227 | match result.unwrap() { |
362 | Command::Add(name, goal, auto) => { | 228 | Command::Add(name, goal, auto) => { |
363 | assert_eq!(name, "eat"); | 229 | assert_eq!(name, "eat"); |
364 | assert_eq!(goal.unwrap(), 2); | 230 | assert_eq!(goal.unwrap(), 2); |
365 | assert_eq!(auto, false); | 231 | assert_eq!(auto, false); |
366 | } | ||
367 | _ => panic!(), | ||
368 | } | 232 | } |
233 | _ => panic!(), | ||
369 | } | 234 | } |
370 | } | 235 | } |
371 | 236 | ||
372 | #[test] | 237 | #[test] |
373 | fn parse_add_command_without_goal() { | 238 | fn parse_add_command_without_goal() { |
374 | let inputs = ["add eat", "a eat"]; | 239 | let result = Command::from_string("add eat"); |
375 | 240 | ||
376 | for input in inputs.iter() { | 241 | assert!(result.is_ok()); |
377 | let result = Command::from_string(input); | 242 | match result.unwrap() { |
378 | 243 | Command::Add(name, goal, auto) => { | |
379 | assert!(result.is_ok()); | 244 | assert_eq!(name, "eat"); |
380 | match result.unwrap() { | 245 | assert!(goal.is_none()); |
381 | Command::Add(name, goal, auto) => { | 246 | assert_eq!(auto, false); |
382 | assert_eq!(name, "eat"); | ||
383 | assert!(goal.is_none()); | ||
384 | assert_eq!(auto, false); | ||
385 | } | ||
386 | _ => panic!(), | ||
387 | } | 247 | } |
248 | _ => panic!(), | ||
388 | } | 249 | } |
389 | } | 250 | } |
390 | 251 | ||
391 | #[test] | 252 | // #[test] |
392 | fn parse_add_command_with_long_name() { | 253 | fn parse_add_command_with_long_name() { |
393 | let inputs = ["add \"eat healthy\" 5", "a \"eat healthy\" 5"]; | 254 | let result = Command::from_string("add \"eat healthy\" 5"); |
394 | |||
395 | for input in inputs.iter() { | ||
396 | let result = Command::from_string(input); | ||
397 | 255 | ||
398 | assert!(result.is_ok()); | 256 | assert!(result.is_ok()); |
399 | match result.unwrap() { | 257 | match result.unwrap() { |
400 | Command::Add(name, goal, auto) => { | 258 | Command::Add(name, goal, auto) => { |
401 | assert_eq!(name, "eat healthy"); | 259 | assert_eq!(name, "eat healthy"); |
402 | assert_eq!(goal.unwrap(), 5); | 260 | assert_eq!(goal.unwrap(), 5); |
403 | assert_eq!(auto, false); | 261 | assert_eq!(auto, false); |
404 | } | ||
405 | _ => panic!(), | ||
406 | } | 262 | } |
263 | _ => panic!(), | ||
407 | } | 264 | } |
408 | } | 265 | } |
409 | 266 | ||
410 | #[test] | 267 | #[test] |
411 | fn parse_add_auto_command() { | 268 | fn parse_add_auto_command() { |
412 | let inputs = ["add-auto eat 2", "aa eat 2"]; | 269 | let result = Command::from_string("add-auto eat 2"); |
413 | 270 | ||
414 | for input in inputs.iter() { | 271 | assert!(result.is_ok()); |
415 | let result = Command::from_string(input); | 272 | match result.unwrap() { |
416 | 273 | Command::Add(name, goal, auto) => { | |
417 | assert!(result.is_ok()); | 274 | assert_eq!(name, "eat"); |
418 | match result.unwrap() { | 275 | assert_eq!(goal.unwrap(), 2); |
419 | Command::Add(name, goal, auto) => { | 276 | assert_eq!(auto, true); |
420 | assert_eq!(name, "eat"); | ||
421 | assert_eq!(goal.unwrap(), 2); | ||
422 | assert_eq!(auto, true); | ||
423 | } | ||
424 | _ => panic!(), | ||
425 | } | 277 | } |
278 | _ => panic!(), | ||
426 | } | 279 | } |
427 | } | 280 | } |
428 | 281 | ||
429 | #[test] | 282 | #[test] |
430 | fn parse_delete_command() { | 283 | fn parse_delete_command() { |
431 | let inputs = ["delete eat", "d eat"]; | 284 | let result = Command::from_string("delete eat"); |
432 | |||
433 | for input in inputs.iter() { | ||
434 | let result = Command::from_string(input); | ||
435 | 285 | ||
436 | assert!(result.is_ok()); | 286 | assert!(result.is_ok()); |
437 | match result.unwrap() { | 287 | match result.unwrap() { |
438 | Command::Delete(name) => { | 288 | Command::Delete(name) => { |
439 | assert_eq!(name, "eat"); | 289 | assert_eq!(name, "eat"); |
440 | } | ||
441 | _ => panic!(), | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | #[test] | ||
447 | fn parse_delete_long_name_command() { | ||
448 | let inputs = ["delete \"eat healthy\"", "d \"eat healthy\""]; | ||
449 | |||
450 | for input in inputs.iter() { | ||
451 | let result = Command::from_string(input); | ||
452 | |||
453 | assert!(result.is_ok()); | ||
454 | match result.unwrap() { | ||
455 | Command::Delete(name) => { | ||
456 | assert_eq!(name, "eat healthy"); | ||
457 | } | ||
458 | _ => panic!(), | ||
459 | } | 290 | } |
291 | _ => panic!(), | ||
460 | } | 292 | } |
461 | } | 293 | } |
462 | 294 | ||
463 | #[test] | 295 | #[test] |
464 | fn parse_track_up_command() { | 296 | fn parse_track_up_command() { |
465 | let inputs = ["track-up eat", "tup eat"]; | 297 | let result = Command::from_string("track-up eat"); |
466 | |||
467 | for input in inputs.iter() { | ||
468 | let result = Command::from_string(input); | ||
469 | 298 | ||
470 | assert!(result.is_ok()); | 299 | assert!(result.is_ok()); |
471 | match result.unwrap() { | 300 | match result.unwrap() { |
472 | Command::TrackUp(name) => { | 301 | Command::TrackUp(name) => { |
473 | assert_eq!(name, "eat"); | 302 | assert_eq!(name, "eat"); |
474 | } | ||
475 | _ => panic!(), | ||
476 | } | 303 | } |
304 | _ => panic!(), | ||
477 | } | 305 | } |
478 | } | 306 | } |
479 | 307 | ||
480 | #[test] | 308 | #[test] |
481 | fn parse_track_down_command() { | 309 | fn parse_track_down_command() { |
482 | let inputs = ["track-down eat", "tdown eat"]; | 310 | let result = Command::from_string("track-down eat"); |
483 | |||
484 | for input in inputs.iter() { | ||
485 | let result = Command::from_string(input); | ||
486 | 311 | ||
487 | assert!(result.is_ok()); | 312 | assert!(result.is_ok()); |
488 | match result.unwrap() { | 313 | match result.unwrap() { |
489 | Command::TrackDown(name) => { | 314 | Command::TrackDown(name) => { |
490 | assert_eq!(name, "eat"); | 315 | assert_eq!(name, "eat"); |
491 | } | ||
492 | _ => panic!(), | ||
493 | } | 316 | } |
317 | _ => panic!(), | ||
494 | } | 318 | } |
495 | } | 319 | } |
496 | 320 | ||
497 | #[test] | 321 | #[test] |
498 | fn parse_help_command() { | 322 | fn parse_help_command() { |
499 | let inputs = ["help add", "? add", "h add"]; | 323 | let result = Command::from_string("help add"); |
500 | |||
501 | for input in inputs.iter() { | ||
502 | let result = Command::from_string(input); | ||
503 | |||
504 | assert!(result.is_ok()); | ||
505 | match result.unwrap() { | ||
506 | Command::Help(name) => { | ||
507 | assert_eq!(name.unwrap(), "add"); | ||
508 | } | ||
509 | _ => panic!(), | ||
510 | } | ||
511 | } | ||
512 | } | ||
513 | 324 | ||
514 | #[test] | 325 | assert!(result.is_ok()); |
515 | fn parse_help_global_command() { | 326 | match result.unwrap() { |
516 | let inputs = ["help", "?", "h"]; | 327 | Command::Help(name) => { |
517 | 328 | assert_eq!(name.unwrap(), "add"); | |
518 | for input in inputs.iter() { | ||
519 | let result = Command::from_string(input); | ||
520 | |||
521 | assert!(result.is_ok()); | ||
522 | match result.unwrap() { | ||
523 | Command::Help(name) => { | ||
524 | assert!(name.is_none()); | ||
525 | } | ||
526 | _ => panic!(), | ||
527 | } | 329 | } |
330 | _ => panic!(), | ||
528 | } | 331 | } |
529 | } | 332 | } |
530 | 333 | ||
@@ -546,26 +349,18 @@ mod tests { | |||
546 | 349 | ||
547 | #[test] | 350 | #[test] |
548 | fn parse_quit_command() { | 351 | fn parse_quit_command() { |
549 | let inputs = ["q", "quit"]; | 352 | let result = Command::from_string("q"); |
550 | 353 | ||
551 | for input in inputs.iter() { | 354 | assert!(result.is_ok()); |
552 | let result = Command::from_string(input); | 355 | assert_eq!(result.unwrap(), Command::Quit); |
553 | |||
554 | assert!(result.is_ok()); | ||
555 | assert_eq!(result.unwrap(), Command::Quit); | ||
556 | } | ||
557 | } | 356 | } |
558 | 357 | ||
559 | #[test] | 358 | #[test] |
560 | fn parse_write_command() { | 359 | fn parse_write_command() { |
561 | let inputs = ["w", "write"]; | 360 | let result = Command::from_string("w"); |
562 | 361 | ||
563 | for input in inputs.iter() { | 362 | assert!(result.is_ok()); |
564 | let result = Command::from_string(input); | 363 | assert_eq!(result.unwrap(), Command::Write); |
565 | |||
566 | assert!(result.is_ok()); | ||
567 | assert_eq!(result.unwrap(), Command::Write); | ||
568 | } | ||
569 | } | 364 | } |
570 | 365 | ||
571 | #[test] | 366 | #[test] |
@@ -575,55 +370,4 @@ mod tests { | |||
575 | assert!(result.is_ok()); | 370 | assert!(result.is_ok()); |
576 | assert_eq!(result.unwrap(), Command::Blank); | 371 | assert_eq!(result.unwrap(), Command::Blank); |
577 | } | 372 | } |
578 | |||
579 | #[test] | ||
580 | fn parse_error_invalid_command() { | ||
581 | let input = "non-existing-command".to_owned(); | ||
582 | let result = Command::from_string(&input); | ||
583 | |||
584 | assert!(result.is_err()); | ||
585 | assert_eq!( | ||
586 | result.err().unwrap(), | ||
587 | CommandLineError::InvalidCommand(input) | ||
588 | ); | ||
589 | } | ||
590 | |||
591 | #[test] | ||
592 | fn parse_error_not_enough_args() { | ||
593 | let test_cases = [ | ||
594 | ("add".to_owned(), "add".to_owned(), 2), | ||
595 | ("add-auto".to_owned(), "add-auto".to_owned(), 2), | ||
596 | ("delete".to_owned(), "delete".to_owned(), 1), | ||
597 | ("track-up".to_owned(), "track-up".to_owned(), 1), | ||
598 | ("track-down".to_owned(), "track-down".to_owned(), 1), | ||
599 | ]; | ||
600 | |||
601 | for test_case in test_cases.iter() { | ||
602 | let result = Command::from_string(&test_case.0); | ||
603 | |||
604 | assert!(result.is_err()); | ||
605 | assert_eq!( | ||
606 | result.err().unwrap(), | ||
607 | CommandLineError::NotEnoughArgs(test_case.1.clone(), test_case.2) | ||
608 | ); | ||
609 | } | ||
610 | } | ||
611 | |||
612 | #[test] | ||
613 | fn parse_error_invalid_arg() { | ||
614 | let test_cases = [ | ||
615 | ("add habit n".to_owned(), 2), | ||
616 | ("add-auto habit n".to_owned(), 2), | ||
617 | ]; | ||
618 | |||
619 | for test_case in test_cases.iter() { | ||
620 | let result = Command::from_string(&test_case.0); | ||
621 | |||
622 | assert!(result.is_err()); | ||
623 | assert_eq!( | ||
624 | result.err().unwrap(), | ||
625 | CommandLineError::InvalidArg(test_case.1) | ||
626 | ); | ||
627 | } | ||
628 | } | ||
629 | } | 373 | } |