Merge pull request #45 from djmitche/issue30

add an 'info' subcommand
This commit is contained in:
Dustin J. Mitchell 2020-11-24 11:42:34 -05:00 committed by GitHub
commit d84c156782
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 1 deletions

55
cli/src/cmd/info.rs Normal file
View file

@ -0,0 +1,55 @@
use crate::table;
use clap::{App, ArgMatches, SubCommand as ClapSubCommand};
use failure::Fallible;
use prettytable::{cell, row, Table};
use crate::cmd::{shared, ArgMatchResult, CommandInvocation};
#[derive(Debug)]
struct Invocation {
task: String,
}
define_subcommand! {
fn decorate_app<'a>(&self, app: App<'a, 'a>) -> App<'a, 'a> {
app.subcommand(
ClapSubCommand::with_name("info")
.about("info on the given task")
.arg(shared::task_arg()))
}
fn arg_match<'a>(&self, matches: &ArgMatches<'a>) -> ArgMatchResult {
match matches.subcommand() {
("info", Some(matches)) => ArgMatchResult::Ok(Box::new(Invocation {
task: matches.value_of("task").unwrap().into(),
})),
_ => ArgMatchResult::None,
}
}
}
subcommand_invocation! {
fn run(&self, command: &CommandInvocation) -> Fallible<()> {
let task = shared::get_task(&mut command.get_replica(), &self.task)?;
let mut t = Table::new();
t.set_format(table::format());
t.add_row(row![b->"Uuid", task.get_uuid()]);
t.add_row(row![b->"Description", task.get_description()]);
t.add_row(row![b->"Status", task.get_status()]);
t.printstd();
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn parse_command() {
with_subcommand_invocation!(vec!["task", "info", "1"], |inv: &Invocation| {
assert_eq!(inv.task, "1".to_string());
});
}
}

View file

@ -5,15 +5,23 @@ use taskchampion::{taskstorage, Replica};
#[macro_use]
mod macros;
mod shared;
mod add;
mod gc;
mod info;
mod list;
mod pending;
/// Get a list of all subcommands in this crate
pub(crate) fn subcommands() -> Vec<Box<dyn SubCommand>> {
vec![add::cmd(), gc::cmd(), list::cmd(), pending::cmd()]
vec![
add::cmd(),
gc::cmd(),
list::cmd(),
pending::cmd(),
info::cmd(),
]
}
/// The result of a [`crate::cmd::SubCommand::arg_match`] call

38
cli/src/cmd/shared.rs Normal file
View file

@ -0,0 +1,38 @@
use clap::Arg;
use failure::{format_err, Fallible};
use taskchampion::{Replica, Task};
use uuid::Uuid;
pub(super) fn task_arg<'a>() -> Arg<'a, 'a> {
Arg::with_name("task")
.help("task id or uuid")
.required(true)
}
pub(super) fn get_task<S: AsRef<str>>(replica: &mut Replica, task_arg: S) -> Fallible<Task> {
let task_arg = task_arg.as_ref();
// first try treating task as a working-set reference
match task_arg.parse::<u64>() {
Ok(i) => {
let mut working_set = replica.working_set().unwrap();
if i > 0 && i < working_set.len() as u64 {
if let Some(task) = working_set[i as usize].take() {
return Ok(task);
}
}
}
Err(_) => {}
}
match Uuid::parse_str(task_arg) {
Ok(uuid) => {
if let Some(task) = replica.get_task(&uuid)? {
return Ok(task);
}
}
Err(_) => {}
}
Err(format_err!("Cannot interpret {:?} as a task", task_arg))
}

View file

@ -68,6 +68,16 @@ impl Status {
Status::Deleted => "D",
}
}
/// Get the full-name value for this status to use in the TaskMap.
pub fn to_string(&self) -> &str {
// TODO: should be impl Display
match self {
Status::Pending => "Pending",
Status::Completed => "Completed",
Status::Deleted => "Deleted",
}
}
}
#[derive(Debug, PartialEq)]