//! The system clipboard, behind the `"+` register (and behind every yank //! and paste with `clipboard = "unnamedplus"`). It's opened the first time //! it's used, and kept open: on Linux, text copied there lasts as long as //! cumulus runs, or until a clipboard manager takes it over. //! //! The tests keep their clipboard in memory, so they never touch yours. /// The system clipboard. #[derive(Default)] pub struct Clipboard { #[cfg(not(test))] system: Option, #[cfg(test)] text: Option, } impl std::fmt::Debug for Clipboard { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("Clipboard") } } #[cfg(not(test))] impl Clipboard { /// The text on the clipboard. pub fn read(&mut self) -> Result { self.open()?.get_text().map_err(problem) } /// Puts text on the clipboard. pub fn write(&mut self, text: &str) -> Result<(), String> { self.open()?.set_text(text.to_string()).map_err(problem) } fn open(&mut self) -> Result<&mut arboard::Clipboard, String> { if self.system.is_none() { self.system = Some(arboard::Clipboard::new().map_err(problem)?); } self.system.as_mut().ok_or_else(|| "the clipboard isn't available".to_string()) } } /// What went wrong with the clipboard, in words. #[cfg(not(test))] fn problem(error: arboard::Error) -> String { match error { arboard::Error::ContentNotAvailable => "the clipboard holds no text".to_string(), error => format!("the clipboard isn't available: {error}"), } } #[cfg(test)] impl Clipboard { pub fn read(&mut self) -> Result { self.text.clone().ok_or_else(|| "the clipboard holds no text".to_string()) } pub fn write(&mut self, text: &str) -> Result<(), String> { self.text = Some(text.to_string()); Ok(()) } }