mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
Implement copypasta::Store for macOS pasteboard
Only works with strings, currently.
This commit is contained in:
parent
6e708d2119
commit
7cdf06e2be
2 changed files with 98 additions and 7 deletions
|
@ -32,10 +32,12 @@ pub trait Load : Sized {
|
|||
/// order to load the contents from other applications.
|
||||
pub trait Store : Load {
|
||||
/// Sets the primary clipboard contents
|
||||
fn store_primary(&mut self, contents: String) -> Result<(), Self::Err>;
|
||||
fn store_primary<S>(&mut self, contents: S) -> Result<(), Self::Err>
|
||||
where S: Into<String>;
|
||||
|
||||
/// Sets the secondary clipboard contents
|
||||
fn store_selection(&mut self, contents: String) -> Result<(), Self::Err>;
|
||||
fn store_selection<S>(&mut self, contents: S) -> Result<(), Self::Err>
|
||||
where S: Into<String>;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
|
|
@ -34,6 +34,10 @@ mod ns {
|
|||
ReadObjectsForClasses,
|
||||
}
|
||||
|
||||
/// Errors from writing strings to the pasteboard
|
||||
#[derive(Debug)]
|
||||
pub struct WriteStringError;
|
||||
|
||||
/// A trait for reading contents from the pasteboard
|
||||
///
|
||||
/// This is intended to reflect the underlying objective C API
|
||||
|
@ -43,6 +47,12 @@ mod ns {
|
|||
fn read_object(&self) -> Result<T, Self::Err>;
|
||||
}
|
||||
|
||||
/// A trait for writing contents to the pasteboard
|
||||
pub trait PasteboardWriteObject<T> {
|
||||
type Err;
|
||||
fn write_object(&mut self, T) -> Result<(), Self::Err>;
|
||||
}
|
||||
|
||||
impl PasteboardReadObject<String> for Pasteboard {
|
||||
type Err = ReadStringError;
|
||||
fn read_object(&self) -> Result<String, ReadStringError> {
|
||||
|
@ -113,6 +123,40 @@ mod ns {
|
|||
}
|
||||
}
|
||||
|
||||
impl PasteboardWriteObject<String> for Pasteboard {
|
||||
type Err = WriteStringError;
|
||||
|
||||
fn write_object(&mut self, object: String) -> Result<(), Self::Err> {
|
||||
let objects = NSArray::from_vec(vec![NSString::from_str(&object)]);
|
||||
|
||||
self.clear_contents();
|
||||
|
||||
// The writeObjects method returns true in case of success, and
|
||||
// false otherwise.
|
||||
let ok: bool = unsafe {
|
||||
msg_send![self.0, writeObjects:objects]
|
||||
};
|
||||
|
||||
if ok {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(WriteStringError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::error::Error for WriteStringError {
|
||||
fn description(&self) -> &str {
|
||||
"Failed writing string to the NSPasteboard (writeContents returned false)"
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for WriteStringError {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
f.write_str(::std::error::Error::description(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::error::Error for ReadStringError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
|
@ -171,6 +215,17 @@ mod ns {
|
|||
|
||||
Ok(Pasteboard(id))
|
||||
}
|
||||
|
||||
/// Clears the existing contents of the pasteboard, preparing it for new
|
||||
/// contents.
|
||||
///
|
||||
/// This is the first step in providing data on the pasteboard. The
|
||||
/// return value is the change count of the pasteboard
|
||||
pub fn clear_contents(&mut self) -> usize {
|
||||
unsafe {
|
||||
msg_send![self.0, clearContents]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,6 +233,7 @@ mod ns {
|
|||
pub enum Error {
|
||||
CreatePasteboard(ns::NewPasteboardError),
|
||||
ReadString(ns::ReadStringError),
|
||||
WriteString(ns::WriteStringError),
|
||||
}
|
||||
|
||||
|
||||
|
@ -186,6 +242,7 @@ impl ::std::error::Error for Error {
|
|||
match *self {
|
||||
Error::CreatePasteboard(ref err) => Some(err),
|
||||
Error::ReadString(ref err) => Some(err),
|
||||
Error::WriteString(ref err) => Some(err),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,6 +250,7 @@ impl ::std::error::Error for Error {
|
|||
match *self {
|
||||
Error::CreatePasteboard(ref _err) => "Failed to create pasteboard",
|
||||
Error::ReadString(ref _err) => "Failed to read string from pasteboard",
|
||||
Error::WriteString(ref _err) => "Failed to write string to pasteboard",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,6 +264,9 @@ impl ::std::fmt::Display for Error {
|
|||
Error::ReadString(ref err) => {
|
||||
write!(f, "Failed to read string from pasteboard: {}", err)
|
||||
},
|
||||
Error::WriteString(ref err) => {
|
||||
write!(f, "Failed to write string to pasteboard: {}", err)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -222,6 +283,12 @@ impl From<ns::ReadStringError> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<ns::WriteStringError> for Error {
|
||||
fn from(val: ns::WriteStringError) -> Error {
|
||||
Error::WriteString(val)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Clipboard(ns::Pasteboard);
|
||||
|
||||
impl super::Load for Clipboard {
|
||||
|
@ -232,19 +299,41 @@ impl super::Load for Clipboard {
|
|||
}
|
||||
|
||||
fn load_primary(&self) -> Result<String, Self::Err> {
|
||||
self::ns::PasteboardReadObject::<String>::read_object(&self.0)
|
||||
use self::ns::PasteboardReadObject;
|
||||
|
||||
self.0.read_object()
|
||||
.map_err(::std::convert::From::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl super::Store for Clipboard {
|
||||
fn store_primary<S>(&mut self, contents: S) -> Result<(), Self::Err>
|
||||
where S: Into<String>
|
||||
{
|
||||
use self::ns::PasteboardWriteObject;
|
||||
|
||||
self.0.write_object(contents.into())
|
||||
.map_err(::std::convert::From::from)
|
||||
}
|
||||
|
||||
fn store_selection<S>(&mut self, _contents: S) -> Result<(), Self::Err>
|
||||
where S: Into<String>
|
||||
{
|
||||
// No such thing on macOS
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Clipboard;
|
||||
use ::Load;
|
||||
use ::{Load, Store};
|
||||
|
||||
#[test]
|
||||
fn create_clipboard_and_load_contents() {
|
||||
let clipboard = Clipboard::new().unwrap();
|
||||
println!("{:?}", clipboard.load_primary());
|
||||
fn create_clipboard_save_load_contents() {
|
||||
let mut clipboard = Clipboard::new().unwrap();
|
||||
clipboard.store_primary("arst").unwrap();
|
||||
let loaded = clipboard.load_primary().unwrap();
|
||||
assert_eq!("arst", loaded);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue