summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMalte Brandy <malte.brandy@maralorn.de>2018-04-28 02:05:39 +0200
committerMalte Brandy <malte.brandy@maralorn.de>2018-04-28 02:05:39 +0200
commit46c9383dc3c205bcf70eba201e711f0b4ea4af71 (patch)
tree60db592908989bc15eeac9be43d864bdada00661 /src
parent804593f7ea7e45f3a04a78a8715410b6ba2201ae (diff)
Make tw module more flexible
As recommended this commit separates the save and query functions into multiple functions, where the user can always supply their own Command. The save process can return a Child struct if wanted. This is a poor mans future for now.
Diffstat (limited to 'src')
-rw-r--r--src/tw.rs64
1 files changed, 42 insertions, 22 deletions
diff --git a/src/tw.rs b/src/tw.rs
index 3ed4f19..ac7f1ed 100644
--- a/src/tw.rs
+++ b/src/tw.rs
@@ -11,48 +11,68 @@
use error::{Result, ResultExt, ErrorKind as EK};
use task::Task;
-use std::process::{Command, Stdio};
+use std::process::{Command, Stdio, Child};
use std::io::Write;
+use std::iter::once;
use import::import;
use serde_json;
/// This will give you all tasks which match the given query in the taskwarrior query syntax.
/// This is not sanitized. Never get the query string from an untrusted user.
pub fn query(query: &str) -> Result<Vec<Task>> {
- let mut cmd = Command::new("task");
- for filter in query.split_whitespace() {
- cmd.arg(filter);
+ let mut cmd = add_query_to_cmd(query, Command::new("task"));
+ cmd.stdout(Stdio::piped());
+ run_query_cmd(cmd)
+}
+
+/// This will take a Command, and append the given query string splited at whitespace followed by
+/// the "export" command to the arguments of the Command.
+pub fn add_query_to_cmd(query: &str, mut cmd: Command) -> Command {
+ for x in query.split_whitespace().chain(once("export")) {
+ cmd.arg(x);
}
- let mut export = cmd.arg("export").stdout(Stdio::piped()).spawn().chain_err(
- || {
- EK::TaskCmdError
- },
- )?;
+ cmd
+}
+
+/// This executes the given Command and trys to convert the Result into a Vec<Task>.
+pub fn run_query_cmd(mut cmd: Command) -> Result<Vec<Task>> {
+ let mut export = cmd.spawn().chain_err(|| EK::TaskCmdError)?;
export.wait().chain_err(|| EK::TaskCmdError)?;
import(export.stdout.chain_err(|| EK::TaskCmdError)?)
}
-/// This will save the given tasks to taskwarrior. Call with `Some(task)` if you just have one
-/// task.
-pub fn save<T>(tasks: T) -> Result<()>
-where
- T: IntoIterator<Item = Task>,
-{
- let tasks: Vec<Task> = tasks.into_iter().collect();
+/// This function runs the given Command, pipes the tasks as JSON to it and returns a handle to the child process.
+pub fn save_to_cmd<'a>(tasks: Vec<&'a Task>, mut cmd: Command) -> Result<Child> {
let input_buffer = serde_json::to_string(&tasks).chain_err(
|| EK::SerializeError,
)?;
- let mut import = Command::new("task")
- .arg("import")
- .stdin(Stdio::piped())
- .spawn()
- .chain_err(|| EK::TaskCmdError)?;
+ let mut import = cmd.spawn().chain_err(|| EK::TaskCmdError)?;
import
.stdin
.as_mut()
.chain_err(|| EK::TaskCmdError)?
.write_all(input_buffer.as_bytes())
.chain_err(|| EK::TaskCmdError)?;
- import.wait().chain_err(|| EK::TaskCmdError)?;
+ Ok(import)
+}
+
+/// This will save the given tasks to taskwarrior. Call with `Some(&task)` if you just have one
+/// task.
+/// This will block until the save was successful.
+pub fn save<'a, T>(tasks: T) -> Result<()>
+where
+ T: IntoIterator<Item = &'a Task>,
+{
+ save_async(tasks)?.wait().chain_err(|| EK::TaskCmdError)?;
Ok(())
}
+
+/// This function returns the handle to a child process which saves the given tasks.
+pub fn save_async<'a, T>(tasks: T) -> Result<Child>
+where
+ T: IntoIterator<Item = &'a Task>,
+{
+ let mut cmd = Command::new("task");
+ cmd.arg("import").stdin(Stdio::piped());
+ save_to_cmd(tasks.into_iter().collect(), cmd)
+}