copypasta_ext/
lib.rs

1//! A clipboard library providing useful extensions for the
2//! [`copypasta`][copypasta] library.
3//!
4//! Here are some of these additions:
5//!
6//! - [`X11ForkClipboardProvider`](https://docs.rs/copypasta-ext/*/copypasta_ext/x11_fork/index.html):
7//!   forks process and sets clipboard on X11, keeps contents after exit
8//! - [`X11BinClipboardProvider`](https://docs.rs/copypasta-ext/*/copypasta_ext/x11_bin/index.html):
9//!   invokes `xclip`/`xsel` to set clipboard on X11, keeps contents after exit
10//! - [`WaylandBinClipboardProvider`](https://docs.rs/copypasta-ext/*/copypasta_ext/wayland_bin/index.html):
11//!   invokes `wl-copy`/`wl-paste` to set clipboard on Wayland
12//! - [`Osc52ClipboardContext`](https://docs.rs/copypasta-ext/*/copypasta_ext/osc52/index.html):
13//!   use OSC 52 escape sequence to set clipboard contents
14//! - [`CombinedClipboardProvider`](https://docs.rs/copypasta-ext/*/copypasta_ext/struct.CombinedClipboardContext.html):
15//!   combine two providers, use different for getting/setting clipboard
16//!
17//! # Example
18//!
19//! Get and set clipboard contents. Tries to select the correct clipboard context at runtime using
20//! `try_context`. Useful if you just want quick access to the clipboard, and if you don't want to
21//! implement any clipboard context selecting logic yourself.
22//!
23//! ```rust,no_run
24//! let mut ctx = copypasta_ext::try_context().expect("failed to get clipboard context");
25//! println!("{:?}", ctx.get_contents());
26//! ctx.set_contents("some string".into()).unwrap();
27//! ```
28//!
29//! Get and set clipboard contents. Keeps contents in X11 clipboard after exit by forking the
30//! process (which normally doesn't work with copypasta's X11ClipboardContext). Falls back to
31//! standard clipboard provider on non X11 platforms. See
32//! [`x11_fork`](https://docs.rs/copypasta-ext/*/copypasta_ext/x11_fork/index.html) module for
33//! details.
34//!
35//! ```rust,no_run
36//! use copypasta_ext::prelude::*;
37//! use copypasta_ext::x11_fork::ClipboardContext;
38//!
39//! let mut ctx = ClipboardContext::new().unwrap();
40//! println!("{:?}", ctx.get_contents());
41//! ctx.set_contents("some string".into()).unwrap();
42//! ```
43//!
44//! Get and set clipboard contents. Keeps contents in X11 clipboard after exit by
45//! invoking `xclip`/`xsel`. Falls back to standard clipboard provider on non X11
46//! platforms. See [`x11_bin`](https://docs.rs/copypasta-ext/*/copypasta_ext/x11_bin/index.html)
47//! module for details.
48//!
49//! ```rust,no_run
50//! use copypasta_ext::prelude::*;
51//! use copypasta_ext::x11_bin::ClipboardContext;
52//!
53//! let mut ctx = ClipboardContext::new().unwrap();
54//! println!("{:?}", ctx.get_contents());
55//! ctx.set_contents("some string".into()).unwrap();
56//! ```
57//!
58//! # Requirements
59//!
60//! - Rust 1.47 or above
61//! - Same requirements as [`copypasta`][copypasta]
62//! - Requirements noted in specific clipboard context modules
63//!
64//! [copypasta]: https://github.com/alacritty/copypasta
65
66mod combined;
67pub mod display;
68#[cfg(feature = "osc52")]
69pub mod osc52;
70#[cfg(all(
71    feature = "wayland-bin",
72    unix,
73    not(any(target_os = "macos", target_os = "android", target_os = "emscripten"))
74))]
75pub mod wayland_bin;
76#[cfg(all(
77    feature = "x11-bin",
78    unix,
79    not(any(target_os = "macos", target_os = "android", target_os = "emscripten"))
80))]
81pub mod x11_bin;
82#[cfg(all(
83    feature = "x11-fork",
84    unix,
85    not(any(target_os = "macos", target_os = "android", target_os = "emscripten"))
86))]
87pub mod x11_fork;
88
89// Expose platform specific contexts
90#[cfg(not(all(
91    feature = "wayland-bin",
92    unix,
93    not(any(target_os = "macos", target_os = "android", target_os = "emscripten"))
94)))]
95pub mod wayland_bin {
96    /// No Wayland binary (`wayland-bin`) support. Fallback to `copypasta::ClipboardContext`.
97    pub type ClipboardContext = copypasta::ClipboardContext;
98}
99#[cfg(not(all(
100    feature = "x11-bin",
101    unix,
102    not(any(target_os = "macos", target_os = "android", target_os = "emscripten"))
103)))]
104pub mod x11_bin {
105    /// No X11 binary (`x11-bin`) support. Fallback to `copypasta::ClipboardContext`.
106    pub type ClipboardContext = copypasta::ClipboardContext;
107}
108#[cfg(not(all(
109    feature = "x11-fork",
110    unix,
111    not(any(target_os = "macos", target_os = "android", target_os = "emscripten"))
112)))]
113pub mod x11_fork {
114    /// No X11 fork (`x11-fork`) support. Fallback to `copypasta::ClipboardContext`.
115    pub type ClipboardContext = copypasta::ClipboardContext;
116}
117
118use std::error::Error;
119
120/// Copypasta result type, for your convenience.
121pub type ClipResult<T> = Result<T, Box<dyn Error + Send + Sync + 'static>>;
122
123// Re-export
124pub use combined::CombinedClipboardContext;
125pub use copypasta;
126
127/// Try to get clipboard context.
128///
129/// This attempts to obtain a clipboard context suitable for the current environment. This checks
130/// at runtime which clipboard contexts are available and which is best suited. If no compatible
131/// clipboard context is avaiable, or if initializing a context failed, `None` is returned.
132///
133/// Note: this function may be used to automatically select an X11 or Wayland clipboard on Unix
134/// systems based on the runtime environment.
135pub fn try_context() -> Option<Box<dyn ClipboardProviderExt>> {
136    display::DisplayServer::select().try_context()
137}
138
139/// Trait prelude.
140///
141/// ```rust
142/// use copypasta_ext::prelude::*;
143/// ```
144pub mod prelude {
145    pub use super::copypasta::ClipboardProvider;
146    pub use super::ClipboardProviderExt;
147}
148
149/// Extension trait for clipboard access
150pub trait ClipboardProviderExt: prelude::ClipboardProvider {
151    /// Get related display server.
152    fn display_server(&self) -> Option<display::DisplayServer>;
153
154    /// If this clipboard provider only has a clipboard lifetime of the current binary, rather than
155    /// forever.
156    fn has_bin_lifetime(&self) -> bool {
157        false
158    }
159}
160
161impl ClipboardProviderExt for copypasta::nop_clipboard::NopClipboardContext {
162    fn display_server(&self) -> Option<display::DisplayServer> {
163        None
164    }
165
166    fn has_bin_lifetime(&self) -> bool {
167        false
168    }
169}
170
171/// X11 clipboards have binary lifetime, not infinite.
172#[cfg(all(
173    unix,
174    not(any(
175        target_os = "macos",
176        target_os = "android",
177        target_os = "ios",
178        target_os = "emscripten"
179    ))
180))]
181impl ClipboardProviderExt for copypasta::x11_clipboard::X11ClipboardContext {
182    fn display_server(&self) -> Option<display::DisplayServer> {
183        Some(display::DisplayServer::X11)
184    }
185
186    fn has_bin_lifetime(&self) -> bool {
187        true
188    }
189}
190
191/// Wayland clipboards have binary lifetime, not infinite.
192#[cfg(all(
193    unix,
194    not(any(
195        target_os = "macos",
196        target_os = "android",
197        target_os = "ios",
198        target_os = "emscripten"
199    ))
200))]
201impl ClipboardProviderExt for copypasta::wayland_clipboard::Clipboard {
202    fn display_server(&self) -> Option<display::DisplayServer> {
203        Some(display::DisplayServer::Wayland)
204    }
205
206    fn has_bin_lifetime(&self) -> bool {
207        true
208    }
209}
210
211#[cfg(windows)]
212impl ClipboardProviderExt for copypasta::windows_clipboard::WindowsClipboardContext {
213    fn display_server(&self) -> Option<display::DisplayServer> {
214        Some(display::DisplayServer::Windows)
215    }
216
217    fn has_bin_lifetime(&self) -> bool {
218        false
219    }
220}
221
222#[cfg(target_os = "macos")]
223impl ClipboardProviderExt for copypasta::osx_clipboard::OSXClipboardContext {
224    fn display_server(&self) -> Option<display::DisplayServer> {
225        Some(display::DisplayServer::MacOs)
226    }
227
228    fn has_bin_lifetime(&self) -> bool {
229        false
230    }
231}