use std::{ffi::OsStr, io::{self, BufRead}, process::{Child, Command, Stdio}};
use anyhow::{anyhow, Result};
pub fn output<I, S>(args: I) -> Result<String>
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
let args: Vec<S> = args.into_iter().collect();
let output = Command::new(&args[0])
.args(&args[1..])
.output()?;
let outerr = String::from_utf8_lossy(&output.stderr);
if !outerr.is_empty() {
if let Some(e) = outerr.strip_suffix("\n") {
return Err(anyhow!("{e}"));
} else {
return Err(anyhow!("{outerr}"));
}
}
let out = String::from_utf8_lossy(&output.stdout);
if let Some(o) = out.strip_suffix("\n") {
return Ok(o.to_string());
}
Ok(out.to_string())
}
pub fn spawn<I, S>(args: I) -> Result<Vec<String>>
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
let args: Vec<S> = args.into_iter().collect();
let mut child: Child = Command::new(&args[0])
.args(&args[1..])
.stdout(Stdio::piped()) .spawn()?;
let stdout = child.stdout.take().ok_or_else(|| anyhow!("Could not capture standard output"))?;
let reader = io::BufReader::new(stdout);
let mut result = Vec::new();
for line in reader.lines() {
let line = line?;
println!("{}", line);
result.push(line);
}
let _ = child.wait()?;
Ok(result)
}