summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/utils/clipboard.rs33
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"))]