1555 Commits

Author SHA1 Message Date
Qwerasd
5cf7575967 fix(PageList): when cloning, explicitly set cols
Otherwise pages may have the wrong width if they were resized down with
a fast path that just chanes the size without adjusting capacity at all.
2025-01-13 13:50:29 -08:00
Mitchell Hashimoto
7aed08be40 terminal: keep track of colon vs semicolon state in CSI params
Fixes #5022

The CSI SGR sequence (CSI m) is unique in that its the only CSI sequence
that allows colons as delimiters between some parameters, and the colon
vs. semicolon changes the semantics of the parameters.

Previously, Ghostty assumed that an SGR sequence was either all colons
or all semicolons, and would change its behavior based on the first
delimiter it encountered.

This is incorrect. It is perfectly valid for an SGR sequence to have
both colons and semicolons as delimiters. For example, Kakoune sends
the following:

    ;4:3;38;2;175;175;215;58:2::190:80:70m

This is equivalent to:

  - unset (0)
  - curly underline (4:3)
  - foreground color (38;2;175;175;215)
  - underline color (58:2::190:80:70)

This commit changes the behavior of Ghostty to track the delimiter per
parameter, rather than per sequence. It also updates the SGR parser to
be more robust and handle the various edge cases that can occur. Tests
were added for the new cases.
2025-01-13 12:47:07 -08:00
Damien Mehala
fc99c99b74 code review 2025-01-11 22:19:42 +01:00
Damien Mehala
95fc1d64c8 parse ConEmu OSC9;5 2025-01-11 17:24:13 +01:00
Mitchell Hashimoto
7ae94e145d terminal: ConEmu OSC9 parsing is more robust and correct
Related to #4485

This commit matches ConEmu's parsing logic[^1] more faithfully. For any
substate that requires a progress, ConEmu parses so long as there is a
number and then just ignores the rest.

For substates that don't require a progress, ConEmu literally ignores
everything after the state.

Tests cover both.

[^1]: 740b09c363/src/ConEmuCD/ConAnsiImpl.cpp (L2264)
2025-01-06 15:41:44 -08:00
Damien Mehala
ead241f38c Merge branch 'main' into dmehala/conemu-osc9 2025-01-05 21:58:45 +01:00
Mitchell Hashimoto
e3c94210f2 docs: improve terminal page list documentation (#4648)
This PR enhances clarity and comprehension for the terminal page list
documentation.
2025-01-05 12:53:55 -08:00
Alexandre Antonio Juca
057b196024 docs: improve terminal page list documentation 2025-01-05 21:50:20 +01:00
Mitchell Hashimoto
68624e6c45 parse ConEmu OSC9;3 (#4644)
This PR implements support for the [ConEmu OSC9;3 escape
sequence](https://conemu.github.io/en/AnsiEscapeCodes.html#OSC_Operating_system_commands).

| Sequence | Description |
| - | - |
ESC ] 9 ; 3 ; ”txt“ ST | Change ConEmu Tab to txt. Set empty string to
return original Tab text

#3125
2025-01-05 12:35:43 -08:00
Mitchell Hashimoto
f5f30605a8 feat: parse ConEmu OSC9;2 (#4447)
This PR implements support for the [ConEmu OSC9;2 escape
sequence](https://conemu.github.io/en/AnsiEscapeCodes.html#OSC_Operating_system_commands).

| Sequence | Description |
| - | - |
ESC ] 9 ; 2 ; ”txt“ ST | Show GUI MessageBox ( txt ) for any purposes.
2025-01-04 14:37:01 -08:00
Damien Mehala
d3334ecb06 [3/12] parse ConEmu OSC9;3 2025-01-04 16:19:19 +01:00
Damien Mehala
8a3aae2caf code review
- Change show_message_box from struct to string.
- Add tests:
  - Blank message
  - Spaces only message
  - No trailing semicolon OSC 9;2
2025-01-03 12:01:50 +01:00
David Leadbeater
4cb2fd4f79 Add negative test for temporary filename and fix other tests 2025-01-03 12:09:49 +11:00
David Leadbeater
c9dfcd2781 kittygfx: Ensure temporary files are named per spec
Temporary files used with Kitty graphics must have
"tty-graphics-protocol" somewhere in their full path.

https://sw.kovidgoyal.net/kitty/graphics-protocol/#the-transmission-medium
2025-01-03 11:15:03 +11:00
Damien Mehala
8d7ed3e0fc feat: parse ConEmu OSC9;2 2025-01-03 00:26:06 +01:00
Damien Mehala
9d9fa60ece code review
- Default to 100 if the value can't be parsed as an integer or
  is missing entirely.
2025-01-02 23:57:53 +01:00
Mitchell Hashimoto
fc545cd048 fix: handle intermediate bytes in CSI and ESC sequences (#4063)
This adds missing handling for CSI and ESC commands.

Fixes: https://github.com/ghostty-org/ghostty/issues/3122

Supersedes: #3132
2025-01-02 13:53:19 -08:00
Damien Mehala
c98d207eb9 code review
- Add test with invalid value.
- Fix inspector compilation.
2025-01-02 00:13:55 +01:00
Damien MEHALA
b52e76334e feat: parse ConEmu OSC9;1 2025-01-01 22:21:47 +01:00
Qwerasd
4543cdeac8 fix(terminal): correct SGR direct color parsing 2024-12-31 15:05:25 -05:00
Qwerasd
5ba8fee38a test/terminal: add failing sgr direct color parsing test
Behavior checked against xterm
2024-12-31 14:57:54 -05:00
Bryan Lee
a1f7a95763 Add pin order assertion in Pin.pageIterator 2024-12-31 01:14:56 +08:00
Ayman Bagabas
66681f94e0 fix: handle intermediate bytes in CSI and ESC sequences
This adds missing handling for CSI and ESC commands.

Fixes: https://github.com/ghostty-org/ghostty/issues/3122
2024-12-30 18:26:05 +03:00
Mitchell Hashimoto
cd2e2b801a Screen.cursorScrollAboveRotate memory corruption fix (#3129)
Extracted from #3110

Initial fix is relatively basic, and catching it with a test only
required a little bit of extra scrutiny of the cursor state after one of
the tests that we already had.

However, the fix revealed faulty dirty tracking logic throughout the
`cursorScrollAbove` function (and therefore bad results that were being
tested for when they should not have been). I've ended up clarifying
things, fixing the asserted dirty states in all the `cursorScrollAbove`
tests, and then finally implementing another very trivial fix that
catches the mistake.

Fixing the dirty tracking is really just an exercise in correctness
though, since when the scroll happens it inherently invalidates the
viewport, and therefore will trigger a full rebuild in the renderer...
unless, I guess, another operation is performed that cancels things out
and results in the viewport pin being in the same place as the previous
render, but that seems an exceptionally difficult scenario to make
happen on purpose much less accidentally.

This PR is almost entirely changes to comments and tests, there are only
2 lines of real code it changes, the one added to the start of
`cursorScrollAbove` and the one modified at the start of
`cursorScrollAboveRotate`. I believe these changes are entirely safe. (I
wonder if they might have a bad effect on our `vtebench` scrolling
performance though...)
2024-12-26 06:30:27 -08:00
Qwerasd
d030155c81 fix: unconditionally mark cursor row dirty in cursorScrollAbove
explained in comment
2024-12-25 21:15:58 -05:00
Qwerasd
67f51dcffd test: correct scroll above dirty assertions
Accounts for improved behavior due to prior memory corruption fix for
`cursorScrollAboveRotate` and reveals a new problem in a different
`cursorScrollAbove` sub-function.
2024-12-25 21:14:18 -05:00
Qwerasd
b68c161d98 improve comments
The new diagrams are different due to changes that have happened since
they were last generated.
2024-12-25 21:00:36 -05:00
Qwerasd
6d034d04a0 fix: memory corruption in Screen.cursorScrollAboveRotate
Unless it's guaranteed that the new pin is in the same page as the old
one, `cursor.page_pin` should only be updated through `cursorChangePin`,
not directly.
2024-12-25 20:09:20 -05:00
Qwerasd
a387e680ed test: add additional checks to scroll above cross-page test
Reveals a memory corruption issue caused by the direct assignment of
`cursor.page_pin` instead of using the `cursorChangePin` method.
2024-12-25 20:08:05 -05:00
Qwerasd
8f0dcb9d91 fix: memory corruption in Screen.cursorAbsolute
We call `cursorChangePin` which may invalidate the provided pin if it
needs to adjust the page capacity, and as such we should consider the
pin we pass in to it invalid afterwards, and access it through cursor
instead.
2024-12-25 19:04:35 -05:00
Qwerasd
b89e87c80d test: add failing test for Screen.cursorAbsolute memory corruption 2024-12-25 19:04:35 -05:00
Jan200101
7027147c76 terminal: support progress for ConEmu pause and error state 2024-12-25 14:38:34 -08:00
Mitchell Hashimoto
3356ce18d1 fix: correct handling of CTC and DECST8C (#3121)
Cursor Tab Control (CTC) `CSI <n> W` has a default value of 0, which is
the same as setting a tab stop at the current cursor position. Set Tab
at every 8th Column (DECST8C) `CSI ? 5 W` is a DEC private sequence that
resets the tab stops to every 8th column.

Reference: https://vt100.net/docs/vt510-rm/DECST8C.html
Reference:
https://wezfurlong.org/ecma48/07-control.html?highlight=ctc#7210-ctc---cursor-tabulation-control
Reference:
https://gitlab.gnome.org/GNOME/vte/-/blob/master/src/parser-seq.py#L596-L601
Fixes: https://github.com/ghostty-org/ghostty/issues/3120
2024-12-25 14:36:22 -08:00
Mitchell Hashimoto
eacba35d19 terminal: parse ConEmu progress OSC 9 (#3124)
Fixes #3119
Supersedes #3099 

ConEmu and iTerm2 both use OSC 9 to implement different things. iTerm2
uses it to implement desktop notifications, while ConEmu uses it to
implement various OS commands.

Ghostty has supported iTerm2 OSC 9 for a while, but it didn't (and
doesn't) support ConEmu OSC 9. This means that if a program tries to
send a ConEmu OSC 9 to Ghostty, it will turn into a desktop
notification.

This commit adds parsing for ConEmu OSC 9 progress reports. This means
that these specific syntaxes can never be desktop notifications, but
they're quite strange to be desktop notifications anyway so this should
be an okay tradeoff.

This doesn't actually _do anything with the progress reports_, it just
parses them so that they don't turn into desktop notifications.

cc @Jan200101
2024-12-25 13:35:13 -08:00
Jan200101
c3bf7246f6 terminal: parse ConEmu progress OSC 9
Fixes #3119

ConEmu and iTerm2 both use OSC 9 to implement different things. iTerm2
uses it to implement desktop notifications, while ConEmu uses it to
implement various OS commands.

Ghostty has supported iTerm2 OSC 9 for a while, but it didn't (and
doesn't) support ConEmu OSC 9. This means that if a program tries to
send a ConEmu OSC 9 to Ghostty, it will turn into a desktop notification.

This commit adds parsing for ConEmu OSC 9 progress reports. This means
that these specific syntaxes can never be desktop notifications, but
they're quite strange to be desktop notifications anyway so this should
be an okay tradeoff.

This doesn't actually _do anything with the progress reports_, it just
parses them so that they don't turn into desktop notifications.
2024-12-25 13:23:21 -08:00
Ayman Bagabas
48368471a7 fix: correct handling of CTC and DECST8C
Cursor Tab Control (CTC) `CSI <n> W` has a default value of 0, which is
the same as setting a tab stop at the current cursor position. Set Tab
at every 8th Column (DECST8C) `CSI ? 5 W` is a DEC private sequence that
resets the tab stops to every 8th column.

Reference: https://vt100.net/docs/vt510-rm/DECST8C.html
Reference: https://wezfurlong.org/ecma48/07-control.html?highlight=ctc#7210-ctc---cursor-tabulation-control
Reference: https://gitlab.gnome.org/GNOME/vte/-/blob/master/src/parser-seq.py#L596-L601
Fixes: https://github.com/ghostty-org/ghostty/issues/3120
2024-12-25 23:40:04 +03:00
David Rubin
8efa638110 optimize Style.eql using PackedStyle 2024-12-25 00:20:06 -08:00
Mitchell Hashimoto
d7542ec504 terminal: address typos in style struct 2024-12-24 12:08:05 -08:00
David Rubin
5052be3efe add some comments 2024-12-24 10:07:58 -08:00
David Rubin
120a2b9597 optimize Style hashing to be single-shot 2024-12-24 09:35:05 -08:00
Mitchell Hashimoto
67fb7d0bee Fix UB in style hashing by using autoHash, but keep XxHash3
Back out "perf(styles): greatly improve style.hash performance"
This backs out commit 3bfe4cd25ca7a5ae4d4084818b86ada9236b3bb5, but
keeps the hash algorithm as XxHash3 which showed improvements in
performance.
2024-12-24 07:22:31 -08:00
Qwerasd
3bfe4cd25c perf(styles): greatly improve style.hash performance
By switching to one-shot hashing of the raw bytes of the struct with
XxHash3 instead of using `autoHash` with Wyhash, a performance gain of
around 20% can be observed in DOOM-fire-zig.
2024-12-23 22:05:14 -05:00
Qwerasd
56cbbd940b perf(RefCountedSet): make swap metric prioritize high refcount items
This experimentally yields a ~20% performance improvement as measured by
running DOOM-fire-zig, which is honestly a lot more than I expected.
2024-12-23 21:41:51 -05:00
Mitchell Hashimoto
53c41255eb terminal: selectionString only applies x offset on first/last page
Fixes #2841

We were incorrectly applying the start/end x offset for the first/last
row of every single page. If a selection spanned multiple pages this
would trim data incorrectly.

Unit test updated to cover this case.
2024-12-23 14:39:20 -08:00
Mitchell Hashimoto
cecf2d8699 Fix RefCountedSet issue(s) (#3093)
Fixes #2497 

While investigating the issue I added an integrity check that found a
problem hiding in the insert logic that was unrelated- in fixing that I
greatly simplified the insert logic.

It turns out that #2497 is ultimately just a case of bad luck,
pathological inputs that result in very non-uniform hashes so the
clustering overwhelms things. The solution was just to add a check and
claim we're out of memory.

I tried adding an entropy folding function to fix the hash a little but
it had a measurable negative impact on performance and isn't necessary
so I've not included it here. Currently there's an open PR to Zig to
[add RapidHash](https://github.com/ziglang/zig/pull/22085), which is the
successor to Wyhash and apparently has much better statistical
characteristics on top of being faster. I imagine it will land in time
for 0.14 so whenever we update to 0.14 we should probably switch our
standard hash function to RapidHash, which I imagine should yield
improvements across the board.

Using the AutoHasher may also be not the best idea, I may explore ways
to improve how we generate our style hashes in the future.
2024-12-23 14:10:05 -08:00
Mitchell Hashimoto
809593473b terminal: PageList.pin doesn't allow out of bounds x values
Fixes #2958

The y was alround bounded but we allowed any x value and assumed the
caller would handle it. This is not the case so we now check the x and
return null if it's out of bounds (same as y, which was already doing
this).
2024-12-23 13:27:19 -08:00
Qwerasd
cb60f9d1da fix(RefCountedSet): Gracefully handle pathological cases
Poor hash uniformity and/or a crafted or unlucky input could cause the
bounds of the PSL stats array to be exceeded, which caused memory
corruption (not good!) -- we avoid such cases now by returning an
OutOfMemory error if we're about to insert and there's an item with a
PSL in the last slot.
2024-12-23 16:03:26 -05:00
Qwerasd
b44ebed798 Fix a scenario that could cause issues under some conditions
I don't know if this actually occurs in a way that can cause serious
problems, but it's better to nip it in the bud.
2024-12-23 15:45:30 -05:00
Qwerasd
a51871a3f7 RefCountedSet: simplify insert logic, cleanup, improve comments
Previous logic had multiple issues that were hiding in edge cases of
edge cases with the ressurected item handling among other things; the
added assertIntegrity method finds these issues, the primary one being
an edge case where an ID is present in two different buckets.

Added more comments to explain logic in more detail and fixed a couple
little things like always using `+%` when incrementing the probe pos,
and replacing a silent return on an integrity issue that should be
impossible (`table[item.meta.bucket] != id`) with an assert.
2024-12-23 15:43:57 -05:00
Jon Parise
82756f8b4c terminal: handle consecutive .input's in clearPrompt
Our semantic prompts are row-based, so the last prompt marker set on a
row "wins". In the case of at least our bash shell integration, this
means that consecutive prompt lines will all be marked as .input (OSC
133;B -- end-of-prompt, start of input).

Previously, clearPrompt() identified the current prompt's "area" by
searching upward from the current row until it encounters a .prompt
marker or some command output. In the bash case, .prompt is never the
dominant ("last") marker, so clearPrompt() would aggressively clear all
immediately preceding consecutive prompts.

With this change, we'll stop searching upwards when we encounter some
command output, a .prompt marker, _or another .input marker_. That last
case prevents clearPrompt() from unintentionally clearing earlier prompt
lines.

There may be improvements we can make to the way that our bash shell
integration emits semantic prompt markers, but I think this logic is
generally sound for all cases, and it specifically improves the current
bash prompt-clearing experience.
2024-12-16 21:06:15 -08:00