edtui/clipboard.rs
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
//! The editors clipboard
//!
//! ## Default clipboard
//!
//! `EdTUI` uses the arboard clipboard by default, which enables copy and paste
//! operations between the system clipboard and the editor. However, if a lighter
//! clipboard is desired, the "arboard" function flag can be deactivated. In this
//! case, the internal clipboard is used, which only supports copying and pasting
//! within the editor.
//!
//! ## Example: A custom global clipboard
//!
//! `EdTUI` allows you to set a custom clipboard. This is useful if you want to
//! define a global clipboard for example:
//!
//!```ignore
//! use once_cell::sync::Lazy;
//! use std::sync::Mutex;
//!
//! static CLIPBOARD: Lazy<GlobalClipboard> = Lazy::new(|| GlobalClipboard::new());
//!
//! struct GlobalClipboard(Mutex<Clipboard>);
//!
//! impl GlobalClipboard {
//! pub fn new() -> Self {
//! Self(Mutex::new(arboard::Clipboard::new().unwrap()))
//! }
//! }
//!
//! impl ClipboardTrait for &GlobalClipboard {
//! fn set_text(&mut self, text: String) {
//! if let Ok(mut clipboard) = self.0.lock() {
//! let _ = clipboard.set_text(text);
//! }
//! }
//!
//! fn get_text(&mut self) -> String {
//! if let Ok(mut clipboard) = self.0.lock() {
//! return clipboard.get_text().unwrap_or_default();
//! }
//! String::new()
//! }
//! }
//!
//! let mut state = EditorState::default();
//! state.set_clipboard(Lazy::force(&CLIPBOARD));
//!```
#[cfg(feature = "arboard")]
mod arboard;
use std::{cell::RefCell, rc::Rc};
/// Trait defining clipboard operations.
pub trait ClipboardTrait {
/// Sets text to the clipboard.
fn set_text(&mut self, text: String);
/// Retrieves text from the clipboard.
fn get_text(&mut self) -> String;
}
/// A clipboard for the editor.
///
/// This struct can hold any type that implements [`ClipboardTrait`].
#[derive(Clone)]
pub struct Clipboard(Rc<RefCell<dyn ClipboardTrait>>);
impl Clipboard {
/// Creates a new `Clipboard` instance with a provided clipboard implementation.
///
/// ## Example
///
/// ```
/// use edtui::clipboard::{Clipboard, ClipboardTrait};
///
/// struct MyClipboard(String);
///
/// impl ClipboardTrait for MyClipboard {
/// fn set_text(&mut self, text: String) {
/// self.0 = text;
/// }
///
/// fn get_text(&mut self) -> String {
/// self.0.clone()
/// }
/// }
///
/// let clipboard = MyClipboard(String::new());
/// let clipboard_wrapper = Clipboard::new(clipboard);
/// ```
#[must_use]
pub fn new(clipboard: impl ClipboardTrait + 'static) -> Self {
Clipboard(Rc::new(RefCell::new(clipboard)))
}
}
impl ClipboardTrait for Clipboard {
fn set_text(&mut self, text: String) {
self.0.borrow_mut().set_text(text);
}
fn get_text(&mut self) -> String {
self.0.borrow_mut().get_text()
}
}
#[derive(Default)]
pub struct InternalClipboard(String);
impl ClipboardTrait for InternalClipboard {
fn set_text(&mut self, text: String) {
self.0 = text;
}
fn get_text(&mut self) -> String {
self.0.clone()
}
}
#[cfg(not(feature = "arboard"))]
impl Default for Clipboard {
/// Creates a new `Clipboard` with `InternalClipboard`.
/// The internal clipboard does not capture the systems clipboard.
fn default() -> Self {
Self::new(InternalClipboard::default())
}
}