Commit Graph

13905 Commits

Author SHA1 Message Date
Steven Lu
ba16ce0249 reintroduce assertion, with adjusted limit 2026-01-21 20:03:37 +07:00
Steven Lu
2d7305a16a this appears to fix the crash. 2026-01-21 00:02:06 +07:00
Steven Lu
1e41d87709 hope to fix 2026-01-20 11:45:01 +07:00
Steven Lu
06130d40da split_tree: fix test passing wrong type to split()
The test was passing *TestView instead of *TestTree to the split()
function, which caused a compilation error.
2026-01-20 00:55:50 +07:00
Steven Lu
6db4e437ca splits: make resize_split and toggle_split_zoom non-performable with single pane
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-19 17:34:34 +07:00
Mitchell Hashimoto
250877eff6 terminal: increaseCapacity should preserve dirty flag (#10374)
This never caused any known issues, but it's a bug! `increaseCapacity`
should produce a node with identical contents, just more capacity. We
were forgetting to copy over the dirty flag.

I looked back at `adjustCapacity` and it also didn't preserve the dirty
flag so presumably downstream consumers have been handling this case
manually. But, I think semantically it makes sense for
`increaseCapacity` to preserve the dirty flag.

This bug was found by AI (while I was doing another task). I fixed it
and wrote the test by hand though.
2026-01-18 14:52:56 -08:00
Mitchell Hashimoto
8d78a82d1b ssh-cache: use AtomicFile to write the cache file (#10365)
We previously wrote our new cache file into a temporary directory and
the (atomically) renamed it to the canonical cache file path. This
rename operation unfortunately only works when both files are on the
same file system, and that's not always the case (e.g. when $TMPDIR is
on its own file system).

Instead, we can use Zig's AtomicFile to safely perform this operation
inside of the cache directory.

There's a new risk of a crash leaving the temporary file around in this
directory (and not getting cleaned up like $TMPDIR-based files), but the
probability is low and those files will only be readable by the creating
user (mode 0o600).

There's a new test cash that verifies the expected AtomicFile clean up
behavior. I also switched the file-oriented tests to use testing.tmpDir
rather than using our application-level TempDir type.

Fixes #10364

---

**AI Disclosure:** I asked Claude to write the initial test case to
verify the AtomicFile cleanup behavior.
2026-01-18 14:52:30 -08:00
Mitchell Hashimoto
676b4993e8 Update iTerm2 colorschemes (#10363)
Upstream release:
https://github.com/mbadolato/iTerm2-Color-Schemes/releases/tag/release-20260112-150707-28c8f5b
2026-01-18 14:51:50 -08:00
Mitchell Hashimoto
3ee30058ab terminal: increaseCapacity should preserve dirty flag
This never caused any known issues, but it's a bug! `increaseCapacity`
should produce a node with identical contents, just more capacity. We
were forgetting to copy over the dirty flag.

I looked back at `adjustCapacity` and it also didn't preserve the dirty
flag so presumably downstream consumers have been handling this case
manually. But, I think semantically it makes sense for
`increaseCapacity` to preserve the dirty flag.

This bug was found by AI (while I was doing another task). I fixed it
and wrote the test by hand though.
2026-01-18 14:47:12 -08:00
Jon Parise
5423d64c6a ssh-cache: use AtomicFile to write the cache file
We previously wrote our new cache file into a temporary directory and
the (atomically) renamed it to the canonical cache file path. This
rename operation unfortunately only works when both files are on the
same file system, and that's not always the case (e.g. when $TMPDIR is
on its own file system).

Instead, we can use Zig's AtomicFile to safely perform this operation
inside of the cache directory.

There's a new risk of a crash leaving the temporary file around in this
directory (and not getting cleaned up like $TMPDIR-based files), but the
probability is low and those files will only be readable by the creating
user (mode 0o600).

There's a new test cash that verifies the expected AtomicFile clean up
behavior. I also switched the file-oriented tests to use testing.tmpDir
rather than using our application-level TempDir type.
2026-01-17 20:44:22 -05:00
mitchellh
73a8d64b8a deps: Update iTerm2 color schemes 2026-01-18 00:16:59 +00:00
Mitchell Hashimoto
9fb03ba55c terminal: grow prune check should not prune if required for active (#10353)
Fixes #10352

The bug was that non-standard pages would mix the old
`growRequiredForActive` check and make our active area insufficient in
the PageList.

But, since scrollbars now require we have a cached `total_rows` that our
safety checks always verify, we can remove the old linked list traversal
and switch to some simple math in general across all page sizes.
2026-01-16 21:34:16 -08:00
Mitchell Hashimoto
464c31328e terminal: grow prune check should not prune if required for active
Fixes #10352

The bug was that non-standard pages would mix the old
`growRequiredForActive` check and make our active area insufficient in
the PageList.

But, since scrollbars now require we have a cached `total_rows` that our
safety checks always verify, we can remove the old linked list traversal
and switch to some simple math in general across all page sizes.
2026-01-16 21:26:54 -08:00
Mitchell Hashimoto
56237efeef PageList overflow detection and protection (#10337)
Fixes #10258  
Replaces #10284

1. `Page.Capacity` now uses smaller bit-width integers that represent a
true maximum capacity for various fields.
2. On 64-bit systems, a maxed out `Page.Capacity` (every field `maxInt`)
can be represented in an addressable allocation (total required memory
less than 64 bits). This means `Page.layout` can't overflow.
3. All `adjustCapacity` functions replaced with `increaseCapacity` which
doesn't allow specifying the resulting value, which makes it so overflow
is only possible in significantly fewer places, making it easier to
handle in general.
4. `increaseCapacity` can return a new error `OutOfSpace` which happens
when overflow is detected. This means that no valid page can accommodate
the desired capacity increase because we're already at the max. The
caller is expected to handle this.
5. Updated our resize so that the only possible error is system OOM, we
handle the new `OutOfSpace` by copying the recent reflowed row into a
new page and continuing.

A very, very high-level overview is below. The "overflow" here papers
over a bunch of details where the prior usize capacities flowed through
to Page.layout and ultimately RefCountedSet and other managed types
which then caused incorrect calculations on total memory size required.

```mermaid
flowchart TB
    subgraph Before["Before: adjustCapacity"]
        A1[capacity: usize] --> A2["capacity *= 2"]
        A2 --> A3{Overflow?}
        A3 -->|"Not detected"| A4["Massive allocation or crash"]
    end
    
    subgraph After["After: increaseCapacity"]
        B1["capacity: bounded int<br/>(u16/u32)"] --> B2["capacity *= 2"]
        B2 --> B3{Overflow?}
        B3 -->|"OutOfSpace error"| B4["Graceful handling:<br/>move row to new page"]
        B3 -->|"Success"| B5["Normal allocation"]
    end
    
    Before --> After
    
    classDef beforeStyle fill:#3d1a1a,stroke:#ff6b6b,color:#ff6b6b
    classDef afterStyle fill:#1a3d3a,stroke:#4ecdc4,color:#4ecdc4
    
    class A1,A2,A3,A4 beforeStyle
    class B1,B2,B3,B4,B5 afterStyle
```
2026-01-16 14:52:28 -08:00
Mitchell Hashimoto
df35363b15 terminal: more robust handling of max_page_size
not 100%
2026-01-16 14:47:53 -08:00
Mitchell Hashimoto
442a395850 terminal: ensure our std_capacity fits within max page size 2026-01-16 14:25:01 -08:00
Mitchell Hashimoto
4770aba089 Misc bug fixes (#10349)
Just fixes for a couple bugs I happened across
2026-01-16 14:13:59 -08:00
Qwerasd
69066200ef fix: handle double tmux control mode exit command 2026-01-16 16:58:58 -05:00
Mitchell Hashimoto
85a3d623b2 terminal: increaseCapacity should reach maxInt before overflow 2026-01-16 13:43:56 -08:00
Qwerasd
4e5c1dcdc1 osc: fix bad indexing for empty kv in semantic prompt 2026-01-16 16:36:37 -05:00
Qwerasd
f89b6433c2 osc: add failing test for osc 133 parsing trailing ;
This actually causes a crash lol, bad indexing of a slice with `1..0`
because it's `key.len + 1 ..` and the length is `0`.
2026-01-16 16:29:59 -05:00
Mitchell Hashimoto
ec0a150098 terminal: moveLastRowToNewPage needs to fix up total_rows 2026-01-16 13:23:55 -08:00
Mitchell Hashimoto
c9d15949d8 terminal: on reflow OutOfSpace, move last row to new page and try again 2026-01-16 13:23:55 -08:00
Mitchell Hashimoto
42321cc7d5 terminal: write to the proper cell 2026-01-16 13:23:55 -08:00
Mitchell Hashimoto
97621ece93 terminal: handle reflowRow OutOfSpace by no-op 2026-01-16 13:23:55 -08:00
Mitchell Hashimoto
25643ec806 terminal: reflowRow extract writeCell 2026-01-16 13:23:55 -08:00
Mitchell Hashimoto
d626984418 terminal: reflowCursor improve error handling on assumed cases 2026-01-16 13:23:55 -08:00
Mitchell Hashimoto
6b2455828e terminal: resizeWithoutReflowGrowCols can only fail for OOM 2026-01-16 13:23:55 -08:00
Mitchell Hashimoto
e704525887 terminal: PageList remove adjustCapacity 2026-01-16 13:23:55 -08:00
Mitchell Hashimoto
b59ac60a87 terminal: remove Screen.adjustCapacity 2026-01-16 13:23:55 -08:00
Mitchell Hashimoto
c8afc42308 terminal: switch to increaseCapacity 2026-01-16 13:09:19 -08:00
Mitchell Hashimoto
25b7cc9f2c terminal: hyperlink state uses increaseCapacity on screen 2026-01-16 13:09:19 -08:00
Mitchell Hashimoto
29d4aba033 terminal: Screen replace adjust with increaseCapacity 2026-01-16 13:09:19 -08:00
Mitchell Hashimoto
1e5973386b terminal: Screen.increaseCapacity 2026-01-16 13:09:19 -08:00
Mitchell Hashimoto
8306f96d94 terminal: PageList.increaseCapacity 2026-01-16 13:07:32 -08:00
Mitchell Hashimoto
95a23f756d terminal: more strict sizing for page capacities, max cap can fit 64-bit 2026-01-16 13:07:32 -08:00
Mitchell Hashimoto
c8295815cb terminal: fix stale cursor pin usage after cursorChangePin (#10348)
Fixes #10282

The function `cursorChangePin` is supposed to be called anytime the
cursor page pin changes, but it itself may alter the page pin if setting
up the underlying managed memory forces a page size adjustment.

Multiple callers to this function were erroneously reusing the old page
pin value.

**AI disclosure:** I had Amp help me write the test. I eyeballed and
found the bug myself, verified it by asking Amp to write the test,
reviewed that manually, then implemented the fixes manually and got it
to pass.
2026-01-16 13:03:09 -08:00
Mitchell Hashimoto
f1dbdc7965 terminal: fix stale cursor pin usage after cursorChangePin
Fixes #10282

The function `cursorChangePin` is supposed to be called anytime the
cursor page pin changes, but it itself may alter the page pin if setting
up the underlying managed memory forces a page size adjustment. 

Multiple callers to this function were erroneously reusing the old page
pin value.
2026-01-16 12:57:29 -08:00
Jon Parise
204170d052 shellcheck: move common directives to .shellcheckrc (#10343)
This simplifies our CI command line and makes it easier to document
expected usage (in HACKING.md).

There unfortunately isn't a way to set --checked-sourced or our default
warning level in .shellcheckrc, and our `find` command is still a bit
unwieldy, but this is still a net improvement.
2026-01-16 10:41:01 -05:00
Jon Parise
bf1ca59196 shellcheck: move common directives to .shellcheckrc
This simplifies our CI command line and makes it easier to document
expected usage (in HACKING.md).

There unfortunately isn't a way to set --checked-sourced or our default
warning level in .shellcheckrc, and our `find` command is still a bit
unwieldy, but this is still a net improvement.
2026-01-16 09:31:11 -05:00
Jon Parise
af2d33895d zsh: strip control characters from window title (#10341)
## Summary
- Fix literal \n appearing in window titles when running commands in zsh

## Description
The zsh shell integration was using ${(V)1} parameter expansion to set
the window title. The (V) flag converts control characters to their
visible escape sequence representations, causing commands ending with a
newline to display as command\n in the title bar.

Changed to use ${1//[[:cntrl:]]} which strips control characters
entirely, matching the behavior of the bash integration.

<img width="231" height="47" alt="image"
src="https://github.com/user-attachments/assets/356c77a1-32da-47b0-bf86-29735cc67e90"
/>

## Test

  - Open Ghostty with zsh shell integration enabled
  - Run a command (e.g., cargo install trunk)

  ---
AI Disclosure: This PR was written primarily by Claude Code. (Opus 4.5)
2026-01-16 09:07:15 -05:00
Jon Parise
ca924f4f45 zsh: improve title-related comment 2026-01-16 08:53:18 -05:00
Julian Haag
3ca8b97ca7 fix(zsh): strip control characters from window title
The zsh shell integration was using `${(V)1}` parameter expansion to set
the window title, which converts control characters to their visible
escape sequence representations. This caused commands ending with a
newline to display as `command\n` in the title bar.

Changed to use `${1//[[:cntrl:]]}` which strips control characters
entirely, matching the behavior of the bash integration.
2026-01-16 10:53:50 +01:00
Mitchell Hashimoto
26e243a919 font/shaper/coretext: Detect ligatures to avoid positioning (marking) glyphs incorrectly (#10295)
This PR implements a heuristic for detecting ligatures that then
prevents resetting to the cell grid prematurely, avoiding position
errors from glyphs that follow ligatures. The inspiration for this was
the example from https://github.com/ghostty-org/ghostty/pull/10179 that
was off.

See the giant comment for an explanation of the heuristic.

The tests for this are the following:

### Tai Tham
The Tai Tham example from
https://github.com/ghostty-org/ghostty/pull/10179 got updated since now
the marking glyph is attached to the ligature cell correctly.

Browser:
ᩉ᩠ᨿᩩ

Before:
<img width="970" height="110" alt="CleanShot 2026-01-12 at 10 02 42@2x"
src="https://github.com/user-attachments/assets/1315bbeb-0541-420a-91a1-bac39897efe3"
/>

After:
<img width="962" height="122" alt="CleanShot 2026-01-12 at 10 02 57@2x"
src="https://github.com/user-attachments/assets/ca2b3e1d-0785-462f-993c-f482d875a1e9"
/>

### Javanese

Browser:
ꦤ꧀ꦲꦸ

Before:
<img width="962" height="98" alt="CleanShot 2026-01-12 at 10 05 43@2x"
src="https://github.com/user-attachments/assets/74002334-7140-4646-806e-2194457e56c5"
/>

After:
<img width="962" height="110" alt="CleanShot 2026-01-12 at 10 05 23@2x"
src="https://github.com/user-attachments/assets/49c08ac9-98af-409c-9b0e-49a34da93597"
/>

There does seem to be a small maybe single pixel difference here, and I
didn't investigate why.

### Chakma

Browser:
𑄝𑄖𑄳𑄠𑄬

Before:
<img width="1406" height="104" alt="CleanShot 2026-01-12 at 10 07 52@2x"
src="https://github.com/user-attachments/assets/3ba7a9d8-d2a2-4e47-976a-8c7702462a49"
/>

After:
<img width="1408" height="104" alt="CleanShot 2026-01-12 at 10 08 08@2x"
src="https://github.com/user-attachments/assets/c25c4a41-b651-4109-8ded-69983fc77267"
/>

### Bengali

Browser:
রাষ্ট্রে

Before:
<img width="1370" height="84" alt="CleanShot 2026-01-12 at 10 10 42@2x"
src="https://github.com/user-attachments/assets/c59e5fc9-0e9e-4c8f-b937-025ad28866d2"
/>

After:
<img width="1370" height="96" alt="CleanShot 2026-01-12 at 10 11 00@2x"
src="https://github.com/user-attachments/assets/d108dcda-b0b5-4824-b3e4-d1e2ddb6d6de"
/>

This one doesn't match the browser, but it seems like a CoreText or font
issue.

### Log output

I've got a `log.txt` with 15k lines from "cell_offset.cluster differs
from cluster (potential ligature detected)" logs when I run
[ttylang](https://github.com/jacobsandlund/ttylang) (printing the
Universal Declaration of Human Rights in various languages).

But right now when I try to create a gist with it, I get:

<img width="1554" height="584" alt="CleanShot 2026-01-12 at 10 15 29@2x"
src="https://github.com/user-attachments/assets/b8a5dd0c-c034-45f6-a2fb-80c67f93f26f"
/>
2026-01-15 08:06:07 -08:00
Mitchell Hashimoto
24b0ff05e2 terminal: parse kitty text sizing protocol (OSC 66), redux (#10315)
#9845 redone to use the new OSC parser

Implements the VT side of #5563
2026-01-15 06:58:47 -08:00
Mitchell Hashimoto
33555be934 build(deps): bump namespacelabs/nscloud-setup-buildx-action from 0.0.20 to 0.0.21 (#10308)
Bumps
[namespacelabs/nscloud-setup-buildx-action](https://github.com/namespacelabs/nscloud-setup-buildx-action)
from 0.0.20 to 0.0.21.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a7e5254161"><code>a7e5254</code></a>
Adopt new wait command in action. (<a
href="https://redirect.github.com/namespacelabs/nscloud-setup-buildx-action/issues/12">#12</a>)</li>
<li>See full diff in <a
href="91c2e65377...a7e5254161">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=namespacelabs/nscloud-setup-buildx-action&package-manager=github_actions&previous-version=0.0.20&new-version=0.0.21)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2026-01-15 06:57:10 -08:00
Leah Amelia Chen
916b99df7c terminal: parse kitty text sizing protocol (OSC 66), redux
#9845 redone to use the new OSC parser

Implements the VT side of #5563
2026-01-15 00:13:55 +08:00
Ken VanDine
2fd3efd6cd snap: fix handling of nonexistent last_revision file (#10241)
Assuming /bin/sh is symlinked to bash, the handling of special builtin
'source' is slightly different between bash and bash-in-POSIX-mode (as a
result of being invoked through /bin/sh). Specifically errors in builtin
'source' cannot be masked with `|| true`. Compare

```
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Dec 11 11:00 /bin/sh -> bash
$ /bin/sh -c 'set -e ; source nofile || true; echo ok'
/bin/sh: line 1: source: nofile: file not found
$ /bin/bash -c 'set -e ; source nofile || true; echo ok'
/bin/bash: line 1: nofile: No such file or directory
ok
```

Thus ghostty from snap would not start at all when
$SNAP_USER_DATA/.last_revision does not exist causign the launcher
script to exit prematurely.
2026-01-14 09:47:40 -05:00
Jacob Sandlund
54f1a6ce5e Merge remote-tracking branch 'upstream/main' into ligature-detect 2026-01-14 08:56:22 -05:00
Jon Parise
5ff99ba9a0 macos: cycle through our icons in the About view (#10298)
Clicking on the icon immediately advances to the next one. Hovering on
the icon pauses the automatic cycling, and the "help" tooltip displays
the icon's configuration name (for `macos-icon`).

---


https://github.com/user-attachments/assets/5cfbd225-bbdf-4077-96c1-7da315ce02cc
2026-01-14 07:53:51 -05:00