rs_peekaboo 0.3.4

Rust-native cross-platform computer-use CLI and library
Documentation
use crate::PeekabooError;
use crate::Result;
use crate::models::ShellOutput;
use std::ffi::OsStr;
use std::io::Write;
use std::path::Path;
use std::process::{Command, Stdio};

#[derive(Clone, Debug)]
pub struct ProcessOutput {
    pub stdout: String,
}

pub fn run(program: &str, args: &[&str], input: Option<&str>) -> Result<ProcessOutput> {
    let output = run_status(program, args, input, None)?;
    if !output.success {
        return Err(PeekabooError::CommandFailed {
            program: program.to_string(),
            status: output.status,
            stderr: output.stderr,
        });
    }
    Ok(ProcessOutput {
        stdout: output.stdout,
    })
}

pub fn run_status(
    program: &str,
    args: &[&str],
    input: Option<&str>,
    cwd: Option<&Path>,
) -> Result<ShellOutput> {
    let mut command = Command::new(program);
    command.args(args.iter().map(OsStr::new));
    if let Some(cwd) = cwd {
        command.current_dir(cwd);
    }
    command.stdout(Stdio::piped()).stderr(Stdio::piped());
    if input.is_some() {
        command.stdin(Stdio::piped());
    }
    let mut child = command.spawn()?;
    if let Some(input) = input
        && let Some(mut stdin) = child.stdin.take()
    {
        stdin.write_all(input.as_bytes())?;
    }
    let output = child.wait_with_output()?;
    let status = output.status.code().unwrap_or(-1);
    let stdout = String::from_utf8_lossy(&output.stdout).into_owned();
    let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
    Ok(ShellOutput {
        stdout,
        stderr,
        status,
        success: output.status.success(),
    })
}

pub fn probe(program: &str, args: &[&str]) -> bool {
    run(program, args, None).is_ok()
}

pub fn shell_program() -> &'static str {
    if cfg!(target_os = "windows") {
        "cmd"
    } else {
        "/bin/sh"
    }
}

pub fn shell_args(command: &str) -> Vec<String> {
    if cfg!(target_os = "windows") {
        vec!["/C".to_string(), command.to_string()]
    } else {
        vec!["-c".to_string(), command.to_string()]
    }
}