fix(tui): a bracketed paste that is not the clipboard never attaches its image

The origin check ran only on Otty. An IME commit or a diverged tmux buffer on any
other terminal attached whatever image sat on the clipboard.
This commit is contained in:
雷电芽衣 committed 2026-09-29 13:54:45 -04:00
1 parent 0e063e5b02
commit 041c5ca030
6 files changed
+61 -36

No files matched your search

@@ -189,11 +189,6 @@ impl TerminalName {
| Self::Zed
)
}
/// Only Otty is known to wrap macOS IME commits in bracketed paste.
pub fn delivers_ime_as_bracketed_paste(self) -> bool {
matches!(self, Self::Otty)
}
}
impl TerminalContext {
@@ -51,24 +51,6 @@ fn brand_otty_from_term_program() {
assert_eq!(detect_terminal_brand_from_env(&env), TerminalName::Otty);
}
#[test]
fn otty_delivers_ime_as_bracketed_paste_only() {
assert!(TerminalName::Otty.delivers_ime_as_bracketed_paste());
for brand in [
TerminalName::AppleTerminal,
TerminalName::Ghostty,
TerminalName::Iterm2,
TerminalName::Unknown,
TerminalName::WezTerm,
TerminalName::Kitty,
] {
assert!(
!brand.delivers_ime_as_bracketed_paste(),
"{brand:?} must not gate IME bracketed-paste origin"
);
}
}
#[test]
fn otty_is_capability_unclassified_like_unknown() {
assert!(TerminalName::Otty.is_capability_unclassified());
+1 -1
View File
@@ -1258,7 +1258,7 @@ pub enum ProbedAttachment {
PersistFailed(String),
/// The pasteboard probe completed normally without raster data.
NoRaster,
/// The attachment result was intentionally discarded because its baseline went stale.
/// The attachment result was discarded: stale baseline, or the paste was not the clipboard.
ProbeDropped,
/// The attachment probe task failed or timed out.
ProbeFailed,
@@ -1103,6 +1103,27 @@ pub(super) fn parse_usage_response(
.map(|usage| usage.rows)
.map_err(|e| format!("Parse error: {e}"))
}
/// `Some` ends a clipboard probe before any attachment read.
pub(super) fn bracketed_origin_verdict(
probe_bracketed: bool,
payload: Option<&str>,
) -> Option<crate::app::actions::ProbedAttachment> {
use crate::app::actions::ProbedAttachment;
if !probe_bracketed {
return None;
}
match crate::clipboard::bracketed_payload_came_from_clipboard_result(payload.unwrap_or("")) {
Ok(true) => None,
Ok(false) => {
tracing::debug!("bracketed paste differs from the clipboard; no attachment probe");
Some(ProbedAttachment::ProbeDropped)
}
Err(_) => {
tracing::debug!("clipboard unreadable for a bracketed paste; no attachment probe");
Some(ProbedAttachment::ProbeDropped)
}
}
}
/// A blocking flock on the shared, possibly-network `~/.kigi` lock must never
/// stall the event-loop thread (and would hang exit on `/quit`); the registry
/// is best-effort, so skip on contention.
+5 -12
View File
@@ -1637,18 +1637,11 @@ pub(crate) fn execute(
{
return (ProbedAttachment::ProbeDropped, None);
}
if probe_bracketed
&& crate::terminal::terminal_context()
.brand
.delivers_ime_as_bracketed_paste()
{
match crate::clipboard::bracketed_payload_came_from_clipboard_result(
probe_text.as_deref().unwrap_or(""),
) {
Ok(true) => {}
Ok(false) => return (ProbedAttachment::ProbeDropped, None),
Err(_) => return (ProbedAttachment::ProbeFailed, None),
}
if let Some(verdict) = helpers::bracketed_origin_verdict(
probe_bracketed,
probe_text.as_deref(),
) {
return (verdict, None);
}
let (image_data, file_urls) = match crate::clipboard::system_clipboard_probe_attachments(
probe_text.as_deref(),
@@ -1664,3 +1664,37 @@ fn session_picker_entry_maps_to_dormant_roster_row() {
assert_eq!(roster.origin.kind, "local");
assert_eq!(roster.origin.host.as_deref(), Some("box"));
}
fn origin_verdict_with_clipboard(
clipboard: Option<&str>,
read_failed: bool,
probe_bracketed: bool,
payload: &str,
) -> Option<crate::app::actions::ProbedAttachment> {
crate::clipboard::set_clipboard_probe_hook(crate::clipboard::ClipboardProbeHook {
text: clipboard.map(str::to_owned),
text_read_failed: read_failed,
..Default::default()
});
let verdict = bracketed_origin_verdict(probe_bracketed, Some(payload));
crate::clipboard::clear_clipboard_probe_hook();
verdict
}
#[test]
fn bracketed_paste_that_is_not_the_clipboard_drops_the_probe() {
let verdict = origin_verdict_with_clipboard(Some("copied text"), false, true, "typed by ime");
assert!(matches!(verdict, Some(crate::app::actions::ProbedAttachment::ProbeDropped)));
}
#[test]
fn bracketed_paste_matching_the_clipboard_keeps_probing() {
assert!(origin_verdict_with_clipboard(Some("copied text"), false, true, "copied text").is_none());
}
#[test]
fn unreadable_clipboard_drops_a_bracketed_probe_without_an_error() {
let verdict = origin_verdict_with_clipboard(None, true, true, "anything");
assert!(matches!(verdict, Some(crate::app::actions::ProbedAttachment::ProbeDropped)));
}
#[test]
fn clipboard_key_probe_skips_the_origin_check() {
assert!(origin_verdict_with_clipboard(Some("copied text"), false, false, "other").is_none());
}