diff --git a/CHANGELOG.md b/CHANGELOG.md index c7edd33..f7a2c95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Print name of launch command if Alacritty failed to execute it - Live reload font settings from config - UTF-8 mouse mode escape sequence (`CSI ? 1005 h` / `CSI ? 1005 l`) +- Escape for reading clipboard (`OSC 52 ; ; ? BEL`) +- Set selection clipboard (`OSC 52 ; ; BEL`) ### Changed diff --git a/alacritty_terminal/src/ansi.rs b/alacritty_terminal/src/ansi.rs index 55c064e..3cd03cb 100644 --- a/alacritty_terminal/src/ansi.rs +++ b/alacritty_terminal/src/ansi.rs @@ -16,7 +16,6 @@ use std::io; use std::str; -use base64; use log::{debug, trace}; use serde::{Deserialize, Serialize}; @@ -324,7 +323,10 @@ pub trait Handler { fn reset_color(&mut self, _: usize) {} /// Set the clipboard - fn set_clipboard(&mut self, _: &str) {} + fn set_clipboard(&mut self, _: u8, _: &[u8]) {} + + /// Write clipboard data to child. + fn write_clipboard(&mut self, _: u8, _: &mut W) {} /// Run the dectest routine fn dectest(&mut self) {} @@ -847,19 +849,13 @@ where // Set clipboard b"52" => { - if params.len() < 3 { + if params.len() < 3 || params[1].is_empty() { return unhandled(params); } match params[2] { - b"?" => unhandled(params), - selection => { - if let Ok(string) = base64::decode(selection) { - if let Ok(utf8_string) = str::from_utf8(&string) { - self.handler.set_clipboard(utf8_string); - } - } - }, + b"?" => self.handler.write_clipboard(params[1][0], writer), + base64 => self.handler.set_clipboard(params[1][0], base64), } }, diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index 570dc7f..1622ece 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -16,7 +16,7 @@ use std::cmp::{max, min}; use std::ops::{Index, IndexMut, Range}; use std::time::{Duration, Instant}; -use std::{io, mem, ptr}; +use std::{io, mem, ptr, str}; use log::{debug, trace}; use serde::{Deserialize, Serialize}; @@ -1718,8 +1718,33 @@ impl ansi::Handler for Term { /// Set the clipboard #[inline] - fn set_clipboard(&mut self, string: &str) { - self.clipboard.store(ClipboardType::Clipboard, string); + fn set_clipboard(&mut self, clipboard: u8, base64: &[u8]) { + let clipboard_type = match clipboard { + b'c' => ClipboardType::Clipboard, + b'p' | b's' => ClipboardType::Selection, + _ => return, + }; + + if let Ok(bytes) = base64::decode(base64) { + if let Ok(text) = str::from_utf8(&bytes) { + self.clipboard.store(clipboard_type, text); + } + } + } + + /// Write clipboard data to child. + #[inline] + fn write_clipboard(&mut self, clipboard: u8, writer: &mut W) { + let clipboard_type = match clipboard { + b'c' => ClipboardType::Clipboard, + b'p' | b's' => ClipboardType::Selection, + _ => return, + }; + + let text = self.clipboard.load(clipboard_type); + let base64 = base64::encode(&text); + let escape = format!("\x1b]52;{};{}\x07", clipboard as char, base64); + let _ = writer.write_all(escape.as_bytes()); } #[inline]