Commit Graph

8514 Commits

Author SHA1 Message Date
Mitchell Hashimoto
f479210daf Rewrite semantic prompt parsing, parse the full spec (#10427)
Related to #5932 

This updates our OSC parser to parse the full OSC 133 specification:
https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/semantic-prompts.md

The logic for handling these events was _unchanged_ from our prior
implementation. This is just a parser-only update. As such, we ignore a
bunch of semantic prompt command we should definitely handle, and
incorrectly handle others. This is the crux of #5932 that I want to head
towards fixing. This PR just contains the parser updates.

I also retained all the Kitty parser extensions.

**AI disclosure:** AI helped a lot of the rote tasks once I manually did
a few. I'm still reviewing this manually but will do so shortly.
2026-01-24 07:04:04 -08:00
Mitchell Hashimoto
c98e3e6fc7 terminal/osc: rename the prompt2 file 2026-01-23 14:38:28 -08:00
Mitchell Hashimoto
afea12116d terminal/osc: Kitty extensions to semantic prompt options 2026-01-23 14:38:06 -08:00
Mitchell Hashimoto
d23722dbd7 terminal: remove old semantic prompt handling 2026-01-23 14:35:10 -08:00
Mitchell Hashimoto
389439b167 terminal: handle semantic prompt same as old 2026-01-23 14:30:27 -08:00
Mitchell Hashimoto
6ce45fb65a terminal/osc: semantic prompt redraw option from Kitty 2026-01-23 14:19:43 -08:00
Mitchell Hashimoto
9f2808ce40 terminal: stream handles new SemanticPrompt type 2026-01-23 14:14:28 -08:00
Mitchell Hashimoto
edafe86203 terminal/osc: semantic prompt is a struct not tagged union 2026-01-23 14:04:27 -08:00
Mitchell Hashimoto
a9e23c135f terminal/osc: semantic prompt 'D' 2026-01-23 13:56:29 -08:00
Mitchell Hashimoto
9d1282eb95 terminal/osc: semantic prompt 'C' 2026-01-23 13:44:34 -08:00
Mitchell Hashimoto
7421e78f1e terminal/osc: semantic prompt 'I' 2026-01-23 13:43:08 -08:00
Mitchell Hashimoto
fdc6a6b10a terminal/osc: semantic prompt 'B' 2026-01-23 13:39:33 -08:00
Mitchell Hashimoto
0d9216bb5a terminal/osc: semantic prompt 'N' 2026-01-23 13:37:34 -08:00
Mitchell Hashimoto
39c0f79b8d terminal/osc: semantic prompt 'P' 2026-01-23 13:35:16 -08:00
Mitchell Hashimoto
7968358234 terminal/osc: semantic prompt options 2026-01-23 13:26:45 -08:00
Mitchell Hashimoto
65c56c7c77 terminal/osc: add 'A' 2026-01-23 13:19:11 -08:00
Mitchell Hashimoto
d040c935e2 terminal/osc: boilerplate new OSC 133 parsing 2026-01-23 13:02:23 -08:00
Jeffrey C. Ollie
f0b4e86ab5 gtk: add read-only indicator for surfaces
Fixes: #9889
2026-01-23 12:11:48 -06:00
Jeffrey C. Ollie
e1b82ff398 osc: parse iTerm2 OSC 1337 extensions
Add a framework for parsing iTerm2's OSC 1337 extensions. Implement
a couple (`Copy` and `CurrentDir`) that map easily onto existing OSC
commands.
2026-01-22 22:06:39 -06:00
Mitchell Hashimoto
338c9b15aa splits: make resize_split and toggle_split_zoom non-performable with single pane (#10376)
Refer to discussion #10000 

When a tab contains only a single split, resize_split and
toggle_split_zoom actions now return false (not performed). This allows
keybindings marked with `performable: true` to pass the event through to
the terminal program.

The performable flag causes unperformed actions to be treated as if the
binding didn't exist, so the key event is sent to the terminal instead
of being consumed.

- Add isSplit() helper to SplitTree to detect single-pane vs split state
- Update GTK resizeSplit/toggleSplitZoom to return false when single
pane
- Update macOS resizeSplit/toggleSplitZoom to return Bool and check
isSplit
- Add unit test for isSplit method
2026-01-22 08:23:57 -08:00
Mitchell Hashimoto
01f1611c9f tripwire: change backing store from ArrayHashMap to EnumMap
This eliminates all allocation from Tripwire.
2026-01-21 15:30:49 -08:00
Mitchell Hashimoto
fbc1e326d6 Introduce Tripwire to test errdefer and fix some found issues (#10401)
This adds a new single-file library called "Tripwire" in
`src/tripwire.zig`. This library helps inject failures around `try`
cases for the purpose of testing `errdefer`. It is fully optimized away
in non-test builds (even debug), turning into zero space and zero
assembly.

From this, I've verified (via unit tests w/ tripwire) and fixed a number
of errdefer issues:

* PageList init with non-standard pages that requires more than 1 page
can leak on allocation error on the 2nd+ loop
* Tabstop allocation failure on resize corrupts the internal state
(invalid cols)
* `Screen.selectionString` would leak memory on late allocation failures
* Screen search could leak memory on late allocation failures
* `SharedGrid.renderGlyph` in our font subsystem would corrupt the glyph
cache if failure occurred
* `SharedGrid.init` could leak memory if loading font metrics failed

In addition to the bugs found, there is now tripwire coverage around
more of our core and we should continue to add more. I've also added
significantly more explicit error sets as I found them.

**AI disclosure:** AI wrote some of the tests, but tripwire itself is
all handwritten and everything was reviewed.
2026-01-21 12:50:55 -08:00
Mitchell Hashimoto
3fdff49a82 font: fix memory leak in SharedGrid.init on late failure
Add errdefer cleanup for codepoints and glyphs hash maps in init().
Previously, if ensureTotalCapacity or reloadMetrics() failed after
allocating these maps, they would leak.

Add tripwire test to verify all failure points in init().
2026-01-21 12:37:21 -08:00
Mitchell Hashimoto
b606b71cda font: fix missing errdefer rollback in SharedGrid.renderGlyph
Add errdefer to remove cache entry after getOrPut if subsequent
operations fail (getPresentation, atlas.grow, renderGlyph). Without
this, failed renders would leave uninitialized/garbage entries in
the glyph cache, potentially causing crashes or incorrect rendering.

Add tripwire test to verify the rollback behavior.
2026-01-21 12:23:28 -08:00
Mitchell Hashimoto
64ccad3a75 terminal: fix memory leak on error handling in screen search 2026-01-21 12:01:59 -08:00
Mitchell Hashimoto
c1b22a8041 terminal: fix leak on error in selectionString 2026-01-21 11:53:25 -08:00
Mitchell Hashimoto
a83bd6a111 font: add tripwire tests to Atlas 2026-01-21 11:34:59 -08:00
Mitchell Hashimoto
82b10ae7af terminal: explicit error sets in Screen and ScreenSet 2026-01-21 11:34:59 -08:00
Jeffrey C. Ollie
9ee27d2697 OSC 9: Finish parsing all ConEmu OSCs
Adds support for parsing OSC 9;7, 9;8, 9;9, 9;10, 9;11, 9;12
2026-01-21 13:34:30 -06:00
Mitchell Hashimoto
3d2152f5e8 terminal: Tabstops fix state corruption on error in resize 2026-01-21 09:50:53 -08:00
Mitchell Hashimoto
baa9dd6b2a terminal: use tripwire with PageList init, fix an errdefer bug 2026-01-21 09:42:31 -08:00
Mitchell Hashimoto
179a9d4cfa tripwire: a module for injecting failures to test errdefer 2026-01-21 09:39:02 -08:00
Steven Lu
ba16ce0249 reintroduce assertion, with adjusted limit 2026-01-21 20:03:37 +07:00
Mitchell Hashimoto
6ec2bfe288 renderer: kitty graphics prep can't fail (skip failed conversions) 2026-01-20 12:29:10 -08:00
Mitchell Hashimoto
d235c490e9 renderer: handle rebuildCells failures gracefully 2026-01-20 12:13:30 -08:00
Mitchell Hashimoto
db092ac3ce renderer: extract rebuildRow to its own function 2026-01-20 12:07:42 -08:00
Mitchell Hashimoto
112363c4e1 font: Collection.getEntry explicit error set 2026-01-20 11:57:22 -08:00
Mitchell Hashimoto
e875b453b7 font/shaper: hook functions can't fail 2026-01-20 11:51:01 -08:00
Mitchell Hashimoto
e3c39ed502 renderer: cell.Contents.resize errdefer handling is now safe 2026-01-20 11:46:27 -08:00
Mitchell Hashimoto
7204f7ef9e renderer: remove palette_dirty, rely on terminal state 2026-01-20 11:34:53 -08:00
Mitchell Hashimoto
8786745969 renderer: don't access shared state for custom shader color palettes 2026-01-20 11:25:27 -08:00
ClearAspect
8d2eb280db custom shaders: add colorscheme information to shader uniforms
Adds palette and color scheme uniforms to custom shaders, allowing
custom shaders to access terminal color information:

  - iPalette[256]: Full 256-color terminal palette (RGB)
  - iBackgroundColor, iForegroundColor: Terminal colors (RGB)
  - iCursorColor, iCursorText: Cursor colors (RGB)
  - iSelectionBackgroundColor, iSelectionForegroundColor: Selection
colors (RGB)

Colors are normalized to [0.0, 1.0] range and update when the palette
changes via OSC sequences or configuration changes. The palette_dirty
flag tracks when colors need to be refreshed, initialized to true to
ensure correct colors on new surfaces.
2026-01-20 11:15:09 -08:00
Mitchell Hashimoto
cb25c0a8ae build: libghostty-vt now depends on uucode directly
This doesn't add any real weight to it, we only need it for a type
definition. This fixes our example builds.
2026-01-20 10:18:47 -08:00
Martin Emde
c2deda3231 config: switch certain physical keybinds to unicode
Switches several default keybindings from physical key codes

`.physical = .equal // or .bracket_left or .bracket_right`

to unicode characters

`.unicode = '=' // or '[' or ']'`

to support alternative keyboard layouts like Dvorak and
keyboards with dedicated plus keys (like German layouts).

I found in testing that all of these must be fixed at once otherwise
the bracket physical keys overshadew the correct (for dvorak) plus key.
With this fix, tab and pane navigation (cmd+[], cmd+shift+[]), as well
as cmd+shift+equals and cmd+equals work as expected on dvoark layout on MacOS.
2026-01-20 09:58:34 -08:00
Mitchell Hashimoto
492eb40d28 gtk: add GSettings generic module and respect gtk-enable-primary-paste on gtk systems (#10328)
# Add GSettings Support for Primary Paste

Implements support for `org.gnome.desktop.interface
gtk-enable-primary-paste` to allow users to disable middle-click paste.
Also refactors GTK Settings access into a reusable generic module.

## Changes

- **NEW**: `src/apprt/gtk/gsettings.zig` - Generic GTK Settings reader
supporting `bool` and `c_int` types, portal-aware for Flatpak/Snap
- **MODIFIED**: `src/apprt/gtk/class/surface.zig` - Reads primary paste
setting and refactors gtk-xft-dpi to use new module

## Behavior
- Setting `false` → Middle-click paste blocked
- Setting `true` or unavailable → Middle-click paste works (default)
- Uses GTK Settings API which automatically uses XDG Desktop Portal in
sandboxed environments

Note: No unit tests added as this is a thin wrapper around GTK Settings
API that's already tested indirectly through surface.zig. Happy to add
tests if desired, though they would require an active display
environment and skip on most CI systems.
2026-01-20 09:49:48 -08:00
Mitchell Hashimoto
c8ffc0faa5 termio: report color scheme synchronously (#9705)
The reporting of color scheme was handled asynchronously by queuing a
handler in the surface. This could lead to race conditions where the DSR
is reported after subsequent VT sequences.

Fixes #5922
2026-01-20 09:48:43 -08:00
Mitchell Hashimoto
49b2b8d644 unicode: switch to uucode grapheme break to (mostly) match unicode spec (#9680)
This PR builds on https://github.com/ghostty-org/ghostty/pull/9678 ~so
the diff from there is included here (it's not possible to stack PRs
unless it's a PR against my own fork)--review that one first!~

This PR updates the `graphemeBreak` calculation to use `uucode`'s
`computeGraphemeBreakNoControl`, which has [tests in
uucode](215ff09730/src/x/grapheme.zig (L753))
that confirm it passes the `GraphemeBreakTest.txt` (minus some
exceptions).

Note that the `grapheme_break` (and `grapheme_break_no_control`)
property in `uucode` incorporates `emoji_modifier` and
`emoji_modifier_base`, diverging from UAX #29 but matching UTS #51. See
[this comment in
uucode](215ff09730/src/grapheme.zig (L420-L434))
for details.

The `grapheme_break_no_control` property and
`computeGraphemeBreakNoControl` both assume `control`, `cr`, and `lf`
have been filtered out, matching the current grapheme break logic in
Ghostty.

This PR keeps the `Precompute.data` logic mostly equivalent, since the
`uucode` `precomputedGraphemeBreak` lacks benchmarks in the `uucode`
repository (it was benchmarked in [the original PR adding `uucode` to
Ghostty](https://github.com/ghostty-org/ghostty/pull/8757)). Note
however, that due to `grapheme_break` being one bit larger than
`grapheme_boundary_class` and the new `BreakState` also being one bit
larger, the state jumps up by a factor of 8 (u10 -> u13), to 8KB.

## Benchmarks

~I benchmarked the old `main` version versus this PR for
`+grapheme-break` and surprisingly this PR is 2% faster (?). Looking at
the assembly though, I'm thinking something else might be causing that.
Once I get to the bottom of that I'll remove the below TODO and include
the benchmark results here.~

When seeing the speedup with `data.txt` and maybe a tiny speedup on
English wiki, I was surprised given the 1KB -> 8KB tables. Here's what
AI said when I asked it to inspect the assembly:
https://ampcode.com/threads/T-979b1743-19e7-47c9-8074-9778b4b2a61e, and
here's what it said when I asked it to predict the faster version:
https://ampcode.com/threads/T-3291dcd3-7a21-4d24-a192-7b3f6e18cd31

It looks like two loads got reordered and that put the load that
depended on stage1 -> stage2 -> stage3 second, "hiding memory latency".
So that makes the new one faster when looking up the `grapheme_break`
property. These gains go away with the Japanese and Arabic benchmarks,
which spend more time processing utf8, and may even have more grapheme
clusters too.

### with data.txt (200 MB ghostty-gen random utf8)

<img width="1822" height="464" alt="CleanShot 2025-11-26 at 08 42 03@2x"
src="https://github.com/user-attachments/assets/56d4ee98-21db-4eab-93ab-a0463a653883"
/>

### with English wiki dump

<img width="2012" height="506" alt="CleanShot 2025-11-26 at 08 43 15@2x"
src="https://github.com/user-attachments/assets/230fbfb7-272d-4a2a-93e7-7268962a9814"
/>

### with Japanese wiki dump

<img width="2008" height="518" alt="CleanShot 2025-11-26 at 08 43 49@2x"
src="https://github.com/user-attachments/assets/edb408c8-a604-4a8f-bd5b-80f19e3d65ee"
/>

### with Arabic wiki dump

<img width="2010" height="512" alt="CleanShot 2025-11-26 at 08 44 25@2x"
src="https://github.com/user-attachments/assets/81a29ac8-0586-4e82-8276-d7fa90c31c90"
/>


TODO:

* [x] Take a closer look at the assembly and understand why this PR (8
KB vs 1 KB table) is faster on my machine.
* [x] _(**edit**: checking this off because it seems unnecessary)_ If
this turns out to actually be unacceptably slower, one possibility is to
switch to `uucode`'s `precomputedGraphemeBreak` which uses a 1445 byte
table since it uses a dense table (indexed using multiplication instead
of bitCast, though, which did show up in the initial benchmarks from
https://github.com/ghostty-org/ghostty/pull/8757 a small amount.)

AI was used in some of the uucode changes in
https://github.com/ghostty-org/ghostty/pull/9678 (Amp--primarily for
tests), but everything was carefully vetted and much of it done by hand.
This PR was made without AI with the exception of consulting AI about
whether the "Prepend + ASCII" scenario is common (hopefully it's right
about that being uncommon).
2026-01-20 09:44:15 -08:00
Mitchell Hashimoto
2e0141fcdf config: clarify selection-word-boundary docs 2026-01-20 09:38:41 -08:00
mauroporras
9b7c20f500 refactor: use u21 for Unicode codepoints and Zig 0.15 ArrayList
- Change all codepoint types from u32 to u21 to align with Zig stdlib
- Update ArrayList to use Zig 0.15 unmanaged pattern (.empty)
- Remove unnecessary @intCast when encoding UTF-8
- Fix formatEntry to use stack-allocated buffer
2026-01-20 09:37:31 -08:00
mauroporras
6f662d70bc refactor: clean up selection-word-chars documentation and formatting 2026-01-20 09:37:31 -08:00