edtui/clipboard.rs
1//! The editors clipboard
2//!
3//! ## Default clipboard
4//!
5//! `EdTUI` uses the arboard clipboard by default, which enables copy and paste
6//! operations between the system clipboard and the editor. However, if a lighter
7//! clipboard is desired, the "arboard" function flag can be deactivated. In this
8//! case, the internal clipboard is used, which only supports copying and pasting
9//! within the editor.
10//!
11//! ## Example: A custom global clipboard
12//!
13//! `EdTUI` allows you to set a custom clipboard. This is useful if you want to
14//! define a global clipboard for example:
15//!
16//!```ignore
17//! use once_cell::sync::Lazy;
18//! use std::sync::Mutex;
19//!
20//! static CLIPBOARD: Lazy<GlobalClipboard> = Lazy::new(|| GlobalClipboard::new());
21//!
22//! struct GlobalClipboard(Mutex<Clipboard>);
23//!
24//! impl GlobalClipboard {
25//! pub fn new() -> Self {
26//! Self(Mutex::new(arboard::Clipboard::new().unwrap()))
27//! }
28//! }
29//!
30//! impl ClipboardTrait for &GlobalClipboard {
31//! fn set_text(&mut self, text: String) {
32//! if let Ok(mut clipboard) = self.0.lock() {
33//! let _ = clipboard.set_text(text);
34//! }
35//! }
36//!
37//! fn get_text(&mut self) -> String {
38//! if let Ok(mut clipboard) = self.0.lock() {
39//! return clipboard.get_text().unwrap_or_default();
40//! }
41//! String::new()
42//! }
43//! }
44//!
45//! let mut state = EditorState::default();
46//! state.set_clipboard(Lazy::force(&CLIPBOARD));
47//!```
48#[cfg(feature = "arboard")]
49mod arboard;
50
51use std::{cell::RefCell, rc::Rc};
52
53/// Trait defining clipboard operations.
54pub trait ClipboardTrait {
55 /// Sets text to the clipboard.
56 fn set_text(&mut self, text: String);
57
58 /// Retrieves text from the clipboard.
59 fn get_text(&mut self) -> String;
60}
61
62/// A clipboard for the editor.
63///
64/// This struct can hold any type that implements [`ClipboardTrait`].
65#[derive(Clone)]
66pub struct Clipboard(Rc<RefCell<dyn ClipboardTrait>>);
67
68impl Clipboard {
69 /// Creates a new `Clipboard` instance with a provided clipboard implementation.
70 ///
71 /// ## Example
72 ///
73 /// ```
74 /// use edtui::clipboard::{Clipboard, ClipboardTrait};
75 ///
76 /// struct MyClipboard(String);
77 ///
78 /// impl ClipboardTrait for MyClipboard {
79 /// fn set_text(&mut self, text: String) {
80 /// self.0 = text;
81 /// }
82 ///
83 /// fn get_text(&mut self) -> String {
84 /// self.0.clone()
85 /// }
86 /// }
87 ///
88 /// let clipboard = MyClipboard(String::new());
89 /// let clipboard_wrapper = Clipboard::new(clipboard);
90 /// ```
91 #[must_use]
92 pub fn new(clipboard: impl ClipboardTrait + 'static) -> Self {
93 Clipboard(Rc::new(RefCell::new(clipboard)))
94 }
95}
96
97impl ClipboardTrait for Clipboard {
98 fn set_text(&mut self, text: String) {
99 self.0.borrow_mut().set_text(text);
100 }
101
102 fn get_text(&mut self) -> String {
103 self.0.borrow_mut().get_text()
104 }
105}
106
107#[derive(Default)]
108pub struct InternalClipboard(String);
109
110impl ClipboardTrait for InternalClipboard {
111 fn set_text(&mut self, text: String) {
112 self.0 = text;
113 }
114
115 fn get_text(&mut self) -> String {
116 self.0.clone()
117 }
118}
119
120#[cfg(not(feature = "arboard"))]
121impl Default for Clipboard {
122 /// Creates a new `Clipboard` with `InternalClipboard`.
123 /// The internal clipboard does not capture the systems clipboard.
124 fn default() -> Self {
125 Self::new(InternalClipboard::default())
126 }
127}