aboutsummaryrefslogtreecommitdiff
path: root/src/command.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/command.rs')
-rw-r--r--src/command.rs51
1 files changed, 43 insertions, 8 deletions
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 @@
1use std::fmt; 1use std::fmt;
2use std::str::FromStr;
2 3
3use cursive::event::{Event, EventResult, Key}; 4use cursive::event::{Event, EventResult, Key};
4use cursive::theme::{BaseColor, Color, ColorStyle}; 5use cursive::theme::{BaseColor, Color, ColorStyle};
@@ -105,9 +106,47 @@ fn call_on_app(s: &mut Cursive, input: &str) {
105 } 106 }
106} 107}
107 108
109#[derive(Debug, PartialEq)]
110pub enum GoalKind {
111 Count(u32),
112 Bit,
113 Float(u32, u8),
114 Addiction(u32),
115}
116
117impl FromStr for GoalKind {
118 type Err = CommandLineError;
119
120 fn from_str(s: &str) -> Result<Self> {
121 if let Some(n) = s.strip_prefix("<") {
122 return n
123 .parse::<u32>()
124 .map_err(|_| CommandLineError::InvalidGoal(s.into()))
125 .map(GoalKind::Addiction);
126 } else if s.contains(".") {
127 let value = s
128 .chars()
129 .filter(|x| x.is_digit(10))
130 .collect::<String>()
131 .parse::<u32>()
132 .map_err(|_| CommandLineError::InvalidCommand(s.into()))?;
133 let precision = s.chars().skip_while(|&x| x != '.').count() - 1;
134 return Ok(GoalKind::Float(value, precision as u8));
135 }
136 if let Ok(v) = s.parse::<u32>() {
137 if v == 1 {
138 return Ok(GoalKind::Bit);
139 } else {
140 return Ok(GoalKind::Count(v));
141 }
142 }
143 return Err(CommandLineError::InvalidCommand(s.into()));
144 }
145}
146
108#[derive(PartialEq)] 147#[derive(PartialEq)]
109pub enum Command { 148pub enum Command {
110 Add(String, Option<u32>, bool), 149 Add(String, Option<GoalKind>, bool),
111 MonthPrev, 150 MonthPrev,
112 MonthNext, 151 MonthNext,
113 Delete(String), 152 Delete(String),
@@ -125,6 +164,7 @@ pub enum CommandLineError {
125 InvalidCommand(String), // command name 164 InvalidCommand(String), // command name
126 InvalidArg(u32), // position 165 InvalidArg(u32), // position
127 NotEnoughArgs(String, u32), // command name, required no. of args 166 NotEnoughArgs(String, u32), // command name, required no. of args
167 InvalidGoal(String), // goal expression
128} 168}
129 169
130impl std::error::Error for CommandLineError {} 170impl std::error::Error for CommandLineError {}
@@ -137,6 +177,7 @@ impl fmt::Display for CommandLineError {
137 CommandLineError::NotEnoughArgs(s, n) => { 177 CommandLineError::NotEnoughArgs(s, n) => {
138 write!(f, "Command `{}` requires atleast {} argument(s)!", s, n) 178 write!(f, "Command `{}` requires atleast {} argument(s)!", s, n)
139 } 179 }
180 CommandLineError::InvalidGoal(s) => write!(f, "Invalid goal expression: `{}`", s),
140 } 181 }
141 } 182 }
142} 183}
@@ -156,13 +197,7 @@ impl Command {
156 if args.is_empty() { 197 if args.is_empty() {
157 return Err(CommandLineError::NotEnoughArgs(first, 1)); 198 return Err(CommandLineError::NotEnoughArgs(first, 1));
158 } 199 }
159 let goal = args 200 let goal = args.get(1).map(|x| GoalKind::from_str(x)).transpose()?;
160 .get(1)
161 .map(|x| {
162 x.parse::<u32>()
163 .map_err(|_| CommandLineError::InvalidArg(2))
164 })
165 .transpose()?;
166 return Ok(Command::Add( 201 return Ok(Command::Add(
167 args.get_mut(0).unwrap().to_string(), 202 args.get_mut(0).unwrap().to_string(),
168 goal, 203 goal,