Support marking multiple tasks as done
Not yet exposed via the CLI though
This commit is contained in:
parent
c07d27aa13
commit
ab63261dfd
5 changed files with 32 additions and 25 deletions
|
|
@ -92,7 +92,7 @@ pub fn run() -> Result<()> {
|
||||||
},
|
},
|
||||||
Some(Command::Done) => match opt.entry {
|
Some(Command::Done) => match opt.entry {
|
||||||
None => return Err(Error::NoNumber),
|
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(),
|
Some(Command::Fmt) => files.mark_all_dirty(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,36 @@
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
|
|
||||||
use crate::eval::Entry;
|
use crate::eval::Entry;
|
||||||
use crate::files::commands::Done;
|
use crate::files::commands::Done;
|
||||||
use crate::files::Files;
|
use crate::files::Files;
|
||||||
|
|
||||||
use super::error::Result;
|
use super::error::{Error, Result};
|
||||||
use super::layout::line::LineLayout;
|
use super::layout::line::LineLayout;
|
||||||
|
|
||||||
pub fn mark_done(
|
pub fn mark_done(
|
||||||
files: &mut Files,
|
files: &mut Files,
|
||||||
entries: &[Entry],
|
entries: &[Entry],
|
||||||
layout: &LineLayout,
|
layout: &LineLayout,
|
||||||
number: usize,
|
numbers: &[usize],
|
||||||
now: NaiveDateTime,
|
now: NaiveDateTime,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let mut not_tasks = vec![];
|
||||||
|
for &number in numbers {
|
||||||
let entry = &entries[layout.look_up_number(number)?];
|
let entry = &entries[layout.look_up_number(number)?];
|
||||||
let done = Done {
|
let done = Done {
|
||||||
date: entry.dates.map(|dates| dates.into()),
|
date: entry.dates.map(|dates| dates.into()),
|
||||||
done_at: now.date(),
|
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(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::NotATask(not_tasks))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ pub enum Error {
|
||||||
NoNumber,
|
NoNumber,
|
||||||
#[error("No entry with number {0}")]
|
#[error("No entry with number {0}")]
|
||||||
NoSuchEntry(usize),
|
NoSuchEntry(usize),
|
||||||
|
#[error("Not a task")]
|
||||||
|
NotATask(Vec<usize>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
|
||||||
11
src/files.rs
11
src/files.rs
|
|
@ -163,14 +163,19 @@ impl Files {
|
||||||
&self.files[source.file].file.commands[source.command]
|
&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];
|
let file = &mut self.files[source.file];
|
||||||
match &mut file.file.commands[source.command] {
|
match &mut file.file.commands[source.command] {
|
||||||
Command::Task(t) => t.done.push(done),
|
Command::Task(t) => t.done.push(done),
|
||||||
Command::Note(_) => return Err(Error::NotATask(vec![number])),
|
Command::Note(_) => return false,
|
||||||
}
|
}
|
||||||
file.dirty = true;
|
file.dirty = true;
|
||||||
Ok(())
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn commands(&self) -> Vec<SourcedCommand<'_>> {
|
pub fn commands(&self) -> Vec<SourcedCommand<'_>> {
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ pub enum Error {
|
||||||
file2: PathBuf,
|
file2: PathBuf,
|
||||||
tz2: String,
|
tz2: String,
|
||||||
},
|
},
|
||||||
#[error("Not a task")]
|
|
||||||
NotATask(Vec<usize>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
|
|
@ -62,16 +60,6 @@ impl Error {
|
||||||
eprintln!(" {:?} has time zone {}", file1, tz1);
|
eprintln!(" {:?} has time zone {}", file1, tz1);
|
||||||
eprintln!(" {:?} has time zone {}", file2, tz2);
|
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(", "));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue