From fbcc966a3da8a75842c6b8843a9fd7f1edb0db15 Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 24 Feb 2021 11:57:37 +0530 Subject: add GoalKinds - this allows for changing habit goals easily - easier to add new habits to dijo in newer versions --- src/command.rs | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) (limited to 'src/command.rs') diff --git a/src/command.rs b/src/command.rs index 30aabe2..bfd09d8 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::str::FromStr; use cursive::event::{Event, EventResult, Key}; use cursive::theme::{BaseColor, Color, ColorStyle}; @@ -105,9 +106,47 @@ fn call_on_app(s: &mut Cursive, input: &str) { } } +#[derive(Debug, PartialEq)] +pub enum GoalKind { + Count(u32), + Bit, + Float(u32, u8), + Addiction(u32), +} + +impl FromStr for GoalKind { + type Err = CommandLineError; + + fn from_str(s: &str) -> Result { + if let Some(n) = s.strip_prefix("<") { + return n + .parse::() + .map_err(|_| CommandLineError::InvalidGoal(s.into())) + .map(GoalKind::Addiction); + } else if s.contains(".") { + let value = s + .chars() + .filter(|x| x.is_digit(10)) + .collect::() + .parse::() + .map_err(|_| CommandLineError::InvalidCommand(s.into()))?; + let precision = s.chars().skip_while(|&x| x != '.').count() - 1; + return Ok(GoalKind::Float(value, precision as u8)); + } + if let Ok(v) = s.parse::() { + if v == 1 { + return Ok(GoalKind::Bit); + } else { + return Ok(GoalKind::Count(v)); + } + } + return Err(CommandLineError::InvalidCommand(s.into())); + } +} + #[derive(PartialEq)] pub enum Command { - Add(String, Option, bool), + Add(String, Option, bool), MonthPrev, MonthNext, Delete(String), @@ -125,6 +164,7 @@ pub enum CommandLineError { InvalidCommand(String), // command name InvalidArg(u32), // position NotEnoughArgs(String, u32), // command name, required no. of args + InvalidGoal(String), // goal expression } impl std::error::Error for CommandLineError {} @@ -137,6 +177,7 @@ impl fmt::Display for CommandLineError { CommandLineError::NotEnoughArgs(s, n) => { write!(f, "Command `{}` requires atleast {} argument(s)!", s, n) } + CommandLineError::InvalidGoal(s) => write!(f, "Invalid goal expression: `{}`", s), } } } @@ -156,13 +197,7 @@ impl Command { if args.is_empty() { return Err(CommandLineError::NotEnoughArgs(first, 1)); } - let goal = args - .get(1) - .map(|x| { - x.parse::() - .map_err(|_| CommandLineError::InvalidArg(2)) - }) - .transpose()?; + let goal = args.get(1).map(|x| GoalKind::from_str(x)).transpose()?; return Ok(Command::Add( args.get_mut(0).unwrap().to_string(), goal, -- cgit v1.2.3