Module: Charming::Escape
- Defined in:
- lib/charming/escape.rb
Overview
Escape is the out-of-band terminal channel: escape sequences written straight to the terminal, before each frame, bypassing the line-based renderer (which measures width and would shred raw control sequences). It is the shared substrate for several primitives — image transmissions (Image::Transmit), clipboard writes, desktop notifications, and the window title.
Sequences are gathered during an event's dispatch via a thread-local collector (Escape.collecting /
Escape.register) and attached to the Response; the Runtime flushes them through
backend.write_escape. Any object that responds to #payload (a string) can ride the channel;
the builders here return Sequence value objects and sanitize interpolated text so user content
can't break out of the sequence.
Defined Under Namespace
Classes: Sequence
Constant Summary collapse
- BUCKET_KEY =
Thread-local key under which the active collection bucket is stored.
:charming_escape_bucket
Class Method Summary collapse
-
.bell ⇒ Object
Builds a terminal-bell sequence (BEL).
-
.clipboard(text, target: "c") ⇒ Object
Builds an OSC 52 clipboard-write sequence setting the target selection (
"c"clipboard,"p"primary) to text. -
.collecting ⇒ Object
Runs block with a fresh collection bucket active and returns the bucket — the Sequences registered via Escape.register during the block.
-
.notification(body, title: nil) ⇒ Object
Builds a desktop-notification sequence: OSC 777 (
title+body) when a title is given, else OSC 9 (body only) — the broadly supported baseline (Ghostty, iTerm2, Kitty). -
.register(sequence) ⇒ Object
Registers sequence with the active collection bucket so it is flushed to the backend.
-
.title(text) ⇒ Object
Builds an OSC 0 sequence setting the terminal window (and icon) title to text.
Class Method Details
.bell ⇒ Object
Builds a terminal-bell sequence (BEL).
63 64 65 |
# File 'lib/charming/escape.rb', line 63 def bell Sequence.new(payload: "\a") end |
.clipboard(text, target: "c") ⇒ Object
Builds an OSC 52 clipboard-write sequence setting the target selection ("c" clipboard,
"p" primary) to text. The text is base64-encoded, so any bytes are safe.
46 47 48 |
# File 'lib/charming/escape.rb', line 46 def clipboard(text, target: "c") Sequence.new(payload: "\e]52;#{target};#{[text.to_s].pack("m0")}\a") end |
.collecting ⇒ Object
25 26 27 28 29 30 31 32 33 |
# File 'lib/charming/escape.rb', line 25 def collecting previous = Thread.current[BUCKET_KEY] bucket = [] Thread.current[BUCKET_KEY] = bucket yield bucket ensure Thread.current[BUCKET_KEY] = previous end |
.notification(body, title: nil) ⇒ Object
Builds a desktop-notification sequence: OSC 777 (title + body) when a title is given,
else OSC 9 (body only) — the broadly supported baseline (Ghostty, iTerm2, Kitty).
52 53 54 55 56 57 58 59 60 |
# File 'lib/charming/escape.rb', line 52 def notification(body, title: nil) payload = if title "\e]777;notify;#{sanitize(title)};#{sanitize(body)}\e\\" else "\e]9;#{sanitize(body)}\a" end Sequence.new(payload: payload) end |
.register(sequence) ⇒ Object
Registers sequence with the active collection bucket so it is flushed to the backend. A no-op (outside a collection, or when sequence is nil) so callers can register freely.
37 38 39 40 41 42 |
# File 'lib/charming/escape.rb', line 37 def register(sequence) return sequence unless sequence Thread.current[BUCKET_KEY]&.push(sequence) sequence end |
.title(text) ⇒ Object
Builds an OSC 0 sequence setting the terminal window (and icon) title to text.
68 69 70 |
# File 'lib/charming/escape.rb', line 68 def title(text) Sequence.new(payload: "\e]0;#{sanitize(text)}\a") end |