diff options
| author | user <user@clank> | 2026-08-20 23:23:07 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-20 23:23:07 +0200 |
| commit | 965966f9fb3808fbc69e6cb55960ad7a3c72c5f4 (patch) | |
| tree | 388d17a48155b9fae25c65fdc6c8765b6bb3ec01 /docs/scripting.md | |
| parent | slosh: floating panes and the drop grammar (diff) | |
| download | slosh-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.md | 2 |
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 | |
