diff --git a/src/eval/command.rs b/src/eval/command.rs index 129b461..3bbcd65 100644 --- a/src/eval/command.rs +++ b/src/eval/command.rs @@ -5,6 +5,7 @@ use chrono::NaiveDate; use crate::files::commands::{BirthdaySpec, Command, Done, Note, Span, Spec, Statement, Task}; use crate::files::{Source, SourcedCommand}; +use super::date::Dates; use super::{DateRange, Entry, EntryKind, Error, Result}; mod birthday; @@ -51,22 +52,26 @@ impl<'a> CommandState<'a> { // Helper functions - fn title(&self) -> String { - self.command.command.title().to_string() + fn kind(&self) -> EntryKind { + match self.command.command { + Command::Task(_) => EntryKind::Task, + Command::Note(_) => EntryKind::Note, + } } - fn desc(&self) -> Vec { - self.command.command.desc().to_vec() - } - - fn source(&self) -> Source { - self.command.source + fn last_done(&self) -> Option { + match self.command.command { + Command::Task(task) => task.done.iter().map(|done| done.done_at).max(), + Command::Note(_) => None, + } } /// Add an entry, respecting [`Self::from`] and [`Self::until`]. Does not /// overwrite existing entries if a root date is specified. - fn add(&mut self, entry: Entry) { - if let Some(root) = entry.root { + fn add(&mut self, kind: EntryKind, dates: Option) { + let entry = Entry::new(self.command.source, kind, dates); + if let Some(dates) = dates { + let root = dates.root(); if let Some(from) = self.from { if root < from { return; @@ -85,9 +90,10 @@ impl<'a> CommandState<'a> { /// Add an entry, ignoring [`Self::from`] and [`Self::until`]. Always /// overwrites existing entries if a root date is specified. - fn add_forced(&mut self, entry: Entry) { - if let Some(root) = entry.root { - self.dated.insert(root, entry); + fn add_forced(&mut self, kind: EntryKind, dates: Option) { + let entry = Entry::new(self.command.source, kind, dates); + if let Some(dates) = dates { + self.dated.insert(dates.root(), entry); } else { self.undated.push(entry); } @@ -95,20 +101,37 @@ impl<'a> CommandState<'a> { // Actual evaluation + fn has_date_stmt(statements: &[Statement]) -> bool { + statements + .iter() + .any(|s| matches!(s, Statement::Date(_) | Statement::BDate(_))) + } + fn eval_task(&mut self, task: &Task) -> Result<()> { - for statement in &task.statements { - self.eval_statement(statement)?; + if Self::has_date_stmt(&task.statements) { + for statement in &task.statements { + self.eval_statement(statement)?; + } + } else { + self.add(self.kind(), None); } + for done in &task.done { self.eval_done(done); } + Ok(()) } fn eval_note(&mut self, note: &Note) -> Result<()> { - for statement in ¬e.statements { - self.eval_statement(statement)?; + if Self::has_date_stmt(¬e.statements) { + for statement in ¬e.statements { + self.eval_statement(statement)?; + } + } else { + self.add(self.kind(), None); } + Ok(()) } @@ -150,13 +173,9 @@ impl<'a> CommandState<'a> { } fn eval_done(&mut self, done: &Done) { - self.add_forced(Entry { - kind: EntryKind::TaskDone(done.done_at), - title: self.title(), - desc: self.desc(), - source: self.source(), - dates: done.date.map(|date| date.into()), - root: done.date.map(|date| date.root()), - }); + self.add_forced( + EntryKind::TaskDone(done.done_at), + done.date.map(|date| date.into()), + ); } } diff --git a/src/eval/command/birthday.rs b/src/eval/command/birthday.rs index f99202a..14ac989 100644 --- a/src/eval/command/birthday.rs +++ b/src/eval/command/birthday.rs @@ -4,7 +4,7 @@ use crate::eval::date::Dates; use crate::files::commands::BirthdaySpec; use super::super::command::CommandState; -use super::super::{Entry, EntryKind}; +use super::super::EntryKind; impl<'a> CommandState<'a> { pub fn eval_birthday_spec(&mut self, spec: &BirthdaySpec) { @@ -12,39 +12,26 @@ impl<'a> CommandState<'a> { // but I don't think that kind of optimization will be necessary any // time soon. for year in self.range.years() { - let mut title = self.title(); - - if spec.year_known { + let age = if spec.year_known { let age = year - spec.date.year(); if age < 0 { continue; } - title.push_str(&format!(" ({})", age)); - } + Some(age) + } else { + None + }; + let kind = EntryKind::Birthday(age); if let Some(date) = spec.date.with_year(year) { - self.add(Entry { - kind: EntryKind::Birthday, - title, - desc: self.desc(), - source: self.source(), - root: Some(date), - dates: Some(Dates::new(date, date)), - }); + self.add(EntryKind::Birthday(age), Some(Dates::new(date, date))); } else { assert_eq!(spec.date.month(), 2); assert_eq!(spec.date.day(), 29); let first = NaiveDate::from_ymd(year, 2, 28); let second = NaiveDate::from_ymd(year, 3, 1); - self.add(Entry { - kind: EntryKind::Birthday, - title, - desc: self.desc(), - source: self.source(), - root: Some(first), // This doesn't matter too much - dates: Some(Dates::new(first, second)), - }); + self.add(kind, Some(Dates::new(first, second))); } } } diff --git a/src/eval/date.rs b/src/eval/date.rs index e914691..33750f8 100644 --- a/src/eval/date.rs +++ b/src/eval/date.rs @@ -3,76 +3,93 @@ use chrono::NaiveDate; use crate::files::commands::{DoneDate, Time}; #[derive(Debug, Clone, Copy)] -pub struct Times { - start: Time, - end: Time, -} - -impl Times { - pub fn start(&self) -> Time { - self.start - } - - pub fn end(&self) -> Time { - self.end - } +struct Times { + root: Time, + other: Time, } #[derive(Debug, Clone, Copy)] pub struct Dates { - start: NaiveDate, - end: NaiveDate, + root: NaiveDate, + other: NaiveDate, times: Option, } impl Dates { - pub fn new(start: NaiveDate, end: NaiveDate) -> Self { - assert!(start <= end); + pub fn new(root: NaiveDate, other: NaiveDate) -> Self { Self { - start, - end, + root, + other, times: None, } } pub fn new_with_time( - start: NaiveDate, - start_time: Time, - end: NaiveDate, - end_time: Time, + root: NaiveDate, + root_time: Time, + other: NaiveDate, + other_time: Time, ) -> Self { - assert!(start <= end); - if start == end { - assert!(start_time <= end_time); - } Self { - start, - end, + root, + other, times: Some(Times { - start: start_time, - end: end_time, + root: root_time, + other: other_time, }), } } + pub fn root(&self) -> NaiveDate { + self.root + } + + pub fn other(&self) -> NaiveDate { + self.other + } + + pub fn root_time(&self) -> Option