Unify Dates logic and expand DoneDate format
This commit is contained in:
parent
2e7ab3c4a1
commit
c69af9bcde
8 changed files with 119 additions and 133 deletions
|
|
@ -80,7 +80,7 @@ impl DayLayout {
|
||||||
|
|
||||||
fn layout_task(&mut self, index: usize, entry: &Entry) {
|
fn layout_task(&mut self, index: usize, entry: &Entry) {
|
||||||
if let Some(dates) = entry.dates {
|
if let Some(dates) = entry.dates {
|
||||||
let (start, end) = dates.start_end();
|
let (start, end) = dates.sorted().dates();
|
||||||
if self.today < start && (start - self.today).num_days() < 7 {
|
if self.today < start && (start - self.today).num_days() < 7 {
|
||||||
// TODO Make this adjustable, maybe even per-command
|
// TODO Make this adjustable, maybe even per-command
|
||||||
let days = (start - self.today).num_days();
|
let days = (start - self.today).num_days();
|
||||||
|
|
@ -100,8 +100,9 @@ impl DayLayout {
|
||||||
|
|
||||||
fn layout_task_done(&mut self, index: usize, entry: &Entry, at: NaiveDate) {
|
fn layout_task_done(&mut self, index: usize, entry: &Entry, at: NaiveDate) {
|
||||||
if let Some(dates) = entry.dates {
|
if let Some(dates) = entry.dates {
|
||||||
if at > dates.end() {
|
let (_, end) = dates.sorted().dates();
|
||||||
let days = (at - dates.end()).num_days();
|
if at > end {
|
||||||
|
let days = (at - end).num_days();
|
||||||
self.insert(at, DayEntry::ReminderSince(index, days));
|
self.insert(at, DayEntry::ReminderSince(index, days));
|
||||||
}
|
}
|
||||||
self.layout_dated_entry(index, dates);
|
self.layout_dated_entry(index, dates);
|
||||||
|
|
@ -113,7 +114,7 @@ impl DayLayout {
|
||||||
|
|
||||||
fn layout_note(&mut self, index: usize, entry: &Entry) {
|
fn layout_note(&mut self, index: usize, entry: &Entry) {
|
||||||
if let Some(dates) = entry.dates {
|
if let Some(dates) = entry.dates {
|
||||||
let (start, end) = dates.start_end();
|
let (start, end) = dates.sorted().dates();
|
||||||
if start < self.range.from() && self.range.until() < end {
|
if start < self.range.from() && self.range.until() < end {
|
||||||
// This note applies to the current day, but it won't appear if
|
// This note applies to the current day, but it won't appear if
|
||||||
// we just layout it as a dated entry, so instead we add it as a
|
// we just layout it as a dated entry, so instead we add it as a
|
||||||
|
|
@ -131,9 +132,10 @@ impl DayLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_dated_entry(&mut self, index: usize, dates: Dates) {
|
fn layout_dated_entry(&mut self, index: usize, dates: Dates) {
|
||||||
let (start, end) = dates.start_end();
|
let sorted_dates = dates.sorted();
|
||||||
|
let (start, end) = sorted_dates.dates();
|
||||||
#[allow(clippy::if_same_then_else)] // Makes the code easier to read
|
#[allow(clippy::if_same_then_else)] // Makes the code easier to read
|
||||||
if let Some((date, time)) = dates.point_in_time() {
|
if let Some((date, time)) = sorted_dates.point_in_time() {
|
||||||
let entry = match time {
|
let entry = match time {
|
||||||
Some(time) => DayEntry::TimedAt(index, time, None),
|
Some(time) => DayEntry::TimedAt(index, time, None),
|
||||||
None => DayEntry::At(index),
|
None => DayEntry::At(index),
|
||||||
|
|
@ -149,7 +151,7 @@ impl DayLayout {
|
||||||
// omit them both. Otherwise, we would get a bracket without any
|
// omit them both. Otherwise, we would get a bracket without any
|
||||||
// visible start or end.
|
// visible start or end.
|
||||||
} else {
|
} else {
|
||||||
let (start_entry, end_entry) = match dates.start_end_time() {
|
let (start_entry, end_entry) = match sorted_dates.times() {
|
||||||
Some((start_time, end_time)) => (
|
Some((start_time, end_time)) => (
|
||||||
DayEntry::TimedStart(index, start_time),
|
DayEntry::TimedStart(index, start_time),
|
||||||
DayEntry::TimedEnd(index, end_time),
|
DayEntry::TimedEnd(index, end_time),
|
||||||
|
|
@ -196,13 +198,13 @@ impl DayLayout {
|
||||||
|
|
||||||
// 2.
|
// 2.
|
||||||
entries.sort_by(|(_, e1, _), (_, e2, _)| {
|
entries.sort_by(|(_, e1, _), (_, e2, _)| {
|
||||||
let d1 = e1.dates.map(|d| (d.end(), d.end_time()));
|
let d1 = e1.dates.map(|d| d.sorted().other_with_time());
|
||||||
let d2 = e2.dates.map(|d| (d.end(), d.end_time()));
|
let d2 = e2.dates.map(|d| d.sorted().other_with_time());
|
||||||
d2.cmp(&d1)
|
d2.cmp(&d1) // Inverse comparison
|
||||||
});
|
});
|
||||||
|
|
||||||
// 1.
|
// 1.
|
||||||
entries.sort_by_key(|(_, e, _)| e.dates.map(|d| (d.start(), d.start_time())));
|
entries.sort_by_key(|(_, e, _)| e.dates.map(|d| d.sorted().root_with_time()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort_day(day: &mut Vec<DayEntry>) {
|
fn sort_day(day: &mut Vec<DayEntry>) {
|
||||||
|
|
|
||||||
|
|
@ -145,22 +145,10 @@ pub fn show_entry(files: &Files, entry: &Entry) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(dates) = entry.dates {
|
if let Some(dates) = entry.dates {
|
||||||
let (start, end) = dates.start_end();
|
println!("DATE {}", dates.sorted());
|
||||||
if start == end {
|
|
||||||
match dates.start_end_time() {
|
|
||||||
Some((s, e)) if s == e => println!("DATE {} {}", start, s),
|
|
||||||
Some((s, e)) => println!("DATE {} {} -- {}", start, s, e),
|
|
||||||
None => println!("DATE {}", start),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match dates.start_end_time() {
|
|
||||||
Some((s, e)) => println!("DATE {} {} -- {} {}", start, s, end, e),
|
|
||||||
None => println!("DATE {} -- {}", start, end),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
println!("NO DATE");
|
println!("NO DATE");
|
||||||
};
|
}
|
||||||
|
|
||||||
for line in command.desc() {
|
for line in command.desc() {
|
||||||
println!("# {}", line);
|
println!("# {}", line);
|
||||||
|
|
|
||||||
178
src/eval/date.rs
178
src/eval/date.rs
|
|
@ -20,44 +20,8 @@ pub struct Dates {
|
||||||
|
|
||||||
impl fmt::Display for Dates {
|
impl fmt::Display for Dates {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let (start, end) = self.start_end();
|
let done_date: DoneDate = (*self).into();
|
||||||
match self.start_end_time() {
|
write!(f, "{}", done_date)
|
||||||
Some((start_time, end_time)) if start == end && start_time == end_time => {
|
|
||||||
write!(f, "{} {}", start, start_time)
|
|
||||||
}
|
|
||||||
Some((start_time, end_time)) if start == end => {
|
|
||||||
write!(f, "{} {} -- {}", start, start_time, end_time)
|
|
||||||
}
|
|
||||||
Some((start_time, end_time)) => {
|
|
||||||
write!(f, "{} {} -- {} {}", start, start_time, end, end_time)
|
|
||||||
}
|
|
||||||
None if start == end => write!(f, "{}", start),
|
|
||||||
None => write!(f, "{} -- {}", start, end),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Dates> for DoneDate {
|
|
||||||
fn from(dates: Dates) -> Self {
|
|
||||||
match dates.times {
|
|
||||||
Some(times) if dates.root == dates.other && times.root == times.other => {
|
|
||||||
DoneDate::DateWithTime {
|
|
||||||
root: dates.root,
|
|
||||||
root_time: times.root,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(times) => DoneDate::DateToDateWithTime {
|
|
||||||
root: dates.root,
|
|
||||||
root_time: times.root,
|
|
||||||
other: dates.other,
|
|
||||||
other_time: times.other,
|
|
||||||
},
|
|
||||||
None if dates.root == dates.other => DoneDate::Date { root: dates.root },
|
|
||||||
None => DoneDate::DateToDate {
|
|
||||||
root: dates.root,
|
|
||||||
other: dates.other,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,66 +50,55 @@ impl Dates {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn root(&self) -> NaiveDate {
|
pub fn root(self) -> NaiveDate {
|
||||||
self.root
|
self.root
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn other(&self) -> NaiveDate {
|
pub fn root_with_time(self) -> (NaiveDate, Option<Time>) {
|
||||||
self.other
|
(self.root, self.times.map(|t| t.root))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn root_time(&self) -> Option<Time> {
|
pub fn other_with_time(self) -> (NaiveDate, Option<Time>) {
|
||||||
self.times.map(|times| times.root)
|
(self.other, self.times.map(|t| t.other))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn other_time(&self) -> Option<Time> {
|
pub fn dates(self) -> (NaiveDate, NaiveDate) {
|
||||||
self.times.map(|times| times.other)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_end(&self) -> (NaiveDate, NaiveDate) {
|
|
||||||
if self.root <= self.other {
|
|
||||||
(self.root, self.other)
|
(self.root, self.other)
|
||||||
} else {
|
}
|
||||||
(self.other, self.root)
|
|
||||||
|
pub fn times(self) -> Option<(Time, Time)> {
|
||||||
|
self.times.map(|times| (times.root, times.other))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Flip `root` and `other`.
|
||||||
|
fn flip(self) -> Self {
|
||||||
|
Self {
|
||||||
|
root: self.other,
|
||||||
|
other: self.root,
|
||||||
|
times: self.times.map(|times| Times {
|
||||||
|
root: times.other,
|
||||||
|
other: times.root,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&self) -> NaiveDate {
|
/// Return a new [`Dates`] where `root` is the earlier and `other` the later
|
||||||
self.start_end().0
|
/// date.
|
||||||
}
|
pub fn sorted(self) -> Self {
|
||||||
|
|
||||||
pub fn end(&self) -> NaiveDate {
|
|
||||||
self.start_end().1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_end_time(&self) -> Option<(Time, Time)> {
|
|
||||||
if let Some(times) = self.times {
|
|
||||||
if self.root < self.other || (self.root == self.other && times.root <= times.other) {
|
|
||||||
Some((times.root, times.other))
|
|
||||||
} else {
|
|
||||||
Some((times.other, times.root))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_time(&self) -> Option<Time> {
|
|
||||||
self.start_end_time().map(|times| times.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn end_time(&self) -> Option<Time> {
|
|
||||||
self.start_end_time().map(|times| times.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn point_in_time(&self) -> Option<(NaiveDate, Option<Time>)> {
|
|
||||||
if self.root != self.other {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
match self.times {
|
match self.times {
|
||||||
Some(times) if times.root == times.other => Some((self.root, Some(times.root))),
|
_ if self.root < self.other => self,
|
||||||
Some(_) => None,
|
None if self.root <= self.other => self,
|
||||||
None => Some((self.root, None)),
|
Some(times) if self.root <= self.other && times.root <= times.other => self,
|
||||||
|
_ => self.flip(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn point_in_time(self) -> Option<(NaiveDate, Option<Time>)> {
|
||||||
|
let done_date: DoneDate = self.into();
|
||||||
|
match done_date {
|
||||||
|
DoneDate::Date { root } => Some((root, None)),
|
||||||
|
DoneDate::DateTime { root, root_time } => Some((root, Some(root_time))),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,28 +115,53 @@ impl From<DoneDate> for Dates {
|
||||||
fn from(date: DoneDate) -> Self {
|
fn from(date: DoneDate) -> Self {
|
||||||
match date {
|
match date {
|
||||||
DoneDate::Date { root } => Self::new(root, root),
|
DoneDate::Date { root } => Self::new(root, root),
|
||||||
DoneDate::DateWithTime { root, root_time } => {
|
DoneDate::DateTime { root, root_time } => {
|
||||||
Self::new_with_time(root, root_time, root, root_time)
|
Self::new_with_time(root, root_time, root, root_time)
|
||||||
}
|
}
|
||||||
DoneDate::DateToDate { root, other } => {
|
DoneDate::DateToDate { root, other } => Self::new(root, other),
|
||||||
if root <= other {
|
DoneDate::DateTimeToTime {
|
||||||
Self::new(root, other)
|
root,
|
||||||
} else {
|
root_time,
|
||||||
Self::new(other, root)
|
other_time,
|
||||||
}
|
} => Self::new_with_time(root, root_time, root, other_time),
|
||||||
}
|
DoneDate::DateTimeToDateTime {
|
||||||
DoneDate::DateToDateWithTime {
|
|
||||||
root,
|
root,
|
||||||
root_time,
|
root_time,
|
||||||
other,
|
other,
|
||||||
other_time,
|
other_time,
|
||||||
} => {
|
} => Self::new_with_time(root, root_time, other, other_time),
|
||||||
if root < other || (root == other && root_time <= other_time) {
|
|
||||||
Self::new_with_time(root, root_time, other, other_time)
|
|
||||||
} else {
|
|
||||||
Self::new_with_time(other, other_time, root, root_time)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Dates> for DoneDate {
|
||||||
|
fn from(dates: Dates) -> Self {
|
||||||
|
if dates.root == dates.other {
|
||||||
|
match dates.times {
|
||||||
|
Some(times) if times.root == times.other => Self::DateTime {
|
||||||
|
root: dates.root,
|
||||||
|
root_time: times.root,
|
||||||
|
},
|
||||||
|
Some(times) => Self::DateTimeToTime {
|
||||||
|
root: dates.root,
|
||||||
|
root_time: times.root,
|
||||||
|
other_time: times.other,
|
||||||
|
},
|
||||||
|
None => Self::Date { root: dates.root },
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match dates.times {
|
||||||
|
Some(times) => Self::DateTimeToDateTime {
|
||||||
|
root: dates.root,
|
||||||
|
root_time: times.root,
|
||||||
|
other: dates.other,
|
||||||
|
other_time: times.other,
|
||||||
|
},
|
||||||
|
None => Self::DateToDate {
|
||||||
|
root: dates.root,
|
||||||
|
other: dates.other,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,8 +75,9 @@ impl Entries {
|
||||||
|
|
||||||
fn is_touching(&self, entry: &Entry) -> bool {
|
fn is_touching(&self, entry: &Entry) -> bool {
|
||||||
if let Some(dates) = entry.dates {
|
if let Some(dates) = entry.dates {
|
||||||
|
let (start, end) = dates.sorted().dates();
|
||||||
// Inside the range or overlapping it
|
// Inside the range or overlapping it
|
||||||
dates.start() <= self.range.until() && self.range.from() <= dates.end()
|
start <= self.range.until() && self.range.from() <= end
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +103,8 @@ impl Entries {
|
||||||
// Unfinished tasks before or inside the range
|
// Unfinished tasks before or inside the range
|
||||||
if let EntryKind::Task = entry.kind {
|
if let EntryKind::Task = entry.kind {
|
||||||
if let Some(dates) = entry.dates {
|
if let Some(dates) = entry.dates {
|
||||||
if dates.start() <= self.range.until() {
|
let (start, _) = dates.sorted().dates();
|
||||||
|
if start <= self.range.until() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,7 @@ pub enum DoneDate {
|
||||||
Date {
|
Date {
|
||||||
root: NaiveDate,
|
root: NaiveDate,
|
||||||
},
|
},
|
||||||
DateWithTime {
|
DateTime {
|
||||||
root: NaiveDate,
|
root: NaiveDate,
|
||||||
root_time: Time,
|
root_time: Time,
|
||||||
},
|
},
|
||||||
|
|
@ -276,7 +276,12 @@ pub enum DoneDate {
|
||||||
root: NaiveDate,
|
root: NaiveDate,
|
||||||
other: NaiveDate,
|
other: NaiveDate,
|
||||||
},
|
},
|
||||||
DateToDateWithTime {
|
DateTimeToTime {
|
||||||
|
root: NaiveDate,
|
||||||
|
root_time: Time,
|
||||||
|
other_time: Time,
|
||||||
|
},
|
||||||
|
DateTimeToDateTime {
|
||||||
root: NaiveDate,
|
root: NaiveDate,
|
||||||
root_time: Time,
|
root_time: Time,
|
||||||
other: NaiveDate,
|
other: NaiveDate,
|
||||||
|
|
|
||||||
|
|
@ -229,9 +229,14 @@ impl fmt::Display for DoneDate {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
DoneDate::Date { root } => write!(f, "{}", root),
|
DoneDate::Date { root } => write!(f, "{}", root),
|
||||||
DoneDate::DateWithTime { root, root_time } => write!(f, "{} {}", root, root_time),
|
DoneDate::DateTime { root, root_time } => write!(f, "{} {}", root, root_time),
|
||||||
DoneDate::DateToDate { root, other } => write!(f, "{} -- {}", root, other),
|
DoneDate::DateToDate { root, other } => write!(f, "{} -- {}", root, other),
|
||||||
DoneDate::DateToDateWithTime {
|
DoneDate::DateTimeToTime {
|
||||||
|
root,
|
||||||
|
root_time,
|
||||||
|
other_time,
|
||||||
|
} => write!(f, "{} {} -- {}", root, root_time, other_time),
|
||||||
|
DoneDate::DateTimeToDateTime {
|
||||||
root,
|
root,
|
||||||
root_time,
|
root_time,
|
||||||
other,
|
other,
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,7 @@ statements = { (stmt_date | stmt_bdate | stmt_from | stmt_until | stmt_except |
|
||||||
|
|
||||||
donedate = {
|
donedate = {
|
||||||
datum ~ time ~ "--" ~ datum ~ time
|
datum ~ time ~ "--" ~ datum ~ time
|
||||||
|
| datum ~ time ~ "--" ~ time
|
||||||
| datum ~ time
|
| datum ~ time
|
||||||
| datum ~ "--" ~ datum
|
| datum ~ "--" ~ datum
|
||||||
| datum
|
| datum
|
||||||
|
|
|
||||||
|
|
@ -652,7 +652,7 @@ fn parse_donedate(p: Pair<'_, Rule>) -> Result<DoneDate> {
|
||||||
root: parse_datum(ps.pop().unwrap())?.value,
|
root: parse_datum(ps.pop().unwrap())?.value,
|
||||||
},
|
},
|
||||||
2 => match ps[1].as_rule() {
|
2 => match ps[1].as_rule() {
|
||||||
Rule::time => DoneDate::DateWithTime {
|
Rule::time => DoneDate::DateTime {
|
||||||
root_time: parse_time(ps.pop().unwrap())?.value,
|
root_time: parse_time(ps.pop().unwrap())?.value,
|
||||||
root: parse_datum(ps.pop().unwrap())?.value,
|
root: parse_datum(ps.pop().unwrap())?.value,
|
||||||
},
|
},
|
||||||
|
|
@ -662,7 +662,12 @@ fn parse_donedate(p: Pair<'_, Rule>) -> Result<DoneDate> {
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
4 => DoneDate::DateToDateWithTime {
|
3 => DoneDate::DateTimeToTime {
|
||||||
|
other_time: parse_time(ps.pop().unwrap())?.value,
|
||||||
|
root_time: parse_time(ps.pop().unwrap())?.value,
|
||||||
|
root: parse_datum(ps.pop().unwrap())?.value,
|
||||||
|
},
|
||||||
|
4 => DoneDate::DateTimeToDateTime {
|
||||||
other_time: parse_time(ps.pop().unwrap())?.value,
|
other_time: parse_time(ps.pop().unwrap())?.value,
|
||||||
other: parse_datum(ps.pop().unwrap())?.value,
|
other: parse_datum(ps.pop().unwrap())?.value,
|
||||||
root_time: parse_time(ps.pop().unwrap())?.value,
|
root_time: parse_time(ps.pop().unwrap())?.value,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue