Skip to content

fix(session): OSC 52 reads get a reply again (engine gate dropped them) - #21

Open
kingb wants to merge 1 commit into
mainfrom
fix/osc52-read-engine-gate
Open

kingb wants to merge 1 commit into
mainfrom
fix/osc52-read-engine-gate

Conversation

@kingb

@kingb kingb commented Sep 28, 2026

Copy link
Copy Markdown
Owner

Fixes the gated OSC 52 clipboard read that shipped in 0.5.0, which has never actually replied.

The bug

alacritty_terminal has its own OSC 52 gate ahead of the event listener, and its default, Osc52::OnlyCopy, drops reads inside the engine (term/mod.rs, clipboard_load). Ember built its Term with Config::default() and never set osc52, so the listener's ClipboardLoad arm never ran:

  • osc52_read = true had no effect.
  • With it off (the default), the documented empty reply never went out. A program waiting on its clipboard query got silence, which is exactly the hang the empty reply exists to prevent.

The fix

Build the engine with osc52: Osc52::CopyPaste. The listener stays the single gate on contents: the real clipboard only with osc52_read = true, and an empty reply otherwise. Copy behaviour is unchanged, and nothing new is exposed. This is the only place Ember constructs a Term.

Why the existing test didn't catch it

osc52_read_gated_off_replies_empty hands a synthetic ClipboardLoad event straight to the listener, bypassing the engine gate that drops the real one. The new osc52_read_through_the_engine_replies_empty sends the real escape bytes (ESC]52;c;?BEL) through the projection. It failed before this change (left: "") and passes after.

Validation

cargo fmt --check, clippy -D warnings, cargo test --all --all-features and the grid conformance corpus (7/7) are all clean. A CHANGELOG [Unreleased] entry is added.

🤖 Generated with Claude Code

https://claude.ai/code/session_014xVjnf8UuQPRQtv2QqgpPK

alacritty_terminal has its own OSC 52 gate ahead of the event listener, and
its default (Osc52::OnlyCopy) drops read requests inside the engine. Ember
built its Term with Config::default() and never set it, so since the gated
clipboard read shipped in 0.5.0 the listener's ClipboardLoad arm never ran.
A read got no reply at all: osc52_read = true had no effect, and with it off
the documented empty reply never went out, leaving a program that waits on
its query to hang.

The engine now accepts both copy and paste (Osc52::CopyPaste), and the
listener stays the single gate on clipboard contents: the real contents only
with osc52_read = true, an empty reply otherwise (the default). Nothing new
is exposed.

The existing test missed this because it handed a synthetic ClipboardLoad
straight to the listener, bypassing the engine gate. The new test sends the
real escape bytes through the engine; it failed with an empty outbox before
this change and passes after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014xVjnf8UuQPRQtv2QqgpPK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant