Change commands to a more statement-driven format
This commit is contained in:
parent
f42027e378
commit
b5ef9e8134
6 changed files with 181 additions and 212 deletions
|
|
@ -58,18 +58,17 @@ DATE 0016-04-09 +dsun; +19y
|
|||
DATE 0017-03-29 +dsun; +19y
|
||||
DATE 0018-04-17 +dsun; +19y
|
||||
|
||||
BIRTHDAY Max
|
||||
NOTE Max
|
||||
BDATE 1987-05-14
|
||||
|
||||
BIRTHDAY Martha
|
||||
NOTE Martha
|
||||
BDATE ?-09-21
|
||||
|
||||
NOTE Physics lecture
|
||||
DATE wed 14:00 -- 15:30
|
||||
DATE 2021-05-07 14:00 -- 15:30
|
||||
FROM 2021-04-14
|
||||
UNTIL 2021-07-28
|
||||
EXCEPT 2021-05-06
|
||||
DATE wed 14:00 -- 15:30
|
||||
MOVE 2021-05-06 TO 2021-05-07
|
||||
# This is a description of the event. It might mention further information that
|
||||
# doesn't fit into the title.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -342,6 +342,22 @@ pub enum Spec {
|
|||
Formula(FormulaSpec),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BirthdaySpec {
|
||||
pub date: NaiveDate,
|
||||
pub year_known: bool, // If year is unknown, use NaiveDate of year 0
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Statement {
|
||||
Date(Spec),
|
||||
BDate(BirthdaySpec),
|
||||
From(Option<NaiveDate>),
|
||||
Until(Option<NaiveDate>),
|
||||
Except(NaiveDate), // TODO Allow excluding ranges
|
||||
Move(NaiveDate, NaiveDate),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum DoneDate {
|
||||
Date {
|
||||
|
|
@ -406,10 +422,7 @@ pub struct Done {
|
|||
#[derive(Debug)]
|
||||
pub struct Task {
|
||||
pub title: String,
|
||||
pub when: Vec<Spec>,
|
||||
pub from: Option<NaiveDate>,
|
||||
pub until: Option<NaiveDate>,
|
||||
pub except: Vec<NaiveDate>,
|
||||
pub statements: Vec<Statement>,
|
||||
pub done: Vec<Done>,
|
||||
pub desc: Vec<String>,
|
||||
}
|
||||
|
|
@ -417,24 +430,7 @@ pub struct Task {
|
|||
#[derive(Debug)]
|
||||
pub struct Note {
|
||||
pub title: String,
|
||||
pub when: Vec<Spec>, // Should not be empty?
|
||||
pub from: Option<NaiveDate>,
|
||||
pub until: Option<NaiveDate>,
|
||||
pub except: Vec<NaiveDate>,
|
||||
pub desc: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BirthdaySpec {
|
||||
pub date: NaiveDate,
|
||||
pub year_known: bool, // If year is unknown, use NaiveDate of year 0
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Birthday {
|
||||
pub title: String,
|
||||
pub when: BirthdaySpec,
|
||||
// pub until: Option<NaiveDate>, // TODO Add UNTIL to birthday
|
||||
pub statements: Vec<Statement>,
|
||||
pub desc: Vec<String>,
|
||||
}
|
||||
|
||||
|
|
@ -442,7 +438,6 @@ pub struct Birthday {
|
|||
pub enum Command {
|
||||
Task(Task),
|
||||
Note(Note),
|
||||
Birthday(Birthday),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use std::fmt;
|
|||
use chrono::Datelike;
|
||||
|
||||
use super::commands::{
|
||||
Birthday, BirthdaySpec, Command, DateSpec, Delta, DeltaStep, Done, DoneDate, Expr, File,
|
||||
FormulaSpec, Note, Repeat, Spanned, Spec, Task, Time, Var, Weekday, WeekdaySpec,
|
||||
BirthdaySpec, Command, DateSpec, Delta, DeltaStep, Done, DoneDate, Expr, File, FormulaSpec,
|
||||
Note, Repeat, Spanned, Spec, Statement, Task, Time, Var, Weekday, WeekdaySpec,
|
||||
};
|
||||
|
||||
impl<T: fmt::Display> fmt::Display for Spanned<T> {
|
||||
|
|
@ -191,13 +191,36 @@ impl fmt::Display for FormulaSpec {
|
|||
|
||||
impl fmt::Display for Spec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "DATE ")?;
|
||||
match self {
|
||||
Spec::Date(spec) => write!(f, "{}", spec)?,
|
||||
Spec::Weekday(spec) => write!(f, "{}", spec)?,
|
||||
Spec::Formula(spec) => write!(f, "{}", spec)?,
|
||||
Spec::Date(spec) => write!(f, "{}", spec),
|
||||
Spec::Weekday(spec) => write!(f, "{}", spec),
|
||||
Spec::Formula(spec) => write!(f, "{}", spec),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BirthdaySpec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.year_known {
|
||||
write!(f, "{}", self.date)
|
||||
} else {
|
||||
write!(f, "?-{:02}-{:02}", self.date.month(), self.date.day())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Statement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Statement::Date(spec) => writeln!(f, "DATE {}", spec),
|
||||
Statement::BDate(spec) => writeln!(f, "BDATE {}", spec),
|
||||
Statement::From(Some(date)) => writeln!(f, "FROM {}", date),
|
||||
Statement::From(None) => writeln!(f, "FROM *"),
|
||||
Statement::Until(Some(date)) => writeln!(f, "UNTIL {}", date),
|
||||
Statement::Until(None) => writeln!(f, "UNTIL *"),
|
||||
Statement::Except(date) => writeln!(f, "EXCEPT {}", date),
|
||||
Statement::Move(from, to) => writeln!(f, "MOVE {} TO {}", from, to),
|
||||
}
|
||||
writeln!(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -230,17 +253,8 @@ impl fmt::Display for Done {
|
|||
impl fmt::Display for Task {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "TASK {}", self.title)?;
|
||||
for spec in &self.when {
|
||||
write!(f, "{}", spec)?;
|
||||
}
|
||||
if let Some(date) = self.from {
|
||||
writeln!(f, "FROM {}", date)?;
|
||||
}
|
||||
if let Some(date) = self.until {
|
||||
writeln!(f, "UNTIL {}", date)?;
|
||||
}
|
||||
for date in &self.except {
|
||||
writeln!(f, "EXCEPT {}", date)?;
|
||||
for statement in &self.statements {
|
||||
write!(f, "{}", statement)?;
|
||||
}
|
||||
for done in &self.done {
|
||||
write!(f, "{}", done)?;
|
||||
|
|
@ -253,37 +267,9 @@ impl fmt::Display for Task {
|
|||
impl fmt::Display for Note {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "NOTE {}", self.title)?;
|
||||
for spec in &self.when {
|
||||
write!(f, "{}", spec)?;
|
||||
for statement in &self.statements {
|
||||
write!(f, "{}", statement)?;
|
||||
}
|
||||
if let Some(date) = self.from {
|
||||
writeln!(f, "FROM {}", date)?;
|
||||
}
|
||||
if let Some(date) = self.until {
|
||||
writeln!(f, "UNTIL {}", date)?;
|
||||
}
|
||||
for date in &self.except {
|
||||
writeln!(f, "EXCEPT {}", date)?;
|
||||
}
|
||||
format_desc(f, &self.desc)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BirthdaySpec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.year_known {
|
||||
writeln!(f, "BDATE {}", self.date)
|
||||
} else {
|
||||
writeln!(f, "BDATE ?-{:02}-{:02}", self.date.month(), self.date.day())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Birthday {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "BIRTHDAY {}", self.title)?;
|
||||
write!(f, "{}", self.when)?;
|
||||
format_desc(f, &self.desc)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -294,7 +280,6 @@ impl fmt::Display for Command {
|
|||
match self {
|
||||
Command::Task(task) => write!(f, "{}", task),
|
||||
Command::Note(note) => write!(f, "{}", note),
|
||||
Command::Birthday(birthday) => write!(f, "{}", birthday),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,12 +101,14 @@ date_weekday_start = { weekday ~ time? }
|
|||
date_weekday_end = { weekday ~ time? | delta ~ time? | time }
|
||||
date_weekday = { date_weekday_start ~ ("--" ~ date_weekday_end)? }
|
||||
|
||||
date = !{ "DATE" ~ (date_fixed | date_expr | date_weekday) ~ eol }
|
||||
stmt_date = !{ "DATE" ~ (date_fixed | date_expr | date_weekday) ~ eol }
|
||||
stmt_bdate = !{ "BDATE" ~ bdatum ~ eol }
|
||||
stmt_from = !{ "FROM" ~ (datum | "*") ~ eol }
|
||||
stmt_until = !{ "UNTIL" ~ (datum | "*") ~ eol }
|
||||
stmt_except = !{ "EXCEPT" ~ datum ~ eol }
|
||||
stmt_move = !{ "MOVE" ~ datum ~ "TO" ~ datum ~ eol }
|
||||
|
||||
bdate = !{ "BDATE" ~ bdatum ~ eol }
|
||||
from = !{ "FROM" ~ datum ~ eol }
|
||||
until = !{ "UNTIL" ~ datum ~ eol }
|
||||
except = !{ "EXCEPT" ~ datum ~ eol }
|
||||
statements = { (stmt_date | stmt_bdate | stmt_from | stmt_until | stmt_except | stmt_move)* }
|
||||
|
||||
donedate = {
|
||||
datum ~ time ~ "--" ~ datum ~ time
|
||||
|
|
@ -115,36 +117,27 @@ donedate = {
|
|||
| datum
|
||||
}
|
||||
done = !{ "DONE" ~ "[" ~ datum ~ "]" ~ donedate? ~ eol }
|
||||
dones = { done* }
|
||||
|
||||
desc_line = { "#" ~ (" " ~ rest_any)? ~ eol }
|
||||
description = { desc_line* }
|
||||
|
||||
task_options = { (date | from | until | except | done)* }
|
||||
|
||||
task = {
|
||||
"TASK"
|
||||
~ title
|
||||
~ task_options
|
||||
~ statements
|
||||
~ dones
|
||||
~ description
|
||||
}
|
||||
|
||||
note_options = { (date | from | until | except)* }
|
||||
|
||||
note = {
|
||||
"NOTE"
|
||||
~ title
|
||||
~ note_options
|
||||
~ description
|
||||
}
|
||||
|
||||
birthday = {
|
||||
"BIRTHDAY"
|
||||
~ title
|
||||
~ bdate
|
||||
~ statements
|
||||
~ description
|
||||
}
|
||||
|
||||
empty_line = _{ WHITESPACE* ~ NEWLINE }
|
||||
command = { include | timezone | task | note | birthday }
|
||||
command = { include | timezone | task | note }
|
||||
|
||||
file = ${ SOI ~ (empty_line* ~ command)* ~ empty_line* ~ WHITESPACE* ~ EOI }
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use pest::{Parser, Span};
|
|||
use crate::files::commands::{Repeat, Spanned};
|
||||
|
||||
use super::commands::{
|
||||
Birthday, BirthdaySpec, Command, DateSpec, Delta, DeltaStep, Done, DoneDate, Expr, File,
|
||||
FormulaSpec, Note, Spec, Task, Time, Var, Weekday, WeekdaySpec,
|
||||
BirthdaySpec, Command, DateSpec, Delta, DeltaStep, Done, DoneDate, Expr, File, FormulaSpec,
|
||||
Note, Spec, Statement, Task, Time, Var, Weekday, WeekdaySpec,
|
||||
};
|
||||
|
||||
#[derive(pest_derive::Parser)]
|
||||
|
|
@ -532,33 +532,101 @@ fn parse_date_weekday(p: Pair<'_, Rule>) -> Result<WeekdaySpec> {
|
|||
Ok(spec)
|
||||
}
|
||||
|
||||
fn parse_date(p: Pair<'_, Rule>) -> Result<Spec> {
|
||||
assert_eq!(p.as_rule(), Rule::date);
|
||||
fn parse_stmt_date(p: Pair<'_, Rule>) -> Result<Statement> {
|
||||
assert_eq!(p.as_rule(), Rule::stmt_date);
|
||||
let p = p.into_inner().next().unwrap();
|
||||
match p.as_rule() {
|
||||
Rule::date_fixed => parse_date_fixed(p).map(Spec::Date),
|
||||
Rule::date_expr => parse_date_expr(p).map(Spec::Formula),
|
||||
Rule::date_weekday => parse_date_weekday(p).map(Spec::Weekday),
|
||||
let spec = match p.as_rule() {
|
||||
Rule::date_fixed => Spec::Date(parse_date_fixed(p)?),
|
||||
Rule::date_expr => Spec::Formula(parse_date_expr(p)?),
|
||||
Rule::date_weekday => Spec::Weekday(parse_date_weekday(p)?),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Ok(Statement::Date(spec))
|
||||
}
|
||||
|
||||
fn parse_bdatum(p: Pair<'_, Rule>) -> Result<BirthdaySpec> {
|
||||
assert_eq!(p.as_rule(), Rule::bdatum);
|
||||
let span = p.as_span();
|
||||
let p = p.into_inner().collect::<Vec<_>>();
|
||||
assert!(p.len() == 2 || p.len() == 3);
|
||||
|
||||
let (y, m, d, year_known) = if p.len() == 3 {
|
||||
let y = p[0].as_str().parse().unwrap();
|
||||
let m = p[1].as_str().parse().unwrap();
|
||||
let d = p[2].as_str().parse().unwrap();
|
||||
(y, m, d, true)
|
||||
} else {
|
||||
let m = p[0].as_str().parse().unwrap();
|
||||
let d = p[1].as_str().parse().unwrap();
|
||||
(0, m, d, false)
|
||||
};
|
||||
|
||||
let date = match NaiveDate::from_ymd_opt(y, m, d) {
|
||||
Some(date) => Ok(date),
|
||||
None => fail(span, "invalid date"),
|
||||
}?;
|
||||
|
||||
Ok(BirthdaySpec { date, year_known })
|
||||
}
|
||||
|
||||
fn parse_stmt_bdate(p: Pair<'_, Rule>) -> Result<Statement> {
|
||||
assert_eq!(p.as_rule(), Rule::stmt_bdate);
|
||||
let spec = parse_bdatum(p.into_inner().next().unwrap())?;
|
||||
Ok(Statement::BDate(spec))
|
||||
}
|
||||
|
||||
fn parse_stmt_from(p: Pair<'_, Rule>) -> Result<Statement> {
|
||||
assert_eq!(p.as_rule(), Rule::stmt_from);
|
||||
let mut p = p.into_inner();
|
||||
let datum = match p.next() {
|
||||
Some(p) => Some(parse_datum(p)?.value),
|
||||
None => None,
|
||||
};
|
||||
assert_eq!(p.next(), None);
|
||||
Ok(Statement::From(datum))
|
||||
}
|
||||
|
||||
fn parse_stmt_until(p: Pair<'_, Rule>) -> Result<Statement> {
|
||||
assert_eq!(p.as_rule(), Rule::stmt_until);
|
||||
let mut p = p.into_inner();
|
||||
let datum = match p.next() {
|
||||
Some(p) => Some(parse_datum(p)?.value),
|
||||
None => None,
|
||||
};
|
||||
assert_eq!(p.next(), None);
|
||||
Ok(Statement::Until(datum))
|
||||
}
|
||||
|
||||
fn parse_stmt_except(p: Pair<'_, Rule>) -> Result<Statement> {
|
||||
assert_eq!(p.as_rule(), Rule::stmt_except);
|
||||
let datum = parse_datum(p.into_inner().next().unwrap())?.value;
|
||||
Ok(Statement::Except(datum))
|
||||
}
|
||||
|
||||
fn parse_stmt_move(p: Pair<'_, Rule>) -> Result<Statement> {
|
||||
assert_eq!(p.as_rule(), Rule::stmt_move);
|
||||
let mut p = p.into_inner();
|
||||
let from = parse_datum(p.next().unwrap())?.value;
|
||||
let to = parse_datum(p.next().unwrap())?.value;
|
||||
assert_eq!(p.next(), None);
|
||||
Ok(Statement::Move(from, to))
|
||||
}
|
||||
|
||||
fn parse_statements(p: Pair<'_, Rule>) -> Result<Vec<Statement>> {
|
||||
assert_eq!(p.as_rule(), Rule::statements);
|
||||
let mut statements = vec![];
|
||||
for p in p.into_inner() {
|
||||
statements.push(match p.as_rule() {
|
||||
Rule::stmt_date => parse_stmt_date(p)?,
|
||||
Rule::stmt_bdate => parse_stmt_bdate(p)?,
|
||||
Rule::stmt_from => parse_stmt_from(p)?,
|
||||
Rule::stmt_until => parse_stmt_until(p)?,
|
||||
Rule::stmt_except => parse_stmt_except(p)?,
|
||||
Rule::stmt_move => parse_stmt_move(p)?,
|
||||
_ => unreachable!(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_from(p: Pair<'_, Rule>) -> Result<NaiveDate> {
|
||||
assert_eq!(p.as_rule(), Rule::from);
|
||||
let datum = parse_datum(p.into_inner().next().unwrap())?;
|
||||
Ok(datum.value)
|
||||
}
|
||||
|
||||
fn parse_until(p: Pair<'_, Rule>) -> Result<NaiveDate> {
|
||||
assert_eq!(p.as_rule(), Rule::until);
|
||||
let datum = parse_datum(p.into_inner().next().unwrap())?;
|
||||
Ok(datum.value)
|
||||
}
|
||||
|
||||
fn parse_except(p: Pair<'_, Rule>) -> Result<NaiveDate> {
|
||||
assert_eq!(p.as_rule(), Rule::except);
|
||||
let datum = parse_datum(p.into_inner().next().unwrap())?;
|
||||
Ok(datum.value)
|
||||
Ok(statements)
|
||||
}
|
||||
|
||||
fn parse_donedate(p: Pair<'_, Rule>) -> Result<DoneDate> {
|
||||
|
|
@ -609,36 +677,13 @@ fn parse_done(p: Pair<'_, Rule>) -> Result<Done> {
|
|||
Ok(Done { date, done_at })
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Options {
|
||||
when: Vec<Spec>,
|
||||
from: Option<NaiveDate>,
|
||||
until: Option<NaiveDate>,
|
||||
except: Vec<NaiveDate>,
|
||||
done: Vec<Done>,
|
||||
}
|
||||
|
||||
fn parse_options(p: Pair<'_, Rule>) -> Result<Options> {
|
||||
assert!(matches!(
|
||||
p.as_rule(),
|
||||
Rule::task_options | Rule::note_options
|
||||
));
|
||||
|
||||
let mut opts = Options::default();
|
||||
for opt in p.into_inner() {
|
||||
match opt.as_rule() {
|
||||
Rule::date => opts.when.push(parse_date(opt)?),
|
||||
Rule::from if opts.from.is_none() => opts.from = Some(parse_from(opt)?),
|
||||
Rule::from => fail(opt.as_span(), "FROM already defined earlier")?,
|
||||
Rule::until if opts.until.is_none() => opts.until = Some(parse_until(opt)?),
|
||||
Rule::until => fail(opt.as_span(), "UNTIL already defined earlier")?,
|
||||
Rule::except => opts.except.push(parse_except(opt)?),
|
||||
Rule::done => opts.done.push(parse_done(opt)?),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
fn parse_dones(p: Pair<'_, Rule>) -> Result<Vec<Done>> {
|
||||
assert_eq!(p.as_rule(), Rule::dones);
|
||||
let mut dones = vec![];
|
||||
for p in p.into_inner() {
|
||||
dones.push(parse_done(p)?);
|
||||
}
|
||||
|
||||
Ok(opts)
|
||||
Ok(dones)
|
||||
}
|
||||
|
||||
fn parse_desc_line(p: Pair<'_, Rule>) -> Result<String> {
|
||||
|
|
@ -662,18 +707,16 @@ fn parse_task(p: Pair<'_, Rule>) -> Result<Task> {
|
|||
let mut p = p.into_inner();
|
||||
|
||||
let title = parse_title(p.next().unwrap());
|
||||
let opts = parse_options(p.next().unwrap())?;
|
||||
let statements = parse_statements(p.next().unwrap())?;
|
||||
let done = parse_dones(p.next().unwrap())?;
|
||||
let desc = parse_description(p.next().unwrap())?;
|
||||
|
||||
assert_eq!(p.next(), None);
|
||||
|
||||
Ok(Task {
|
||||
title,
|
||||
when: opts.when,
|
||||
from: opts.from,
|
||||
until: opts.until,
|
||||
except: opts.except,
|
||||
done: opts.done,
|
||||
statements,
|
||||
done,
|
||||
desc,
|
||||
})
|
||||
}
|
||||
|
|
@ -683,63 +726,18 @@ fn parse_note(p: Pair<'_, Rule>) -> Result<Note> {
|
|||
let mut p = p.into_inner();
|
||||
|
||||
let title = parse_title(p.next().unwrap());
|
||||
let opts = parse_options(p.next().unwrap())?;
|
||||
let statements = parse_statements(p.next().unwrap())?;
|
||||
let desc = parse_description(p.next().unwrap())?;
|
||||
|
||||
assert_eq!(p.next(), None);
|
||||
assert!(opts.done.is_empty());
|
||||
|
||||
Ok(Note {
|
||||
title,
|
||||
when: opts.when,
|
||||
from: opts.from,
|
||||
until: opts.until,
|
||||
except: opts.except,
|
||||
statements,
|
||||
desc,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_bdatum(p: Pair<'_, Rule>) -> Result<BirthdaySpec> {
|
||||
assert_eq!(p.as_rule(), Rule::bdatum);
|
||||
let span = p.as_span();
|
||||
let p = p.into_inner().collect::<Vec<_>>();
|
||||
assert!(p.len() == 2 || p.len() == 3);
|
||||
|
||||
let (y, m, d, year_known) = if p.len() == 3 {
|
||||
let y = p[0].as_str().parse().unwrap();
|
||||
let m = p[1].as_str().parse().unwrap();
|
||||
let d = p[2].as_str().parse().unwrap();
|
||||
(y, m, d, true)
|
||||
} else {
|
||||
let m = p[0].as_str().parse().unwrap();
|
||||
let d = p[1].as_str().parse().unwrap();
|
||||
(0, m, d, false)
|
||||
};
|
||||
|
||||
let date = match NaiveDate::from_ymd_opt(y, m, d) {
|
||||
Some(date) => Ok(date),
|
||||
None => fail(span, "invalid date"),
|
||||
}?;
|
||||
|
||||
Ok(BirthdaySpec { date, year_known })
|
||||
}
|
||||
|
||||
fn parse_bdate(p: Pair<'_, Rule>) -> Result<BirthdaySpec> {
|
||||
assert_eq!(p.as_rule(), Rule::bdate);
|
||||
parse_bdatum(p.into_inner().next().unwrap())
|
||||
}
|
||||
|
||||
fn parse_birthday(p: Pair<'_, Rule>) -> Result<Birthday> {
|
||||
assert_eq!(p.as_rule(), Rule::birthday);
|
||||
let mut p = p.into_inner();
|
||||
|
||||
let title = parse_title(p.next().unwrap());
|
||||
let when = parse_bdate(p.next().unwrap())?;
|
||||
let desc = parse_description(p.next().unwrap())?;
|
||||
|
||||
Ok(Birthday { title, when, desc })
|
||||
}
|
||||
|
||||
fn parse_command(p: Pair<'_, Rule>, file: &mut File) -> Result<()> {
|
||||
assert_eq!(p.as_rule(), Rule::command);
|
||||
|
||||
|
|
@ -752,7 +750,6 @@ fn parse_command(p: Pair<'_, Rule>, file: &mut File) -> Result<()> {
|
|||
},
|
||||
Rule::task => file.commands.push(Command::Task(parse_task(p)?)),
|
||||
Rule::note => file.commands.push(Command::Note(parse_note(p)?)),
|
||||
Rule::birthday => file.commands.push(Command::Birthday(parse_birthday(p)?)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
|
|
|
|||
14
src/main.rs
14
src/main.rs
|
|
@ -8,10 +8,10 @@ use std::path::PathBuf;
|
|||
use chrono::NaiveDate;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use crate::eval::DateRange;
|
||||
// use crate::eval::DateRange;
|
||||
use crate::files::Files;
|
||||
|
||||
mod eval;
|
||||
// mod eval;
|
||||
mod files;
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
|
|
@ -26,11 +26,11 @@ fn main() -> anyhow::Result<()> {
|
|||
let mut files = Files::load(&opt.file)?;
|
||||
println!("{}", files.now().format("%F %T %Z"));
|
||||
|
||||
let range = DateRange::new(
|
||||
NaiveDate::from_ymd(2021, 11, 20),
|
||||
NaiveDate::from_ymd(2021, 11, 26),
|
||||
);
|
||||
println!("{:#?}", files.eval(range));
|
||||
// let range = DateRange::new(
|
||||
// NaiveDate::from_ymd(2021, 11, 20),
|
||||
// NaiveDate::from_ymd(2021, 11, 26),
|
||||
// );
|
||||
// println!("{:#?}", files.eval(range));
|
||||
|
||||
files.mark_all_dirty();
|
||||
files.save()?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue