There are various validation behaviors we did that matched the spec but
didn't match Kitty, because Kitty is written in C (these parts) and does
a lot of C-ish things (like bool is any non-zero value, despite the spec
saying 1/0).
This also fixes a more major issue where invalid formats should be
deferred until transmission finishes so we send a proper response. Right
now we send no response which can cause a client to hang!
There are various validation behaviors we did that matched the spec but
didn't match Kitty, because Kitty is written in C (these parts) and does
a lot of C-ish things (like bool is any non-zero value, despite the spec
saying 1/0).
This also fixes a more major issue where invalid formats should be
deferred until transmission finishes so we send a proper response. Right
now we send no response which can cause a client to hang!
The `d=r`/`d=R` delete parser required a `y` key and enforced `x <= y`,
rejecting the entire command with `error.InvalidFormat` otherwise. Both
bounds now default to zero and neither is validated.
This matches upstream reference implementation.
The `d=r`/`d=R` delete parser required a `y` key and enforced `x <= y`,
rejecting the entire command with `error.InvalidFormat` otherwise. Both
bounds now default to zero and neither is validated.
This matches upstream reference implementation.
Emit a `progress_report` remove effect from the `full_reset` arm,
matching kitty and WezTerm which both clear progress on reset.
Previously, only the termio `StreamHandler` removed the progress bar on
RIS (#10178) - but the terminal stream handler used by `libghostty-vt`
did not, so an embedder's progress bar would outlive the reset.
Initial input files remained open and their fully read buffers remained
allocated after queueWrite copied their contents. Close these files on
both startup success and failure, free their contents after queueing,
and borrow raw values already owned by the arena.
**AI Usage:** This was spotted by GPT 5.6 Sol. I reworked the code a bit
and understand it all.
Glyf rasterization previously let z2d allocate its alpha surface, then
duplicated the completed pixels into caller-owned storage. Back the z2d
surface with the final bitmap instead, eliminating one allocation and a
full bitmap copy for each non-empty glyph.
Initial input files remained open and their fully read buffers remained
allocated after queueWrite copied their contents. Close these files on
both startup success and failure, free their contents after queueing, and
borrow raw values already owned by the arena.
Glyf rasterization previously let z2d allocate its alpha surface, then
duplicated the completed pixels into caller-owned storage. Back the z2d
surface with the final bitmap instead, eliminating one allocation and a
full bitmap copy for each non-empty glyph.
Selection strings previously duplicated formatted text when callers
requested a `StringMap`, even though the regex-link caller immediately
freed the returned copy.
Add a dedicated `selectionStringMap` path that transfers the formatter
output and pin map directly into the returned map. This removes the
extra allocation and copy while making ownership explicit.
**AI Usage:** GTP 5.6 Sol identified and implemented this opportunity. I
reviewed and understand it all.
Fills the 181 untranslated strings in `po/nl.po`, bringing it to
252/252. Most of them are the command palette actions from
`src/input/command.zig`; the rest are the new context menu items, global
keybind notifications, and config editing strings.
**Style.** Ten of the new command palette strings had already been
translated by previous translators, and those settle the verb form, so
the rest follows them: imperative for verb+object action titles (`Split
Left` → `Splits naar links`, `Close Tab` → `Sluit tabblad`), noun
phrases left as noun phrases (`New Window` → `Nieuw venster`), no title
case, informal "je". Descriptions are full imperative sentences. Dialog
headings keep the noun-first infinitive form of the existing `Change
Terminal Title` → `Titel van de terminal wijzigen`.
A few translation notes:
- `ANSI Sequences` → `ANSI-reeksen` in titles, `ANSI escape sequences` →
`ANSI-escapereeksen` in descriptions, mirroring the distinction the
source makes.
- `Toggle X` titles use the idiomatic `X aan/uit`; their descriptions
stay imperative (`Schakel … in of uit.`).
- `surface` is rendered as `terminal` - the Dutch UI has no equivalent
concept.
- `scrollback` → `scrollbuffer`.
**No existing translation was modified.** The diff only touches empty
`msgstr` lines plus `PO-Revision-Date` and `Last-Translator`.
Checked with `msgfmt -c --statistics` (252 translated, no warnings, no
fuzzy) and `msgcat` (formatting is idempotent, so no rewrap noise for
the next translator). No `X-Generator` field added.
---------
Co-authored-by: Nico Geesink <126799020+nwehg@users.noreply.github.com>
Selection strings previously duplicated formatted text when callers
requested a StringMap, even though the regex-link caller immediately
freed the returned copy.
Add a dedicated selectionStringMap path that transfers the formatter
output and pin map directly into the returned map. This removes the
extra allocation and copy while making ownership explicit.
The common directory helper previously allocated a temporary slice to
prepend the base directory before joining path components. Pass the
three known components directly to std.fs.path.join, leaving only the
allocation for the returned path.
The common directory helper previously allocated a temporary slice to
prepend the base directory before joining path components. Pass the
three known components directly to std.fs.path.join, leaving only the
allocation for the returned path.
Some shell setup functions previously converted their stack-backed
command builders to owned sentinel slices before duplicating them into
the result arena. Duplicate the builders' written bytes directly
instead, avoiding unnecessary ownership transfer and sentinel handling.
Text binding actions previously allocated a temporary buffer for every
escaped string. Use a 256-byte stack fallback allocator so typical
bindings avoid the transient heap allocation while larger values
continue to use the existing heap-backed behavior.
Some shell setup functions previously converted their stack-backed
command builders to owned sentinel slices before duplicating them into
the result arena. Duplicate the builders' written bytes directly
instead, avoiding unnecessary ownership transfer and sentinel handling.
Text binding actions previously allocated a temporary buffer for every
escaped string. Use a 256-byte stack fallback allocator so typical
bindings avoid the transient heap allocation while larger values
continue to use the existing heap-backed behavior.
Make `Tabstops.unset` (backing [Tab Clear
(TBC)](https://ghostty.org/docs/vt/csi/tbc) with `n=0`) not set a tab
stop when clearing a column that has no tab stop.
Emit a progress_report remove effect from the full_reset arm, matching
kitty and WezTerm which both clear progress on reset.
Previously, only the termio StreamHandler removed the progress bar on
RIS (ghostty#10178); the terminal stream handler used by libghostty-vt
did not, so an embedder's progress bar would outlive the reset.
Signed-off-by: Fredrik Fornwall <fredrik@fornwall.net>
Tabstops.unset used XOR, so unsetting a column without a tabstop set
one instead. This made TBC (CSI 0 g) and CTC (CSI 2 W) create a
tabstop at the cursor column when none existed.
Signed-off-by: Fredrik Fornwall <fredrik@fornwall.net>
Make uppercase Kitty graphics deletes with a nonzero placement ID leave
the image intact when the named placement does not exist.
Previously, d=I,i=...,p=... could free unreferenced image data after
matching no placement. A later put then failed with ENOENT, diverging
from the protocol and Kitty.
Chunked image responses used the final command even though only the
initial chunk carries the image and placement identifiers. Successful
replies lost image numbers and placement IDs. Final validation errors
could also be suppressed entirely.
Save the initial response identifiers with the in-progress image and use
them when the final chunk completes. Continue replacing the response ID
with the generated image ID after a successful load. Cover successful
image-number replies and invalid final payloads with unit tests.
Graphics query commands previously initialized their loading state but
returned success before completing the image load.
This allowed truncated, malformed, or otherwise invalid image data to
return OK, giving capability probes a false positive.
Complete and validate queried images through the normal load path, then
discard the result without modifying image storage. Add coverage for
invalid data and preserving an existing image with the queried ID.
Make uppercase Kitty graphics deletes with a nonzero placement ID
leave the image intact when the named placement does not exist.
Previously, d=I,i=...,p=... could free unreferenced image data after
matching no placement. A later put then failed with ENOENT, diverging
from the protocol and Kitty.
Chunked image responses used the final command even though only the
initial chunk carries the image and placement identifiers. Successful
replies lost image numbers and placement IDs. Final validation errors
could also be suppressed entirely.
Save the initial response identifiers with the in-progress image and use
them when the final chunk completes. Continue replacing the response ID
with the generated image ID after a successful load. Cover successful
image-number replies and invalid final payloads with unit tests.
Graphics query commands previously initialized their loading state but
returned success before completing the image load.
This allowed truncated, malformed, or otherwise invalid image data to
return OK, giving capability probes a false positive.
Complete and validate queried images through the normal load path, then
discard the result without modifying image storage. Add coverage for
invalid data and preserving an existing image with the queried ID.
- Limit d=a/A to non-virtual placements that intersect the active
screen.
- Keep unrelated unplaced image data when processing d=A.
- Make d=R delete matching unused images even when they have no
placements, and default an omitted x bound to zero.
- Give ED2 a separate clear path that preserves scrollback references
while reclaiming every unreferenced image.
References:
- Spec:
https://sw.kovidgoyal.net/kitty/graphics-protocol/#deleting-images
- Delete reference implementation:
0ecb10d158/kitty/graphics.c (L2114-L2363)
- ED2 reference implementation:
0ecb10d158/kitty/screen.c (L2919-L2958)
- Limit d=a/A to non-virtual placements that intersect the active screen.
- Keep unrelated unplaced image data when processing d=A.
- Make d=R delete matching unused images even when they have no
placements, and default an omitted x bound to zero.
- Give ED2 a separate clear path that preserves scrollback references
while reclaiming every unreferenced image.
References:
- Spec:
https://sw.kovidgoyal.net/kitty/graphics-protocol/#deleting-images
- Delete reference implementation:
0ecb10d158/kitty/graphics.c (L2114-L2363)
- ED2 reference implementation:
0ecb10d158/kitty/screen.c (L2919-L2958)
Previously, delete left partial bytes alive for the next upload, while
failed or incomplete retransmissions kept stale placements visible.
Abort incomplete chunked image uploads on delete commands and remove an
existing image and its placements when retransmission of an explicit ID
begins.
Previously, delete left partial bytes alive for the next upload, while
failed or incomplete retransmissions kept stale placements visible.
Abort incomplete chunked image uploads on delete commands and remove an
existing image and its placements when retransmission of an explicit ID
begins.
File transmissions with exactly S bytes or trailing file data previously
failed because appendRemaining reports StreamTooLong when it reaches its
limit. This broke the protocol's partial-file transmission path.
Use an exact-length allocation and read when S is nonzero, rejecting
premature EOF and values above the image limit. Preserve the existing
bounded read-to-EOF behavior for S=0.
https://sw.kovidgoyal.net/kitty/graphics-protocol/#local-client