From ee341ac7d52f2f6cd13688eaad85e5dcca48cd6a Mon Sep 17 00:00:00 2001 From: Simon Fraser Date: Thu, 17 Dec 2020 12:59:50 +0000 Subject: [PATCH] subcommands: prepend and append to description This currently uses format!() which may not be the best option. Fixes #88 --- cli/src/cmd/append.rs | 64 ++++++++++++++++++++++++++++++++++++++++++ cli/src/cmd/mod.rs | 4 +++ cli/src/cmd/prepend.rs | 64 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 cli/src/cmd/append.rs create mode 100644 cli/src/cmd/prepend.rs diff --git a/cli/src/cmd/append.rs b/cli/src/cmd/append.rs new file mode 100644 index 000000000..e32470475 --- /dev/null +++ b/cli/src/cmd/append.rs @@ -0,0 +1,64 @@ +use crate::cmd::shared; +use clap::{App, Arg, ArgMatches, SubCommand as ClapSubCommand}; +use failure::Fallible; + +use crate::cmd::{ArgMatchResult, CommandInvocation}; + +#[derive(Debug)] +struct Invocation { + task: String, + description: String, +} + +define_subcommand! { + fn decorate_app<'a>(&self, app: App<'a, 'a>) -> App<'a, 'a> { + app.subcommand( + ClapSubCommand::with_name("append").about("appends to a task description") + .arg(shared::task_arg()) + .arg( + Arg::with_name("description") + .help("extra task description") + .required(true), + ), + ) + } + fn arg_match<'a>(&self, matches: &ArgMatches<'a>) -> ArgMatchResult { + match matches.subcommand() { + ("append", Some(matches)) => ArgMatchResult::Ok(Box::new(Invocation { + task: matches.value_of("task").unwrap().into(), + description: matches.value_of("description").unwrap().into(), + })), + _ => ArgMatchResult::None, + } + } + +} + +subcommand_invocation! { + fn run(&self, command: &CommandInvocation) -> Fallible<()> { + let mut replica = command.get_replica()?; + let task = shared::get_task(&mut replica, &self.task)?; + + let mut task = task.into_mut(&mut replica); + + let new_description = format!("{} {}", task.get_description(), self.description.clone()); + task.set_description(new_description)?; + println!("appended to task {}", task.get_uuid()); + Ok(()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn parse_command() { + with_subcommand_invocation!( + vec!["task", "append", "1", "foo bar"], + |inv: &Invocation| { + assert_eq!(inv.description, "foo bar".to_string()); + } + ); + } +} diff --git a/cli/src/cmd/mod.rs b/cli/src/cmd/mod.rs index 17275c52e..e4e3851ea 100644 --- a/cli/src/cmd/mod.rs +++ b/cli/src/cmd/mod.rs @@ -6,6 +6,7 @@ mod macros; mod shared; mod add; +mod append; mod debug; mod delete; mod done; @@ -14,6 +15,7 @@ mod info; mod list; mod modify; mod pending; +mod prepend; mod start; mod stop; mod sync; @@ -22,6 +24,7 @@ mod sync; pub(crate) fn subcommands() -> Vec> { vec![ add::cmd(), + append::cmd(), debug::cmd(), delete::cmd(), done::cmd(), @@ -30,6 +33,7 @@ pub(crate) fn subcommands() -> Vec> { list::cmd(), modify::cmd(), pending::cmd(), + prepend::cmd(), start::cmd(), stop::cmd(), sync::cmd(), diff --git a/cli/src/cmd/prepend.rs b/cli/src/cmd/prepend.rs new file mode 100644 index 000000000..f827ac33a --- /dev/null +++ b/cli/src/cmd/prepend.rs @@ -0,0 +1,64 @@ +use crate::cmd::shared; +use clap::{App, Arg, ArgMatches, SubCommand as ClapSubCommand}; +use failure::Fallible; + +use crate::cmd::{ArgMatchResult, CommandInvocation}; + +#[derive(Debug)] +struct Invocation { + task: String, + description: String, +} + +define_subcommand! { + fn decorate_app<'a>(&self, app: App<'a, 'a>) -> App<'a, 'a> { + app.subcommand( + ClapSubCommand::with_name("prepend").about("add to the start of a task description") + .arg(shared::task_arg()) + .arg( + Arg::with_name("description") + .help("extra task description") + .required(true), + ), + ) + } + fn arg_match<'a>(&self, matches: &ArgMatches<'a>) -> ArgMatchResult { + match matches.subcommand() { + ("prepend", Some(matches)) => ArgMatchResult::Ok(Box::new(Invocation { + task: matches.value_of("task").unwrap().into(), + description: matches.value_of("description").unwrap().into(), + })), + _ => ArgMatchResult::None, + } + } + +} + +subcommand_invocation! { + fn run(&self, command: &CommandInvocation) -> Fallible<()> { + let mut replica = command.get_replica()?; + let task = shared::get_task(&mut replica, &self.task)?; + + let mut task = task.into_mut(&mut replica); + + let new_description = format!("{} {}", self.description.clone(), task.get_description()); + task.set_description(new_description)?; + println!("prepended to task {}", task.get_uuid()); + Ok(()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn parse_command() { + with_subcommand_invocation!( + vec!["task", "prepend", "1", "foo bar"], + |inv: &Invocation| { + assert_eq!(inv.description, "foo bar".to_string()); + } + ); + } +}