Parse range for --range
This commit is contained in:
parent
d67bf0aeea
commit
279bf4a4d1
4 changed files with 103 additions and 3 deletions
|
|
@ -8,6 +8,7 @@ use tzfile::Tz;
|
||||||
use self::commands::{Command, Done, File};
|
use self::commands::{Command, Done, File};
|
||||||
pub use self::error::{Error, Result};
|
pub use self::error::{Error, Result};
|
||||||
|
|
||||||
|
pub mod arguments;
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
mod error;
|
mod error;
|
||||||
mod format;
|
mod format;
|
||||||
|
|
|
||||||
94
src/files/arguments.rs
Normal file
94
src/files/arguments.rs
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use chrono::NaiveDate;
|
||||||
|
use pest::iterators::Pair;
|
||||||
|
use pest::Parser;
|
||||||
|
|
||||||
|
use super::commands::Delta;
|
||||||
|
use super::parse::{self, Error, Result, Rule, TodayfileParser};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum RangeDate {
|
||||||
|
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));
|
||||||
|
Ok(match p.as_rule() {
|
||||||
|
Rule::datum => RangeDate::Date(parse::parse_datum(p)?.value),
|
||||||
|
Rule::today => RangeDate::Today,
|
||||||
|
_ => unreachable!(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_range_start(p: Pair<'_, Rule>) -> Result<(RangeDate, Option<Delta>)> {
|
||||||
|
assert_eq!(p.as_rule(), Rule::range_start);
|
||||||
|
let mut p = p.into_inner();
|
||||||
|
|
||||||
|
let start = parse_range_date(p.next().unwrap())?;
|
||||||
|
let start_delta = match p.next() {
|
||||||
|
None => None,
|
||||||
|
Some(p) => Some(parse::parse_delta(p)?.value),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(p.next(), None);
|
||||||
|
|
||||||
|
Ok((start, start_delta))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_range_end(p: Pair<'_, Rule>) -> Result<(Option<RangeDate>, Option<Delta>)> {
|
||||||
|
assert_eq!(p.as_rule(), Rule::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::delta => end_delta = Some(parse::parse_delta(p)?.value),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((end, end_delta))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_range(p: Pair<'_, Rule>) -> Result<Range> {
|
||||||
|
assert_eq!(p.as_rule(), Rule::range);
|
||||||
|
let mut p = p.into_inner();
|
||||||
|
|
||||||
|
let (start, start_delta) = parse_range_start(p.next().unwrap())?;
|
||||||
|
let (end, end_delta) = parse_range_end(p.next().unwrap())?;
|
||||||
|
|
||||||
|
assert_eq!(p.next(), None);
|
||||||
|
|
||||||
|
Ok(Range {
|
||||||
|
start,
|
||||||
|
start_delta,
|
||||||
|
end,
|
||||||
|
end_delta,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Range {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self> {
|
||||||
|
let mut pairs = TodayfileParser::parse(Rule::range, s)?;
|
||||||
|
let p = pairs.next().unwrap();
|
||||||
|
assert_eq!(pairs.next(), None);
|
||||||
|
|
||||||
|
parse_range(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -142,3 +142,8 @@ empty_line = _{ WHITESPACE* ~ NEWLINE }
|
||||||
command = { include | timezone | task | note }
|
command = { include | timezone | task | note }
|
||||||
|
|
||||||
file = ${ SOI ~ (empty_line* ~ command)* ~ empty_line* ~ WHITESPACE* ~ EOI }
|
file = ${ SOI ~ (empty_line* ~ command)* ~ empty_line* ~ WHITESPACE* ~ EOI }
|
||||||
|
|
||||||
|
today = { "today" }
|
||||||
|
range_start = { (datum | today) ~ delta? }
|
||||||
|
range_end = { (datum | today) ~ delta? | delta }
|
||||||
|
range = { range_start ~ ("--" ~ range_end)? }
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use super::primitives::{Spanned, Time, Weekday};
|
||||||
|
|
||||||
#[derive(pest_derive::Parser)]
|
#[derive(pest_derive::Parser)]
|
||||||
#[grammar = "files/grammar.pest"]
|
#[grammar = "files/grammar.pest"]
|
||||||
struct TodayfileParser;
|
pub struct TodayfileParser;
|
||||||
|
|
||||||
pub type Error = pest::error::Error<Rule>;
|
pub type Error = pest::error::Error<Rule>;
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
@ -55,7 +55,7 @@ fn parse_title(p: Pair<'_, Rule>) -> String {
|
||||||
p.as_str().trim().to_string()
|
p.as_str().trim().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_datum(p: Pair<'_, Rule>) -> Result<Spanned<NaiveDate>> {
|
pub fn parse_datum(p: Pair<'_, Rule>) -> Result<Spanned<NaiveDate>> {
|
||||||
assert_eq!(p.as_rule(), Rule::datum);
|
assert_eq!(p.as_rule(), Rule::datum);
|
||||||
let pspan = p.as_span();
|
let pspan = p.as_span();
|
||||||
let span = (&pspan).into();
|
let span = (&pspan).into();
|
||||||
|
|
@ -203,7 +203,7 @@ fn parse_delta_step(
|
||||||
Ok(Spanned::new(span, f(value)))
|
Ok(Spanned::new(span, f(value)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_delta(p: Pair<'_, Rule>) -> Result<Spanned<Delta>> {
|
pub fn parse_delta(p: Pair<'_, Rule>) -> Result<Spanned<Delta>> {
|
||||||
assert_eq!(p.as_rule(), Rule::delta);
|
assert_eq!(p.as_rule(), Rule::delta);
|
||||||
let span = (&p.as_span()).into();
|
let span = (&p.as_span()).into();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue