Refactor CLI argument parsing
This commit is contained in:
parent
4a46e70a73
commit
2f6911eeca
5 changed files with 112 additions and 45 deletions
|
|
@ -8,35 +8,83 @@ use super::commands::Delta;
|
|||
use super::parse::{self, Error, Result, Rule, TodayfileParser};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RangeDate {
|
||||
pub enum CliDatum {
|
||||
Date(NaiveDate),
|
||||
Today,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Range {
|
||||
pub start: RangeDate,
|
||||
pub start_delta: Option<Delta>,
|
||||
pub end: Option<RangeDate>,
|
||||
pub end_delta: Option<Delta>,
|
||||
}
|
||||
|
||||
/* Parsing */
|
||||
|
||||
fn parse_range_date(p: Pair<'_, Rule>) -> Result<RangeDate> {
|
||||
assert!(matches!(p.as_rule(), Rule::datum | Rule::today));
|
||||
fn parse_cli_datum(p: Pair<'_, Rule>) -> Result<CliDatum> {
|
||||
assert_eq!(p.as_rule(), Rule::cli_datum);
|
||||
let p = p.into_inner().next().unwrap();
|
||||
Ok(match p.as_rule() {
|
||||
Rule::datum => RangeDate::Date(parse::parse_datum(p)?.value),
|
||||
Rule::today => RangeDate::Today,
|
||||
Rule::datum => CliDatum::Date(parse::parse_datum(p)?.value),
|
||||
Rule::today => CliDatum::Today,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_range_start(p: Pair<'_, Rule>) -> Result<(RangeDate, Option<Delta>)> {
|
||||
assert_eq!(p.as_rule(), Rule::range_start);
|
||||
#[derive(Debug)]
|
||||
pub struct CliDate {
|
||||
pub datum: CliDatum,
|
||||
pub delta: Option<Delta>,
|
||||
}
|
||||
|
||||
fn parse_cli_date(p: Pair<'_, Rule>) -> Result<CliDate> {
|
||||
assert_eq!(p.as_rule(), Rule::cli_date);
|
||||
let mut p = p.into_inner();
|
||||
|
||||
let start = parse_range_date(p.next().unwrap())?;
|
||||
let datum = parse_cli_datum(p.next().unwrap())?;
|
||||
let delta = match p.next() {
|
||||
Some(p) => Some(parse::parse_delta(p)?.value),
|
||||
None => None,
|
||||
};
|
||||
|
||||
assert_eq!(p.next(), None);
|
||||
|
||||
Ok(CliDate { datum, delta })
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CliIdent {
|
||||
Number(usize),
|
||||
Date(CliDate),
|
||||
}
|
||||
|
||||
fn parse_cli_ident(p: Pair<'_, Rule>) -> Result<CliIdent> {
|
||||
assert_eq!(p.as_rule(), Rule::cli_ident);
|
||||
let p = p.into_inner().next().unwrap();
|
||||
Ok(match p.as_rule() {
|
||||
Rule::number => CliIdent::Number(parse::parse_number(p) as usize),
|
||||
Rule::cli_date => CliIdent::Date(parse_cli_date(p)?),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
impl FromStr for CliIdent {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
let mut pairs = TodayfileParser::parse(Rule::cli_ident, s)?;
|
||||
let p = pairs.next().unwrap();
|
||||
assert_eq!(pairs.next(), None);
|
||||
|
||||
parse_cli_ident(p)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CliRange {
|
||||
pub start: CliDatum,
|
||||
pub start_delta: Option<Delta>,
|
||||
pub end: Option<CliDatum>,
|
||||
pub end_delta: Option<Delta>,
|
||||
}
|
||||
|
||||
fn parse_cli_range_start(p: Pair<'_, Rule>) -> Result<(CliDatum, Option<Delta>)> {
|
||||
assert_eq!(p.as_rule(), Rule::cli_range_start);
|
||||
let mut p = p.into_inner();
|
||||
|
||||
let start = parse_cli_datum(p.next().unwrap())?;
|
||||
let start_delta = match p.next() {
|
||||
None => None,
|
||||
Some(p) => Some(parse::parse_delta(p)?.value),
|
||||
|
|
@ -47,15 +95,15 @@ fn parse_range_start(p: Pair<'_, Rule>) -> Result<(RangeDate, Option<Delta>)> {
|
|||
Ok((start, start_delta))
|
||||
}
|
||||
|
||||
fn parse_range_end(p: Pair<'_, Rule>) -> Result<(Option<RangeDate>, Option<Delta>)> {
|
||||
assert_eq!(p.as_rule(), Rule::range_end);
|
||||
fn parse_cli_range_end(p: Pair<'_, Rule>) -> Result<(Option<CliDatum>, Option<Delta>)> {
|
||||
assert_eq!(p.as_rule(), Rule::cli_range_end);
|
||||
|
||||
let mut end = None;
|
||||
let mut end_delta = None;
|
||||
|
||||
for p in p.into_inner() {
|
||||
match p.as_rule() {
|
||||
Rule::datum | Rule::today => end = Some(parse_range_date(p)?),
|
||||
Rule::cli_datum => end = Some(parse_cli_datum(p)?),
|
||||
Rule::delta => end_delta = Some(parse::parse_delta(p)?.value),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
@ -64,18 +112,18 @@ fn parse_range_end(p: Pair<'_, Rule>) -> Result<(Option<RangeDate>, Option<Delta
|
|||
Ok((end, end_delta))
|
||||
}
|
||||
|
||||
fn parse_range(p: Pair<'_, Rule>) -> Result<Range> {
|
||||
assert_eq!(p.as_rule(), Rule::range);
|
||||
fn parse_cli_range(p: Pair<'_, Rule>) -> Result<CliRange> {
|
||||
assert_eq!(p.as_rule(), Rule::cli_range);
|
||||
let mut p = p.into_inner();
|
||||
|
||||
let (start, start_delta) = parse_range_start(p.next().unwrap())?;
|
||||
let (start, start_delta) = parse_cli_range_start(p.next().unwrap())?;
|
||||
let (end, end_delta) = match p.next() {
|
||||
// For some reason, the EOI gets captured but the SOI doesn't.
|
||||
Some(p) if p.as_rule() != Rule::EOI => parse_range_end(p)?,
|
||||
Some(p) if p.as_rule() != Rule::EOI => parse_cli_range_end(p)?,
|
||||
_ => (None, None),
|
||||
};
|
||||
|
||||
Ok(Range {
|
||||
Ok(CliRange {
|
||||
start,
|
||||
start_delta,
|
||||
end,
|
||||
|
|
@ -83,14 +131,14 @@ fn parse_range(p: Pair<'_, Rule>) -> Result<Range> {
|
|||
})
|
||||
}
|
||||
|
||||
impl FromStr for Range {
|
||||
impl FromStr for CliRange {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
let mut pairs = TodayfileParser::parse(Rule::range, s)?;
|
||||
let mut pairs = TodayfileParser::parse(Rule::cli_range, s)?;
|
||||
let p = pairs.next().unwrap();
|
||||
assert_eq!(pairs.next(), None);
|
||||
|
||||
parse_range(p)
|
||||
parse_cli_range(p)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue