1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
/*!
**terminal-clipboard** is a cross-platform clipboard library focused on strings copying and pasting for terminal applications:
* it's tested on linux, windows and Android (Termux)
* it doesn't handle other types of objects than strings
* it doesn't handle non UTF8 strings
# Usage
```
terminal_clipboard::set_string("test").unwrap();
assert_eq!("test", terminal_clipboard::get_string().unwrap());
```
# Supported platforms
The implementation is currently chosen from the "target_os" part of the compilation target.
## Android (Termux)
The current implementation will defer to Termux API facilities to access the Android clipboard, and won't work if the Termux API isn't available at runtime.
If you know of solutions to access the Android clipboard without Termux, please open an issue.
## Linux
If a unix-like target is detected and the "termux" feature isn't enabled, terminal-clipboard uses the [x11-clipboard](https://crates.io/crates/x11-clipboard) crate.
You'll need to have `xorg-dev` and `libxcb-composite0-dev` to compile.
On Debian and Ubuntu you can install them with
```bash
sudo apt install xorg-dev libxcb-composite0-dev
```
## Windows
If the compilation target is "windows", terminal-clipboard uses the [clipboard-win](https://crates.io/crates/clipboard-win) crate. If you're only interested in this platform, you should use this crate directly.
```
use terminal_clipboard;
terminal_clipboard::set_string("test").unwrap();
assert_eq!("test", terminal_clipboard::get_string().unwrap());
```
*/
mod clipboard;
mod errors;
mod local;
pub use {
clipboard::Clipboard,
errors::ClipboardError,
local::LocalClipboard,
};
#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "macos")]
pub use macos::MacClipboard;
#[cfg(target_os = "windows")]
mod win;
#[cfg(target_os = "windows")]
pub use win::WinClipboard;
#[cfg(target_os = "android")]
mod termux;
#[cfg(target_os = "android")]
pub use termux::TermuxClipboard;
#[cfg(not(any(target_os="windows",target_os="android",target_os="macos")))]
mod x11;
#[cfg(not(any(target_os="windows",target_os="android",target_os="macos")))]
pub use x11::X11Clipboard;
use {
once_cell::sync::Lazy,
std::sync::Mutex,
};
static CLIPBOARD: Lazy<Mutex<Box<dyn Clipboard + Send>>> = Lazy::new(|| Mutex::new(new_clipboard()));
/// Build a new clipboard.
///
/// It's recommended to not use this directly but the get_string
/// and set_string global functions instead, as those functions
/// ensure the lazy static initialization of the clipboard.
pub fn new_clipboard() -> Box<dyn Clipboard + Send> {
#[cfg(target_os = "windows")]
{
// To my knowledge
return Box::new(WinClipboard::new());
}
#[cfg(target_os = "macos")]
{
// only use MacClipboard after it is verified.
if let Ok(clipboard) = MacClipboard::verified() {
return Box::new(clipboard);
}
}
#[cfg(target_os = "android")]
{
// we'll use the Termux clipboard, but only after having
// checked it works. It fails for example when the
// Termux API isn't available on the device
if let Ok(clipboard) =TermuxClipboard::verified() {
return Box::new(clipboard);
}
}
#[cfg(not(any(target_os="windows",target_os="android",target_os="macos")))]
{
// we'll use the X11 clipboard, but only after having
// checked it works. As nobody understants X11 anyway,
// I won't try to pretend I know when it works and when
// it doesn't
if let Ok(clipboard) = X11Clipboard::verified() {
return Box::new(clipboard);
}
}
// when everything else failed, use a local clipboard
#[allow(unreachable_code)]
Box::new(LocalClipboard::new())
}
/// Return the type of the Clipboard, for example
/// "X11", "Windows", "Local", or "Termux"
pub fn get_type() -> &'static str {
CLIPBOARD.lock().unwrap().get_type()
}
/// Return the content of the clipboard
pub fn get_string() -> Result<String, ClipboardError> {
CLIPBOARD.lock().unwrap().get_string()
}
/// Fill the clipboard with the given string
pub fn set_string<S: AsRef<str>>(s: S) -> Result<(), ClipboardError> {
CLIPBOARD.lock().unwrap().set_string(s.as_ref())
}
// Those tests are the same than doc tests but they must be
// kept separate because cargo-cross doesn't run doc tests
// (see https://github.com/rust-embedded/cross/issues/225)
#[cfg(test)]
mod clipboard_tests {
use super::*;
#[test]
fn write_read() {
let test = "TEST";
set_string(test).unwrap();
assert_eq!(test, get_string().unwrap());
}
}