use std::io::Write;
use std::process::{Command, Stdio};
const TOOLS: [(&str, &[&str]); 4] = [
("wl-copy", &[]),
("xclip", &["-selection", "clipboard"]),
("xsel", &["--clipboard", "--input"]),
("pbcopy", &[]),
];
pub fn copy(text: &str) -> Result<&'static str, String> {
let (cmd, args) = TOOLS.iter().find(|(cmd, _)| on_path(cmd)).ok_or_else(|| {
"no clipboard tool found (install wl-clipboard, xclip or xsel)".to_string()
})?;
let mut child = Command::new(cmd)
.args(*args)
.stdin(Stdio::piped())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.map_err(|e| format!("{cmd}: {e}"))?;
{
let mut stdin = child.stdin.take().ok_or("clipboard: no stdin")?;
stdin
.write_all(text.as_bytes())
.map_err(|e| format!("{cmd}: {e}"))?;
}
match child.wait() {
Ok(s) if s.success() => Ok(cmd),
Ok(s) => Err(format!("{cmd} exited {}", s.code().unwrap_or(-1))),
Err(e) => Err(format!("{cmd}: {e}")),
}
}
fn on_path(program: &str) -> bool {
std::env::var_os("PATH")
.map(|paths| std::env::split_paths(&paths).any(|dir| dir.join(program).is_file()))
.unwrap_or(false)
}