This fixes#10265 and thus also the remaining part of #9718 and likely
#10250.
The issue was that when using `insertLines` and `deleteLines` to
generate scrolling in a region that spans a page boundary, rows that are
replaced by a row from a different page lose their dirty flags in the
clone operation, since the flag is part of the data that gets cloned.
The solution is to set the dirty flag again after the clone, just like
the non-cloning branch does after the pointer swap.
**AI disclosure:** Amp is the MVP here. I prompted it with the
hypothesis I developed in #10265 (that this happens when the scrolling
region spans a page boundary), supplemented with insight I gained from
perusing asciicast files (that the offending scrolling operations are
always triggered by `CSI 1 L` or `CSI 1 M`, that is,
`Terminal.insertLines` or `Terminal.deleteLines`). Amp figured out the
rest and drafted the fix and tests. For free!
I cleaned up the tests and then pushed back a bit against the logic
behind the fix, which led to a better understanding and what I think is
a more appropriate fix. I can explain the details if there's interest,
or people can just skim the thread here:
https://ampcode.com/threads/T-019bb0d6-5334-744a-b78a-7c997ec1fade.
As of NixOS/nixpkgs#473413, `zig.hook` no longer supports
`zig_default_flags`, and now they can and must be provided in
`zigBuildFlags` instead.
Updating also requires removing gnome-xorg since it has been removed
from nixpkgs.
`nix flake check` succeeds on my system (x86_64-linux), with a couple
deprecation warnings that I believe aren't important.
`+help` and `+version` is missing from completions, even though they are
working actions and are referenced in discussion template
[here](https://github.com/ghostty-org/ghostty/pull/7012). This PR adds
the completion for fish (as that is the shell that I use).
This was an unused codepath and it complicates some things I'd like to
do, such as resetting our pools during resize. It complicates those
paths because if a user provides a pool we can't reset it (because other
things might be in it). It's best to own the pools. And since we didn't
reuse pools anyway, let's remove that.
Note this was previously used by our old render state mechanism (before
`terminal.RenderState`) as a way for the renderer to speed up clones by
having a preheated pool that was likely the right size before every
frame. Since we changed methods, we don't need it.
This is recommended for ongoing performance:
https://github.com/ziglang/zig/issues/17851
Likely not an issue for this particular use case which is why it never
bit us; we don't actively modify this map much once it is created. But,
its still good hygiene and ArrayHashMap made some of the API usage
nicer.
We previously only compared the hashes for triggers and actions for hash
map equality. I'm genuinely surprised this never bit us before because
it can result in false positives when two different values have the same
hash. Fix that up!
The big comment in `search/screen.zig` describes the solution well. The
problem is that our search is discrete by page and a page can contain
some amount of history as well.
For zero-scrollback screens, we need to fully prune any history lines.
For everyone else, everything in the PageList is scrollable and visible
so we should search it.
Partial #10227
This fixes the scrollbar part of #10227, but not the search part.
The way PageList works is that max_size is advisory: we always allocate
on page boundaries so we always have _some_ extra space (usually, unless
you ask for a byte-perfect max size). Normally this is fine, it doesn't
cause any real issues. And this has been true since Ghostty 1.0.
But with the introduction of scrollbars (and search), we were exposing
this hidden space to the user. To fix this, the easiest approach is to
special-case the zero-scrollback scenario, since it is already
documented that scrollback limit is not _exact_ and is subject to some
minimum allocations. But with zero-scrollback we really expect NOTHING.
Partial #10227
This fixes the scrollbar part of #10227, but not the search part.
The way PageList works is that max_size is advisory: we always allocate
on page boundaries so we always have _some_ extra space (usually, unless
you ask for a byte-perfect max size). Normally this is fine, it doesn't
cause any real issues.
But with the introduction of scrollbars (and search), we were exposing
this hidden space to the user. To fix this, the easiest approach is to
special-case the zero-scrollback scenario, since it is already
documented that scrollback limit is not _exact_ and is subject to some
minimum allocations. But with zero-scrollback we really expect NOTHING.
This replaces the OSC parser with one that only uses a state machine to
determine which OSC is being handled, rather than parsing the whole OSC.
Once the OSC command is determined the remainder of the data is stored
in a buffer until the terminator is found. The data is then parsed to
determine the final OSC command.