summaryrefslogtreecommitdiffstats
path: root/copypasta
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-12-29 17:57:50 -0500
committerJoe Wilm <joe@jwilm.com>2016-12-29 17:57:50 -0500
commitf1336ee1c74c8e3d324ff7b32b562a64046df5ce (patch)
tree4439d806d42bc2a091488a79b48fdaf04c58a803 /copypasta
parent818a2f6161a718f8f9762a972a5c42e756ccff51 (diff)
Implement clipboard store for x11 with xclip
Diffstat (limited to 'copypasta')
-rw-r--r--copypasta/src/x11.rs74
1 files 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<S>(&mut self, contents: S) -> Result<(), Self::Err>
+ where S: Into<String>
+ {
+ self.store(contents, &["-i", "-selection", "clipboard"])
+ }
+
+ /// Sets the secondary clipboard contents
+ #[inline]
+ fn store_selection<S>(&mut self, contents: S) -> Result<(), Self::Err>
+ where S: Into<String>
+ {
+ self.store(contents, &["-i"])
+ }
+}
+
impl Clipboard {
fn process_xclip_output(output: Output) -> Result<String, Error> {
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<C, S>(&mut self, contents: C, args: &[S]) -> Result<(), Error>
+ where C: Into<String>,
+ S: AsRef<OsStr>,
+ {
+ 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);
}
}