use crate::jos;
use which::which;
pub fn check() {
if !jos::is_linux() && !jos::is_windows() {
let platform = jos::get_operating_system_name();
panic!("Error: unknown platform {}", platform);
}
if jos::is_windows() {
return;
}
let command = "xsel";
let result = which(command);
if result.is_err() {
panic!("Error: the command {} was not found", command);
}
}
pub fn set_text(text: &str) -> Result<(), &'static str> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
set_text_windows(text)?;
return Ok(());
} else if #[cfg(unix)] {
let result = set_text_linux(text);
return match result {
Ok(_) => Ok(()),
Err(_) => Err("Error: cannot write to clipboard"),
};
} else {
let platform = jos::get_operating_system_name();
panic!("Error: unknown platform {}", platform);
}
}
}
pub fn get_text() -> Result<String, &'static str> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
let text = get_text_windows()?;
Ok(text)
} else if #[cfg(unix)] {
let result = get_text_linux();
match result {
Ok(text) => Ok(text),
Err(_) => Err("Error: cannot read from clipboard"),
}
} else {
let platform = jos::get_operating_system_name();
panic!("Error: unknown platform {}", platform);
}
}
}
#[cfg(windows)]
use clipboard_win::formats::Unicode;
#[cfg(windows)]
use clipboard_win::{Clipboard, Getter, Setter};
#[cfg(windows)]
fn set_text_windows(text: &str) -> Result<(), &'static str> {
let _clip = Clipboard::new_attempts(10).expect("Open clipboard");
let result = Unicode.write_clipboard(&text);
match result {
Ok(_) => Ok(()),
_ => Err("cannot write to clipboard"),
}
}
#[cfg(windows)]
fn get_text_windows() -> Result<String, &'static str> {
let _clip = Clipboard::new_attempts(10).expect("Open clipboard");
let mut output = String::new();
let result = Unicode.read_clipboard(&mut output);
match result {
Ok(_) => Ok(output),
_ => Err("cannot read clipboard"),
}
}
#[cfg(unix)]
use std::error::Error;
#[cfg(unix)]
use std::process::{Command, Stdio};
#[cfg(unix)]
fn set_text_linux(text: &str) -> Result<(), Box<dyn Error>> {
set_text_with_xsel(text, "-pi")?; set_text_with_xsel(text, "-bi")?; Ok(())
}
#[cfg(unix)]
fn set_text_with_xsel(text: &str, which_clipboard: &str) -> Result<(), Box<dyn Error>> {
let mut echo_output_child = Command::new("echo")
.arg("-n")
.arg(text)
.stdout(Stdio::piped())
.spawn()?;
echo_output_child.wait()?;
if let Some(echo_output) = echo_output_child.stdout.take() {
let mut xsel_output_child = Command::new("xsel")
.arg(which_clipboard) .stdin(echo_output)
.spawn()?;
xsel_output_child.wait()?;
}
Ok(())
}
#[cfg(unix)]
fn get_text_linux() -> Result<String, Box<dyn Error>> {
let output_child = Command::new("xsel")
.arg("-bo")
.stdout(Stdio::piped())
.spawn()?;
let prg_stdout = output_child.wait_with_output()?;
Ok(String::from_utf8(prg_stdout.stdout)?)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_test() {
assert_eq!(check(), ());
}
#[test]
fn set_text_and_get_text_test() {
check();
let backup = get_text().unwrap();
for &s in &["", "a", "aa", "hello", "rust is cool", "Éva"] {
set_text(s).unwrap();
assert_eq!(get_text().unwrap(), s);
}
set_text(&backup).unwrap();
assert_eq!(get_text().unwrap(), backup);
}
}