Add more 'today new' templates

This commit is contained in:
Joscha 2022-01-14 23:16:29 +01:00
parent 3befb7c773
commit a3a0e0b9cf
2 changed files with 121 additions and 27 deletions

View file

@ -81,7 +81,19 @@ pub enum Command {
// TODO Add templates for tasks and notes // TODO Add templates for tasks and notes
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
pub enum Template { pub enum Template {
/// An undated task marked as done today /// Adds a task
#[structopt(alias = "t")]
Task {
/// If specified, the task is dated to this date
date: Option<String>,
},
/// Adds a note
#[structopt(alias = "n")]
Note {
/// If specified, the note is dated to this date
date: Option<String>,
},
/// Adds an undated task marked as done today
#[structopt(alias = "d")] #[structopt(alias = "d")]
Done, Done,
} }
@ -126,6 +138,10 @@ where
}) })
} }
fn parse_eval_date(name: &str, text: &str, today: NaiveDate) -> Result<NaiveDate> {
parse_eval_arg(name, text, |date: CliDate| date.eval((), today))
}
fn parse_show_idents(identifiers: &[String], today: NaiveDate) -> Result<Vec<show::Ident>> { fn parse_show_idents(identifiers: &[String], today: NaiveDate) -> Result<Vec<show::Ident>> {
let mut idents = vec![]; let mut idents = vec![];
for ident in identifiers { for ident in identifiers {
@ -152,7 +168,17 @@ fn run_command(opt: &Opt, files: &mut Files, range: DateRange, now: NaiveDateTim
show::show(files, &entries, &layout, &idents); show::show(files, &entries, &layout, &idents);
} }
Some(Command::New { template }) => match template { Some(Command::New { template }) => match template {
Template::Done => new::done(files, now)?, Template::Task { date: Some(date) } => {
let date = parse_eval_date("date", date, now.date())?;
new::task(files, Some(date))?
}
Template::Task { date: None } => new::task(files, None)?,
Template::Note { date: Some(date) } => {
let date = parse_eval_date("date", date, now.date())?;
new::note(files, Some(date))?
}
Template::Note { date: None } => new::note(files, None)?,
Template::Done => new::done(files, now.date())?,
}, },
Some(Command::Done { entries: ns }) => { Some(Command::Done { entries: ns }) => {
let entries = find_entries(files, range)?; let entries = find_entries(files, range)?;

View file

@ -1,46 +1,114 @@
use std::result;
use std::str::FromStr; use std::str::FromStr;
use chrono::NaiveDateTime; use chrono::NaiveDate;
use codespan_reporting::files::SimpleFile; use codespan_reporting::files::SimpleFile;
use crate::files::cli::CliCommand; use crate::files::cli::CliCommand;
use crate::files::commands::{Done, DoneKind, Task}; use crate::files::commands::{Command, DateSpec, Done, DoneKind, Note, Spec, Statement, Task};
use crate::files::Files; use crate::files::{Files, ParseError};
use super::error::{Error, Result}; use super::error::{Error, Result};
use super::util; use super::util;
pub fn done(files: &mut Files, now: NaiveDateTime) -> Result<()> { fn edit<R, F>(name: &str, mut text: String, validate: F) -> Result<Option<R>>
let capture = files.capture().ok_or(Error::NoCaptureFile)?; where
R: FromStr<Err = ParseError<()>>,
let command = Task { F: Fn(&R) -> result::Result<(), &str>,
title: String::new(), {
statements: vec![], Ok(loop {
done: vec![Done {
kind: DoneKind::Done,
date: None,
done_at: now.date(),
}],
desc: vec![],
};
let mut text = format!("{command}");
let command = loop {
text = util::edit(&text)?; text = util::edit(&text)?;
match CliCommand::from_str(&text) { match text.parse() {
Ok(command) => break command.0, Ok(command) => match validate(&command) {
Err(e) => crate::error::eprint_error(&SimpleFile::new("new command", &text), &e), Ok(()) => break Some(command),
Err(msg) => eprintln!("{msg}"),
},
Err(e) => crate::error::eprint_error(&SimpleFile::new(name, &text), &e),
} }
if !matches!( if !matches!(
promptly::prompt_default("Continue editing?", true), promptly::prompt_default("Continue editing?", true),
Ok(true) Ok(true)
) { ) {
println!("Aborting"); println!("Aborting");
return Ok(()); break None;
}
})
} }
};
files.insert(capture, command); fn is_task_or_note(command: &CliCommand) -> result::Result<(), &str> {
match command.0 {
Command::Task(_) | Command::Note(_) => Ok(()),
_ => Err("Only TASK and NOTE are allowed"),
}
}
fn new_command(files: &mut Files, command: Command) -> Result<()> {
let capture = files.capture().ok_or(Error::NoCaptureFile)?;
let command = edit("new command", format!("{command}"), is_task_or_note)?;
if let Some(command) = command {
files.insert(capture, command.0)
}
Ok(()) Ok(())
} }
pub fn task(files: &mut Files, date: Option<NaiveDate>) -> Result<()> {
let statements = match date {
Some(date) => vec![Statement::Date(Spec::Date(DateSpec {
start: date,
start_delta: None,
start_time: None,
end: None,
end_delta: None,
end_time: None,
repeat: None,
}))],
None => vec![],
};
let command = Command::Task(Task {
title: String::new(),
statements,
done: vec![],
desc: vec![],
});
new_command(files, command)
}
pub fn note(files: &mut Files, date: Option<NaiveDate>) -> Result<()> {
let statements = match date {
Some(date) => vec![Statement::Date(Spec::Date(DateSpec {
start: date,
start_delta: None,
start_time: None,
end: None,
end_delta: None,
end_time: None,
repeat: None,
}))],
None => vec![],
};
let command = Command::Note(Note {
title: String::new(),
statements,
desc: vec![],
});
new_command(files, command)
}
pub fn done(files: &mut Files, date: NaiveDate) -> Result<()> {
let command = Command::Task(Task {
title: String::new(),
statements: vec![],
done: vec![Done {
kind: DoneKind::Done,
date: None,
done_at: date,
}],
desc: vec![],
});
new_command(files, command)
}