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}