1use crate::jos;
4use which::which;
5
6pub fn check() {
24 if !jos::is_linux() && !jos::is_windows() {
25 let platform = jos::get_operating_system_name();
26 panic!("Error: unknown platform {}", platform);
27 }
28 if jos::is_windows() {
31 return;
32 }
33 let command = "xsel";
35 let result = which(command);
36 if result.is_err() {
37 panic!("Error: the command {} was not found", command);
38 }
39}
40
41pub fn set_text(text: &str) -> Result<(), &'static str> {
68 cfg_if::cfg_if! {
69 if #[cfg(windows)] {
70 set_text_windows(text)?;
71 return Ok(());
72 } else if #[cfg(unix)] {
73 let result = set_text_linux(text);
74 return match result {
75 Ok(_) => Ok(()),
76 Err(_) => Err("Error: cannot write to clipboard"),
77 };
78 } else {
79 let platform = jos::get_operating_system_name();
80 panic!("Error: unknown platform {}", platform);
81 }
82 }
83}
84
85pub fn get_text() -> Result<String, &'static str> {
110 cfg_if::cfg_if! {
111 if #[cfg(windows)] {
112 let text = get_text_windows()?;
113 Ok(text)
114 } else if #[cfg(unix)] {
115 let result = get_text_linux();
116 match result {
117 Ok(text) => Ok(text),
118 Err(_) => Err("Error: cannot read from clipboard"),
119 }
120 } else {
121 let platform = jos::get_operating_system_name();
122 panic!("Error: unknown platform {}", platform);
123 }
124 }
125}
126
127#[cfg(windows)]
132use clipboard_win::formats::Unicode;
133#[cfg(windows)]
134use clipboard_win::{Clipboard, Getter, Setter};
135
136#[cfg(windows)]
137fn set_text_windows(text: &str) -> Result<(), &'static str> {
138 let _clip = Clipboard::new_attempts(10).expect("Open clipboard");
139 let result = Unicode.write_clipboard(&text);
140 match result {
141 Ok(_) => Ok(()),
142 _ => Err("cannot write to clipboard"),
143 }
144}
145
146#[cfg(windows)]
147fn get_text_windows() -> Result<String, &'static str> {
148 let _clip = Clipboard::new_attempts(10).expect("Open clipboard");
149 let mut output = String::new();
150 let result = Unicode.read_clipboard(&mut output);
151 match result {
152 Ok(_) => Ok(output),
153 _ => Err("cannot read clipboard"),
154 }
155}
156
157#[cfg(unix)]
162use std::error::Error;
163#[cfg(unix)]
164use std::process::{Command, Stdio};
165
166#[cfg(unix)]
167fn set_text_linux(text: &str) -> Result<(), Box<dyn Error>> {
168 set_text_with_xsel(text, "-pi")?; set_text_with_xsel(text, "-bi")?; Ok(())
171}
172
173#[cfg(unix)]
174fn set_text_with_xsel(text: &str, which_clipboard: &str) -> Result<(), Box<dyn Error>> {
175 let mut echo_output_child = Command::new("echo")
176 .arg("-n")
177 .arg(text)
178 .stdout(Stdio::piped())
179 .spawn()?;
180
181 echo_output_child.wait()?;
182
183 if let Some(echo_output) = echo_output_child.stdout.take() {
184 let mut xsel_output_child = Command::new("xsel")
185 .arg(which_clipboard) .stdin(echo_output)
187 .spawn()?;
188
189 xsel_output_child.wait()?;
190 }
191
192 Ok(())
193}
194
195#[cfg(unix)]
196fn get_text_linux() -> Result<String, Box<dyn Error>> {
197 let output_child = Command::new("xsel")
198 .arg("-bo")
199 .stdout(Stdio::piped())
200 .spawn()?;
201
202 let prg_stdout = output_child.wait_with_output()?;
203 Ok(String::from_utf8(prg_stdout.stdout)?)
204}
205
206#[cfg(test)]
209mod tests {
210 use super::*;
211
212 #[test]
213 fn check_test() {
214 assert_eq!(check(), ());
215 }
216
217 #[test]
218 fn set_text_and_get_text_test() {
219 check();
220 let backup = get_text().unwrap();
221 for &s in &["", "a", "aa", "hello", "rust is cool", "Éva"] {
223 set_text(s).unwrap();
224 assert_eq!(get_text().unwrap(), s);
225 }
226 set_text(&backup).unwrap();
228 assert_eq!(get_text().unwrap(), backup);
229 }
230}