diff options
Diffstat (limited to 'src/utils/clipboard.rs')
| -rw-r--r-- | src/utils/clipboard.rs | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/src/utils/clipboard.rs b/src/utils/clipboard.rs index 12e1655..cb92bce 100644 --- a/src/utils/clipboard.rs +++ b/src/utils/clipboard.rs @@ -1,19 +1,42 @@ +use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _}; + #[cfg(not(any(target_os = "android", target_os = "emscripten")))] static CLIPBOARD: std::sync::LazyLock<std::sync::Mutex<Option<arboard::Clipboard>>> = std::sync::LazyLock::new(|| std::sync::Mutex::new(arboard::Clipboard::new().ok())); +/// Attempts to set text to clipboard with OSC52 escape sequence +/// Works in many modern terminals, including over SSH. +fn set_text_osc52(text: &str) -> anyhow::Result<()> { + let encoded = BASE64.encode(text); + let seq = format!("\x1b]52;c;{}\x07", encoded); + // Write to stdout: + if let Err(e) = std::io::Write::write_all(&mut std::io::stdout(), seq.as_bytes()) { + return Err(anyhow::anyhow!("Failed to send OSC52 sequence").context(e)); + } + // Flush stdout: + if let Err(e) = std::io::Write::flush(&mut std::io::stdout()) { + return Err(anyhow::anyhow!("Failed to flush OSC52 sequence").context(e)); + } + Ok(()) +} + #[cfg(not(any(target_os = "android", target_os = "emscripten")))] pub fn set_text(text: &str) -> anyhow::Result<()> { + // First try arboard: let mut clipboard = CLIPBOARD.lock().unwrap(); - match clipboard.as_mut() { - Some(clipboard) => { - clipboard.set_text(text)?; + if let Some(clipboard) = clipboard.as_mut() { + if let Ok(()) = clipboard.set_text(text) { #[cfg(target_os = "linux")] std::thread::sleep(std::time::Duration::from_millis(50)); + return Ok(()); } - None => return Err(anyhow::anyhow!("No clipboard available").context("Failed to copy")), } - Ok(()) + // If arboard failed, try OSC52: + match set_text_osc52(text) { + Ok(()) => Ok(()), + Err(osc_err) => Err(anyhow::anyhow!("No clipboard available") + .context(format!("Failed to copy (OSC52 error: {})", osc_err))), + } } #[cfg(any(target_os = "android", target_os = "emscripten"))] |
