mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
use a generic Write instance for command output
This commit is contained in:
parent
6b550e7516
commit
7d17740ca8
13 changed files with 154 additions and 46 deletions
|
@ -12,6 +12,7 @@ log = "^0.4.11"
|
|||
nom = "*"
|
||||
prettytable-rs = "^0.8.0"
|
||||
textwrap = "0.12.1"
|
||||
termcolor = "1.1.2"
|
||||
|
||||
[dependencies.config]
|
||||
default-features = false
|
||||
|
|
|
@ -1,34 +1,42 @@
|
|||
use crate::argparse::{DescriptionMod, Modification};
|
||||
use failure::Fallible;
|
||||
use taskchampion::{Replica, Status};
|
||||
use termcolor::WriteColor;
|
||||
|
||||
pub(crate) fn execute(replica: &mut Replica, modification: Modification) -> Fallible<()> {
|
||||
pub(crate) fn execute<W: WriteColor>(
|
||||
w: &mut W,
|
||||
replica: &mut Replica,
|
||||
modification: Modification,
|
||||
) -> Fallible<()> {
|
||||
let description = match modification.description {
|
||||
DescriptionMod::Set(ref s) => s.clone(),
|
||||
_ => "(no description)".to_owned(),
|
||||
};
|
||||
let t = replica.new_task(Status::Pending, description).unwrap();
|
||||
println!("added task {}", t.get_uuid());
|
||||
write!(w, "added task {}\n", t.get_uuid())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::invocation::cmd::test::test_replica;
|
||||
use crate::invocation::cmd::test::*;
|
||||
|
||||
#[test]
|
||||
fn test_add() {
|
||||
let mut w = test_writer();
|
||||
let mut replica = test_replica();
|
||||
let modification = Modification {
|
||||
description: DescriptionMod::Set("my description".to_owned()),
|
||||
..Default::default()
|
||||
};
|
||||
execute(&mut replica, modification).unwrap();
|
||||
execute(&mut w, &mut replica, modification).unwrap();
|
||||
|
||||
// check that the task appeared..
|
||||
let task = replica.get_working_set_task(1).unwrap().unwrap();
|
||||
assert_eq!(task.get_description(), "my description");
|
||||
assert_eq!(task.get_status(), Status::Pending);
|
||||
|
||||
assert_eq!(w.into_string(), format!("added task {}\n", task.get_uuid()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
use failure::Fallible;
|
||||
use taskchampion::Replica;
|
||||
use termcolor::WriteColor;
|
||||
|
||||
pub(crate) fn execute(replica: &mut Replica) -> Fallible<()> {
|
||||
pub(crate) fn execute<W: WriteColor>(w: &mut W, replica: &mut Replica) -> Fallible<()> {
|
||||
replica.gc()?;
|
||||
println!("garbage collected.");
|
||||
write!(w, "garbage collected.\n")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::invocation::cmd::test::test_replica;
|
||||
use crate::invocation::cmd::test::*;
|
||||
|
||||
#[test]
|
||||
fn test_gc() {
|
||||
let mut w = test_writer();
|
||||
let mut replica = test_replica();
|
||||
execute(&mut replica).unwrap();
|
||||
// this mostly just needs to not fail!
|
||||
execute(&mut w, &mut replica).unwrap();
|
||||
assert_eq!(&w.into_string(), "garbage collected.\n")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,31 @@
|
|||
use crate::usage::Usage;
|
||||
use failure::Fallible;
|
||||
use std::io;
|
||||
use termcolor::WriteColor;
|
||||
|
||||
pub(crate) fn execute(command_name: String, summary: bool) -> Fallible<()> {
|
||||
pub(crate) fn execute<W: WriteColor>(
|
||||
w: &mut W,
|
||||
command_name: String,
|
||||
summary: bool,
|
||||
) -> Fallible<()> {
|
||||
let usage = Usage::new();
|
||||
usage.write_help(io::stdout(), command_name, summary)?;
|
||||
usage.write_help(w, command_name, summary)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::invocation::cmd::test::*;
|
||||
|
||||
#[test]
|
||||
fn test_summary() {
|
||||
execute("task".to_owned(), true).unwrap();
|
||||
let mut w = test_writer();
|
||||
execute(&mut w, "task".to_owned(), true).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_long() {
|
||||
execute("task".to_owned(), false).unwrap();
|
||||
let mut w = test_writer();
|
||||
execute(&mut w, "task".to_owned(), false).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,14 @@ use crate::table;
|
|||
use failure::Fallible;
|
||||
use prettytable::{cell, row, Table};
|
||||
use taskchampion::Replica;
|
||||
use termcolor::WriteColor;
|
||||
|
||||
pub(crate) fn execute(replica: &mut Replica, filter: Filter, debug: bool) -> Fallible<()> {
|
||||
pub(crate) fn execute<W: WriteColor>(
|
||||
w: &mut W,
|
||||
replica: &mut Replica,
|
||||
filter: Filter,
|
||||
debug: bool,
|
||||
) -> Fallible<()> {
|
||||
for task in filtered_tasks(replica, &filter)? {
|
||||
let uuid = task.get_uuid();
|
||||
|
||||
|
@ -25,7 +31,7 @@ pub(crate) fn execute(replica: &mut Replica, filter: Filter, debug: bool) -> Fal
|
|||
t.add_row(row![b->"Status", task.get_status()]);
|
||||
t.add_row(row![b->"Active", task.is_active()]);
|
||||
}
|
||||
t.printstd();
|
||||
t.print(w)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -34,16 +40,22 @@ pub(crate) fn execute(replica: &mut Replica, filter: Filter, debug: bool) -> Fal
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::invocation::cmd::test::test_replica;
|
||||
use crate::invocation::cmd::test::*;
|
||||
use taskchampion::Status;
|
||||
|
||||
#[test]
|
||||
fn test_info() {
|
||||
let mut w = test_writer();
|
||||
let mut replica = test_replica();
|
||||
replica
|
||||
.new_task(Status::Pending, "my task".to_owned())
|
||||
.unwrap();
|
||||
|
||||
let filter = Filter {
|
||||
..Default::default()
|
||||
};
|
||||
let debug = false;
|
||||
execute(&mut replica, filter, debug).unwrap();
|
||||
// output is to stdout, so this is as much as we can check
|
||||
execute(&mut w, &mut replica, filter, debug).unwrap();
|
||||
assert!(w.into_string().contains("my task"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,13 @@ use crate::table;
|
|||
use failure::Fallible;
|
||||
use prettytable::{cell, row, Table};
|
||||
use taskchampion::Replica;
|
||||
use termcolor::WriteColor;
|
||||
|
||||
pub(crate) fn execute(replica: &mut Replica, report: Report) -> Fallible<()> {
|
||||
pub(crate) fn execute<W: WriteColor>(
|
||||
w: &mut W,
|
||||
replica: &mut Replica,
|
||||
report: Report,
|
||||
) -> Fallible<()> {
|
||||
let mut t = Table::new();
|
||||
t.set_format(table::format());
|
||||
t.set_titles(row![b->"id", b->"act", b->"description"]);
|
||||
|
@ -21,7 +26,7 @@ pub(crate) fn execute(replica: &mut Replica, report: Report) -> Fallible<()> {
|
|||
};
|
||||
t.add_row(row![id, active, task.get_description()]);
|
||||
}
|
||||
t.printstd();
|
||||
t.print(w)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -29,17 +34,23 @@ pub(crate) fn execute(replica: &mut Replica, report: Report) -> Fallible<()> {
|
|||
mod test {
|
||||
use super::*;
|
||||
use crate::argparse::Filter;
|
||||
use crate::invocation::cmd::test::test_replica;
|
||||
use crate::invocation::cmd::test::*;
|
||||
use taskchampion::Status;
|
||||
|
||||
#[test]
|
||||
fn test_list() {
|
||||
let mut w = test_writer();
|
||||
let mut replica = test_replica();
|
||||
replica
|
||||
.new_task(Status::Pending, "my task".to_owned())
|
||||
.unwrap();
|
||||
|
||||
let report = Report {
|
||||
filter: Filter {
|
||||
..Default::default()
|
||||
},
|
||||
};
|
||||
execute(&mut replica, report).unwrap();
|
||||
// output is to stdout, so this is as much as we can check
|
||||
execute(&mut w, &mut replica, report).unwrap();
|
||||
assert!(w.into_string().contains("my task"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@ use crate::argparse::{Filter, Modification};
|
|||
use crate::invocation::{apply_modification, filtered_tasks};
|
||||
use failure::Fallible;
|
||||
use taskchampion::Replica;
|
||||
use termcolor::WriteColor;
|
||||
|
||||
pub(crate) fn execute(
|
||||
pub(crate) fn execute<W: WriteColor>(
|
||||
w: &mut W,
|
||||
replica: &mut Replica,
|
||||
filter: Filter,
|
||||
modification: Modification,
|
||||
|
@ -11,7 +13,7 @@ pub(crate) fn execute(
|
|||
for task in filtered_tasks(replica, &filter)? {
|
||||
let mut task = task.into_mut(replica);
|
||||
|
||||
apply_modification(&mut task, &modification)?;
|
||||
apply_modification(w, &mut task, &modification)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -22,10 +24,12 @@ mod test {
|
|||
use super::*;
|
||||
use crate::argparse::DescriptionMod;
|
||||
use crate::invocation::cmd::test::test_replica;
|
||||
use crate::invocation::cmd::test::*;
|
||||
use taskchampion::Status;
|
||||
|
||||
#[test]
|
||||
fn test_modify() {
|
||||
let mut w = test_writer();
|
||||
let mut replica = test_replica();
|
||||
|
||||
let task = replica
|
||||
|
@ -39,11 +43,16 @@ mod test {
|
|||
description: DescriptionMod::Set("new description".to_owned()),
|
||||
..Default::default()
|
||||
};
|
||||
execute(&mut replica, filter, modification).unwrap();
|
||||
execute(&mut w, &mut replica, filter, modification).unwrap();
|
||||
|
||||
// check that the task appeared..
|
||||
let task = replica.get_task(task.get_uuid()).unwrap().unwrap();
|
||||
assert_eq!(task.get_description(), "new description");
|
||||
assert_eq!(task.get_status(), Status::Pending);
|
||||
|
||||
assert_eq!(
|
||||
w.into_string(),
|
||||
format!("modified task {}\n", task.get_uuid())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,32 @@
|
|||
use failure::Fallible;
|
||||
use taskchampion::{server::Server, Replica};
|
||||
use termcolor::WriteColor;
|
||||
|
||||
pub(crate) fn execute(replica: &mut Replica, server: &mut Box<dyn Server>) -> Fallible<()> {
|
||||
pub(crate) fn execute<W: WriteColor>(
|
||||
w: &mut W,
|
||||
replica: &mut Replica,
|
||||
server: &mut Box<dyn Server>,
|
||||
) -> Fallible<()> {
|
||||
replica.sync(server)?;
|
||||
println!("sync complete.");
|
||||
write!(w, "sync complete.\n")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::invocation::cmd::test::{test_replica, test_server};
|
||||
use crate::invocation::cmd::test::*;
|
||||
use tempdir::TempDir;
|
||||
|
||||
#[test]
|
||||
fn test_add() {
|
||||
let mut w = test_writer();
|
||||
let mut replica = test_replica();
|
||||
let server_dir = TempDir::new("test").unwrap();
|
||||
let mut server = test_server(&server_dir);
|
||||
|
||||
// this just has to not fail -- the details of the actual sync are
|
||||
// tested thoroughly in the taskchampion crate
|
||||
execute(&mut replica, &mut server).unwrap();
|
||||
// Note that the details of the actual sync are tested thoroughly in the taskchampion crate
|
||||
execute(&mut w, &mut replica, &mut server).unwrap();
|
||||
assert_eq!(&w.into_string(), "sync complete.\n")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::io;
|
||||
use taskchampion::{server, taskstorage, Replica, ServerConfig};
|
||||
use tempdir::TempDir;
|
||||
|
||||
|
@ -12,3 +13,38 @@ pub(super) fn test_server(dir: &TempDir) -> Box<dyn server::Server> {
|
|||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub(super) struct TestWriter {
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl TestWriter {
|
||||
pub(super) fn into_string(self) -> String {
|
||||
String::from_utf8(self.data).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for TestWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.data.write(buf)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.data.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl termcolor::WriteColor for TestWriter {
|
||||
fn supports_color(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn set_color(&mut self, _spec: &termcolor::ColorSpec) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn reset(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn test_writer() -> TestWriter {
|
||||
TestWriter { data: vec![] }
|
||||
}
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
use failure::Fallible;
|
||||
use termcolor::{ColorSpec, WriteColor};
|
||||
|
||||
pub(crate) fn execute() -> Fallible<()> {
|
||||
println!("TaskChampion {}", env!("CARGO_PKG_VERSION"));
|
||||
pub(crate) fn execute<W: WriteColor>(w: &mut W) -> Fallible<()> {
|
||||
write!(w, "TaskChampion ")?;
|
||||
w.set_color(ColorSpec::new().set_bold(true))?;
|
||||
write!(w, "{}\n", env!("CARGO_PKG_VERSION"))?;
|
||||
w.reset()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::invocation::cmd::test::*;
|
||||
|
||||
#[test]
|
||||
fn test_version() {
|
||||
execute().unwrap();
|
||||
let mut w = test_writer();
|
||||
execute(&mut w).unwrap();
|
||||
assert!(w.into_string().starts_with("TaskChampion "));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::argparse::{Command, Subcommand};
|
|||
use config::Config;
|
||||
use failure::Fallible;
|
||||
use taskchampion::{server, Replica, ReplicaConfig, ServerConfig, Uuid};
|
||||
use termcolor::{ColorChoice, StandardStream};
|
||||
|
||||
mod cmd;
|
||||
mod filter;
|
||||
|
@ -17,6 +18,8 @@ pub(crate) fn invoke(command: Command, settings: Config) -> Fallible<()> {
|
|||
log::debug!("command: {:?}", command);
|
||||
log::debug!("settings: {:?}", settings);
|
||||
|
||||
let mut w = StandardStream::stdout(ColorChoice::Auto);
|
||||
|
||||
// This function examines the command and breaks out the necessary bits to call one of the
|
||||
// `execute` functions in a submodule of `cmd`.
|
||||
|
||||
|
@ -26,11 +29,11 @@ pub(crate) fn invoke(command: Command, settings: Config) -> Fallible<()> {
|
|||
Command {
|
||||
subcommand: Subcommand::Help { summary },
|
||||
command_name,
|
||||
} => return cmd::help::execute(command_name, summary),
|
||||
} => return cmd::help::execute(&mut w, command_name, summary),
|
||||
Command {
|
||||
subcommand: Subcommand::Version,
|
||||
..
|
||||
} => return cmd::version::execute(),
|
||||
} => return cmd::version::execute(&mut w),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
|
@ -39,7 +42,7 @@ pub(crate) fn invoke(command: Command, settings: Config) -> Fallible<()> {
|
|||
Command {
|
||||
subcommand: Subcommand::Add { modification },
|
||||
..
|
||||
} => return cmd::add::execute(&mut replica, modification),
|
||||
} => return cmd::add::execute(&mut w, &mut replica, modification),
|
||||
|
||||
Command {
|
||||
subcommand:
|
||||
|
@ -48,29 +51,29 @@ pub(crate) fn invoke(command: Command, settings: Config) -> Fallible<()> {
|
|||
modification,
|
||||
},
|
||||
..
|
||||
} => return cmd::modify::execute(&mut replica, filter, modification),
|
||||
} => return cmd::modify::execute(&mut w, &mut replica, filter, modification),
|
||||
|
||||
Command {
|
||||
subcommand: Subcommand::List { report },
|
||||
..
|
||||
} => return cmd::list::execute(&mut replica, report),
|
||||
} => return cmd::list::execute(&mut w, &mut replica, report),
|
||||
|
||||
Command {
|
||||
subcommand: Subcommand::Info { filter, debug },
|
||||
..
|
||||
} => return cmd::info::execute(&mut replica, filter, debug),
|
||||
} => return cmd::info::execute(&mut w, &mut replica, filter, debug),
|
||||
|
||||
Command {
|
||||
subcommand: Subcommand::Gc,
|
||||
..
|
||||
} => return cmd::gc::execute(&mut replica),
|
||||
} => return cmd::gc::execute(&mut w, &mut replica),
|
||||
|
||||
Command {
|
||||
subcommand: Subcommand::Sync,
|
||||
..
|
||||
} => {
|
||||
let mut server = get_server(&settings)?;
|
||||
return cmd::sync::execute(&mut replica, &mut server);
|
||||
return cmd::sync::execute(&mut w, &mut replica, &mut server);
|
||||
}
|
||||
|
||||
// handled in the first match, but here to ensure this match is exhaustive
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
use crate::argparse::{DescriptionMod, Modification};
|
||||
use failure::Fallible;
|
||||
use taskchampion::TaskMut;
|
||||
use termcolor::WriteColor;
|
||||
|
||||
/// Apply the given modification
|
||||
pub(super) fn apply_modification(task: &mut TaskMut, modification: &Modification) -> Fallible<()> {
|
||||
pub(super) fn apply_modification<W: WriteColor>(
|
||||
w: &mut W,
|
||||
task: &mut TaskMut,
|
||||
modification: &Modification,
|
||||
) -> Fallible<()> {
|
||||
match modification.description {
|
||||
DescriptionMod::Set(ref description) => task.set_description(description.clone())?,
|
||||
DescriptionMod::Prepend(ref description) => {
|
||||
|
@ -27,7 +32,7 @@ pub(super) fn apply_modification(task: &mut TaskMut, modification: &Modification
|
|||
task.stop()?;
|
||||
}
|
||||
|
||||
println!("modified task {}", task.get_uuid());
|
||||
write!(w, "modified task {}\n", task.get_uuid())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue