From 8fe09d5ddf77da5c377760682b33b386ebc37640 Mon Sep 17 00:00:00 2001 From: akbash Date: Fri, 21 Aug 2026 15:16:43 +0300 Subject: fix: preserve multiline paste in terminal attach (#3056) refs #3054 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> --- src/raw_input.rs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'src/raw_input.rs') diff --git a/src/raw_input.rs b/src/raw_input.rs index 510768fc..5f750ca8 100644 --- a/src/raw_input.rs +++ b/src/raw_input.rs @@ -108,19 +108,22 @@ pub(crate) const GHOSTTY_COLOR_SCHEME_LIGHT_REPORT: &[u8] = b"\x1b[?997;2n"; const BRACKETED_PASTE_START: &[u8] = b"\x1b[200~"; const BRACKETED_PASTE_END: &[u8] = b"\x1b[201~"; -/// Returns whether `data` is exactly one complete bracketed-paste sequence. -/// +/// Returns the UTF-8 payload when `data` is exactly one complete bracketed paste. +pub(crate) fn complete_text_bracketed_paste(data: &[u8]) -> Option<&str> { + if !data.starts_with(BRACKETED_PASTE_START) { + return None; + } + let end = find_subsequence(data, BRACKETED_PASTE_END)?; + if end + BRACKETED_PASTE_END.len() != data.len() { + return None; + } + std::str::from_utf8(&data[BRACKETED_PASTE_START.len()..end]).ok() +} + /// Client transport uses this to distinguish recoverable oversized interactive /// pastes from generic oversized input, which remains a protocol violation. pub(crate) fn is_complete_text_bracketed_paste(data: &[u8]) -> bool { - if !data.starts_with(BRACKETED_PASTE_START) { - return false; - } - let Some(end) = find_subsequence(data, BRACKETED_PASTE_END) else { - return false; - }; - end + BRACKETED_PASTE_END.len() == data.len() - && std::str::from_utf8(&data[BRACKETED_PASTE_START.len()..end]).is_ok() + complete_text_bracketed_paste(data).is_some() } #[derive(Debug)] @@ -1424,7 +1427,10 @@ mod tests { #[test] fn complete_text_bracketed_paste_requires_one_exact_utf8_sequence() { - assert!(is_complete_text_bracketed_paste(b"\x1b[200~hello\x1b[201~")); + assert_eq!( + complete_text_bracketed_paste(b"\x1b[200~hello\x1b[201~"), + Some("hello") + ); assert!(!is_complete_text_bracketed_paste(b"\x1b[200~hello")); assert!(!is_complete_text_bracketed_paste( b"\x1b[200~hello\x1b[201~rest" -- cgit v1.2.3