Add more 'today new' templates
This commit is contained in:
parent
3befb7c773
commit
a3a0e0b9cf
2 changed files with 121 additions and 27 deletions
30
src/cli.rs
30
src/cli.rs
|
|
@ -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)?;
|
||||||
|
|
|
||||||
118
src/cli/new.rs
118
src/cli/new.rs
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue