summaryrefslogtreecommitdiffstats
path: root/cli
diff options
context:
space:
mode:
authorGustav Sörnäs <gustav@sornas.net>2021-08-03 15:13:33 +0200
committerGustav Sörnäs <gustav@sornas.net>2021-08-03 15:13:43 +0200
commitb3da8ba67c91deef80054d2b4c34ddec7120ba7a (patch)
tree8561477bbb9f2df7c652ee496e8e7b61849b79b1 /cli
parentfc223fa9b39020306dffd93137a345af6f9b72b2 (diff)
downloadmoney-b3da8ba67c91deef80054d2b4c34ddec7120ba7a.tar.gz
parse amount comparison
Diffstat (limited to 'cli')
-rw-r--r--cli/src/search.rs79
1 files changed, 40 insertions, 39 deletions
diff --git a/cli/src/search.rs b/cli/src/search.rs
index eaf1d06..6692b00 100644
--- a/cli/src/search.rs
+++ b/cli/src/search.rs
@@ -5,6 +5,7 @@ use nom::character::complete::{alphanumeric1, anychar, char, digit1};
use nom::combinator::{map, map_res, recognize};
use nom::sequence::{delimited, pair, preceded};
use rust_decimal::Decimal;
+use std::convert::TryFrom;
use std::str::FromStr;
use crate::transaction::{Category, Transaction};
@@ -67,22 +68,40 @@ pub enum Comparison {
LessOrEqual,
}
-fn parse_comparison(s: &str) -> Option<(Decimal, Comparison)> {
- if s.starts_with(">=") {
- Some((Decimal::from_str(&s[2..]).ok()?, Comparison::GreaterOrEqual))
- } else if s.starts_with("<=") {
- Some((Decimal::from_str(&s[2..]).ok()?, Comparison::LessOrEqual))
- } else if s.starts_with("=") {
- Some((Decimal::from_str(&s[1..]).ok()?, Comparison::Equal))
- } else if s.starts_with(">") {
- Some((Decimal::from_str(&s[1..]).ok()?, Comparison::Greater))
- } else if s.starts_with("<") {
- Some((Decimal::from_str(&s[1..]).ok()?, Comparison::Less))
- } else {
- None
+impl TryFrom<&str> for Comparison {
+ type Error = ();
+
+ fn try_from(s: &str) -> Result<Self, Self::Error> {
+ match s {
+ "=" | "==" => Ok(Comparison::Equal),
+ ">" => Ok(Comparison::Greater),
+ ">=" => Ok(Comparison::GreaterOrEqual),
+ "<" => Ok(Comparison::Less),
+ "<=" => Ok(Comparison::LessOrEqual),
+ _ => Err(()),
+ }
}
}
+fn parse_comparison(i: &str) -> nom::IResult<&str, (Decimal, Comparison)> {
+ let (i, comparison) = map(
+ alt((
+ tag("="),
+ tag("=="),
+ tag(">"),
+ tag(">="),
+ tag("<"),
+ tag("<="),
+ )),
+ |comparison| Comparison::try_from(comparison).unwrap()
+ )(i)?;
+ let (i, amount) = map_res(
+ digit1,
+ Decimal::from_str
+ )(i)?;
+ Ok((i, (amount, comparison)))
+}
+
#[derive(Clone)]
#[derive(Debug)]
pub enum Constraint {
@@ -151,6 +170,13 @@ impl Constraint {
),
Constraint::On
),
+ map(
+ preceded(
+ tag("amount:"),
+ parse_comparison,
+ ),
+ |(amount, comparison)| Constraint::AmountCompare(amount, comparison)
+ )
))(i)
}
}
@@ -253,32 +279,7 @@ impl<'t> Search<'t> {
}
pub fn parse(mut self, rules: String) -> Self {
- for rule in rules.split(' ') {
- let (filter, rule): (fn(Constraint) -> Filter, &str) = match rule.chars().nth(0).unwrap() {
- '-' => (Filter::Subtract, &rule[1..]),
- '+' => (Filter::Union, &rule[1..]),
- _ => (Filter::Intersect, &rule[..]),
- };
-
- //TODO lexing? can do a function for "spaces inside" instead
-
- //TODO category:"foo bar"
-
- let constraint = match rule.split_once(':').unwrap() {
- // ("category", category) => Constraint::Category(category.to_string()),
- // ("before", date_ish) => Constraint::Before(DateIsh::parse(date_ish)),
- // ("after", date_ish) => Constraint::After(DateIsh::parse(date_ish)),
- // ("on", date_ish) => Constraint::On(DateIsh::parse(date_ish)),
- ("amount", comparison) => {
- let (amount, comparison) = parse_comparison(comparison).unwrap();
- Constraint::AmountCompare(amount, comparison)
- }
- _ => panic!(),
- };
-
- self = self.apply(filter(constraint));
- }
- self
+ todo!()
}
}