aboutsummaryrefslogtreecommitdiffstats
path: root/docs/scripting.md
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-20 23:23:07 +0200
committeruser <user@clank>2026-08-20 23:23:07 +0200
commit965966f9fb3808fbc69e6cb55960ad7a3c72c5f4 (patch)
tree388d17a48155b9fae25c65fdc6c8765b6bb3ec01 /docs/scripting.md
parentslosh: floating panes and the drop grammar (diff)
downloadslosh-965966f9fb3808fbc69e6cb55960ad7a3c72c5f4.tar.gz
slosh-965966f9fb3808fbc69e6cb55960ad7a3c72c5f4.tar.xz
slosh-965966f9fb3808fbc69e6cb55960ad7a3c72c5f4.zip
slosh: OSC 8 hyperlinks pass through the compositor
lib-vt tracks a hyperlink per cell and slosh dropped every one of them: the client's terminal can only offer a link it was sent, so `ls --hyperlink`, gcc diagnostics and friends silently lost theirs inside the session. The link rides beside the cell -- cell_t is the shader ABI and a link is not a colour -- as a plane of ids into an interned URI table, append-only so an id in prev_link still means the same URI next frame (which is what lets the diff compare ids instead of strings), and capped so a hostile pane cannot grow it forever. URIs with control bytes are refused outright: they are emitted verbatim inside an OSC, and a control byte in one is a way to write escape sequences into the client's terminal. The diff wraps emitted runs in OSC 8, closes what it opens before the frame ends, and treats a link-only change as a change. Chrome painted over a link takes the link with it, so a frame, modal or float across a URL is never clickable with the pane's link; links survive scrollback with the text that carries them. Plain-text URLs stay the outer terminal's own matcher, with the catch documented in panes.md: under mouse capture Ghostty only offers links with shift added to the gesture (shift+cmd hover/click), shift being its capture escape. Wrapped URLs can never be regex-matched through a multiplexer -- rows repaint as hard lines -- which is exactly what OSC 8 links, passing through whole, are for. `snapshot format:"bytes"` returns the emitter's own output for a frame (a second call is the delta): the model and the bytes are two different things, and this codebase already paid once for asserting on one while the other was wrong.
Diffstat (limited to 'docs/scripting.md')
-rw-r--r--docs/scripting.md2
1 files changed, 1 insertions, 1 deletions
diff --git a/docs/scripting.md b/docs/scripting.md
index 43615a2..0074782 100644
--- a/docs/scripting.md
+++ b/docs/scripting.md
@@ -21,7 +21,7 @@ Panes and tabs are addressed by **id**, so a background tab is scriptable.
| verb | |
|---|---|
| `panes` `tabs` | what exists, with ids, rects, titles, purposes, state. A pane's `tab_id` is what `move-pane` and `select-tab` want; its `tab` is where that tab sits in the strip |
-| `snapshot` | the composited screen, as JSON or `format:"text"` |
+| `snapshot` | the composited screen, as JSON, `format:"text"`, or `format:"bytes"` — the emitter's own output for this frame (a second call is the delta) |
| `deadline` | when the session wants its next frame, in ms, or -1 |
| `send` | bytes as if typed, decoded like input (`"data":"\\x01\\\\"`) |
| `raw` | bytes straight into the focused pane's pty |