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
```
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.
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.
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.
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.
## 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)
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.
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 />
[](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>
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.
This is a solution for #2107.
When a user right-clicks, and there's no existing selection, the
existing behavior is to try to select the word under the cursor:
3548acfac6/src/Surface.zig (L3740-L3742)
This PR tweaks that behavior _slightly_: If there's a link under our
cursor, as determined by `linkAtPos`, select the link (to copy with the
right-click context menu). Otherwise, select the word as before.
As noted in #2107, this matches the behavior of iTerm and Gnome
Terminal.
It's worth noting that `linkAtPos` already does the right thing in terms
of checking the links from config and their highlight/hover states
(modified by Ctrl or Super depending on platform).
3548acfac6/src/Surface.zig (L3896-L3901)
It also therefore respects `link-url` from config.
3548acfac6/src/config/Config.zig (L3411-L3416)
By using `linkAtPos`, we get all that behavior for free. In practical
terms, that means:
- If I'm holding Ctrl so a link is underlined and I right click on it,
it selects the underlined link.
- If I'm not holding Ctrl and I right click on a link that is not
underlined, it selects the word as before.
- This behavior respects per-platform key bindings and user config
settings.
`linkAtPos` requires that the render state mutex is held. I believe it's
safe to call because we're inside a block holding the mutex:
3548acfac6/src/Surface.zig (L3702-L3704)
**AI Disclosure:** I used Gemini CLI to help me with this PR because
while I have many years of programming experience, this is my first time
writing Zig. I prototyped a couple different approaches with AI before
landing on this one, so AI generated various prototypes and I chose the
final imlementation. I've verified that my code compiles and works as
intended.
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`).