Support marking multiple tasks as done

Not yet exposed via the CLI though
This commit is contained in:
Joscha 2021-12-16 00:47:59 +01:00
parent c07d27aa13
commit ab63261dfd
5 changed files with 32 additions and 25 deletions

View file

@ -92,7 +92,7 @@ pub fn run() -> Result<()> {
},
Some(Command::Done) => match opt.entry {
None => return Err(Error::NoNumber),
Some(n) => done::mark_done(&mut files, &entries, &layout, n, now)?,
Some(n) => done::mark_done(&mut files, &entries, &layout, &[n], now)?,
},
Some(Command::Fmt) => files.mark_all_dirty(),
}

View file

@ -1,24 +1,36 @@
use std::vec;
use chrono::NaiveDateTime;
use crate::eval::Entry;
use crate::files::commands::Done;
use crate::files::Files;
use super::error::Result;
use super::error::{Error, Result};
use super::layout::line::LineLayout;
pub fn mark_done(
files: &mut Files,
entries: &[Entry],
layout: &LineLayout,
number: usize,
numbers: &[usize],
now: NaiveDateTime,
) -> Result<()> {
let mut not_tasks = vec![];
for &number in numbers {
let entry = &entries[layout.look_up_number(number)?];
let done = Done {
date: entry.dates.map(|dates| dates.into()),
done_at: now.date(),
};
files.add_done(number, entry.source, done)?;
if !files.add_done(entry.source, done) {
not_tasks.push(number);
}
}
if not_tasks.is_empty() {
Ok(())
} else {
Err(Error::NotATask(not_tasks))
}
}

View file

@ -12,6 +12,8 @@ pub enum Error {
NoNumber,
#[error("No entry with number {0}")]
NoSuchEntry(usize),
#[error("Not a task")]
NotATask(Vec<usize>),
}
pub type Result<T> = result::Result<T, Error>;

View file

@ -163,14 +163,19 @@ impl Files {
&self.files[source.file].file.commands[source.command]
}
pub fn add_done(&mut self, number: usize, source: Source, done: Done) -> Result<()> {
/// Add a [`Done`] statement to the task identified by `source`.
///
/// Returns whether the addition was successful. It can fail if the entry
/// identified by `source` is a note, not a task.
#[must_use]
pub fn add_done(&mut self, source: Source, done: Done) -> bool {
let file = &mut self.files[source.file];
match &mut file.file.commands[source.command] {
Command::Task(t) => t.done.push(done),
Command::Note(_) => return Err(Error::NotATask(vec![number])),
Command::Note(_) => return false,
}
file.dirty = true;
Ok(())
true
}
pub fn commands(&self) -> Vec<SourcedCommand<'_>> {

View file

@ -24,8 +24,6 @@ pub enum Error {
file2: PathBuf,
tz2: String,
},
#[error("Not a task")]
NotATask(Vec<usize>),
}
impl Error {
@ -62,16 +60,6 @@ impl Error {
eprintln!(" {:?} has time zone {}", file1, tz1);
eprintln!(" {:?} has time zone {}", file2, tz2);
}
Error::NotATask(numbers) => {
if numbers.is_empty() {
eprintln!("Not a task.");
} else if numbers.len() == 1 {
eprintln!("{} is not a task.", numbers[0]);
} else {
let numbers = numbers.iter().map(|n| n.to_string()).collect::<Vec<_>>();
eprintln!("{} are not tasks.", numbers.join(", "));
}
}
}
}
}