From f1336ee1c74c8e3d324ff7b32b562a64046df5ce Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Thu, 29 Dec 2016 17:57:50 -0500 Subject: [PATCH] Implement clipboard store for x11 with xclip --- copypasta/src/x11.rs | 74 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/copypasta/src/x11.rs b/copypasta/src/x11.rs index 8d88c79e..3f64453c 100644 --- a/copypasta/src/x11.rs +++ b/copypasta/src/x11.rs @@ -10,8 +10,9 @@ use std::io; use std::process::{Output, Command}; use std::string::FromUtf8Error; +use std::ffi::OsStr; -use super::Load; +use super::{Load, Store}; /// The x11 clipboard pub struct Clipboard; @@ -87,12 +88,79 @@ impl Load for Clipboard { } } +impl Store for Clipboard { + /// Sets the primary clipboard contents + #[inline] + fn store_primary(&mut self, contents: S) -> Result<(), Self::Err> + where S: Into + { + self.store(contents, &["-i", "-selection", "clipboard"]) + } + + /// Sets the secondary clipboard contents + #[inline] + fn store_selection(&mut self, contents: S) -> Result<(), Self::Err> + where S: Into + { + self.store(contents, &["-i"]) + } +} + impl Clipboard { fn process_xclip_output(output: Output) -> Result { if output.status.success() { - String::from_utf8(output.stdout).map_err(::std::convert::From::from) + String::from_utf8(output.stdout) + .map_err(::std::convert::From::from) } else { - String::from_utf8(output.stderr).map_err(::std::convert::From::from) + String::from_utf8(output.stderr) + .map_err(::std::convert::From::from) + } + } + + fn store(&mut self, contents: C, args: &[S]) -> Result<(), Error> + where C: Into, + S: AsRef, + { + use std::io::Write; + use std::process::{Command, Stdio}; + + let contents = contents.into(); + let mut child = Command::new("xclip") + .args(args) + .stdin(Stdio::piped()) + .spawn()?; + + if let Some(mut stdin) = child.stdin.as_mut() { + stdin.write_all(contents.as_bytes())?; + } + + // Return error if didn't exit cleanly + let exit_status = child.wait()?; + if exit_status.success() { + Ok(()) + } else { + Err(Error::Xclip("xclip returned non-zero exit code".into())) } } } + +#[cfg(test)] +mod tests { + use super::Clipboard; + use ::{Load, Store}; + + #[test] + fn clipboard_works() { + let mut clipboard = Clipboard::new().expect("create clipboard"); + let arst = "arst"; + let oien = "oien"; + clipboard.store_primary(arst).expect("store selection"); + clipboard.store_selection(oien).expect("store selection"); + + let selection = clipboard.load_selection().expect("load selection"); + let primary = clipboard.load_primary().expect("load selection"); + + assert_eq!(arst, primary); + assert_eq!(oien, selection); + } +}