Commit Graph

567 Commits

Author SHA1 Message Date
Jon Parise
04fecd7c07 os/shell: introduce ShellCommandBuilder
This builder is an efficient way to construct space-separated shell
command strings.

We use it in setupBash to avoid using an intermediate array of arguments
to construct our bash command line.
2025-12-12 08:59:44 -05:00
Jon Parise
c0deaaba4e bash: use a shell command for shell integration
Prior to #7044, on macOS, our shell-integrated command line would be
executed under exec -l, which causes bash to be started as a login
shell. This matches the macOS platform norms.

The change to direct command execution meant that we'd skip that path,
and bash would start as a normal interactive (non-login) shell on macOS.
We fixed this in #7253 by adding `--login` to the `bash` direct command
on macOS.

This avoided some of the overhead of starting an extra process just to
get a login shell, but it unfortunately doesn't quite match the bash
environment we get when shell integration isn't enabled (namely, $0
doesn't get the login-shell-identifying "-" prefix).

Instead, this change implements the approach proposed in #7254, which
switches the bash shell integration path to use a .shell command, giving
us the same execution environment as the non-shell-integrated command.
2025-12-11 17:02:14 -05:00
Mitchell Hashimoto
86cd489701 terminal/tmux: introduce command queue for viewer 2025-12-08 09:00:38 -08:00
Mitchell Hashimoto
ec5a60a119 terminal/tmux: make sure we always have space for one action 2025-12-08 07:27:37 -08:00
Mitchell Hashimoto
b26c42f4a6 terminal/tmux: better formatting for notifications and actions 2025-12-08 07:00:44 -08:00
Mitchell Hashimoto
52dbca3d26 termio: hook up tmux viewer 2025-12-08 07:00:43 -08:00
Mitchell Hashimoto
0d75a78747 terminal/tmux: start viewer state machine 2025-12-08 07:00:43 -08:00
Jon Parise
da014d98cd zsh: improve ZDOTDIR documentation
The main thing to emphasize is that end users should never source
.zshenv directly; it's only meant to be used as part of our shell
injection environment.

At the moment, there's no way to guard against accidentally use, but we
can consider making e.g. GHOSTTY_SHELL_FEATURES always defined in this
environment to that it can be used to differentiate the cases.

In practice, it's unlikely that people actually source this .zshenv
script directly, so hopefully this additional documentation clarifies
things well enough.
2025-12-01 19:07:50 -05:00
Mitchell Hashimoto
dbfc3eb679 Remove unused imports 2025-11-27 13:37:53 -08:00
Mitchell Hashimoto
ad8a6e0642 search thread needs to take an allocated needle 2025-11-26 08:50:04 -08:00
Qwerasd
212598ed66 perf: add branch hints based on real world data
+ move stream ESC state entry outside of `nextNonUtf8`
2025-11-18 20:43:31 -07:00
Qwerasd
6d5b4a3426 perf: replace std.debug.assert with inlined version
See doc comment in `quirks.zig` for reasoning
2025-11-17 12:13:56 -07:00
Mitchell Hashimoto
580f9f057b convert t.screen to t.screens.active 2025-11-14 15:40:31 -08:00
Mitchell Hashimoto
3aff5f0aff ScreenSet 2025-11-14 15:08:10 -08:00
Mitchell Hashimoto
2daecd94a5 renderer: use terminal color state, remove color messages 2025-10-30 09:52:39 -07:00
Mitchell Hashimoto
77343bb06e terminal: move color state fully into the terminal for fg/bg/cursor 2025-10-30 09:33:21 -07:00
Mitchell Hashimoto
cabca0aca8 terminal: unify palette functionality into shared type DynamicPalette 2025-10-30 09:15:43 -07:00
Mitchell Hashimoto
580262c96f terminal: add ReadonlyStream that updates terminal state (#9346)
This adds a new stream handler implementation that updates terminal
state in reaction to VT sequences, but doesn't perform any of the
actions that would require responses (e.g. queries).

This is exposed in two ways: first, as a standalone `ReadonlyStream` and
`ReadonlyHandler` type that contains all the implementation. Second, as
a convenience func on `Terminal` as `vtStream` and `vtHandler` which
return their respective types preconfigured to update the calling
terminal state.

This dramatically simplifies libghostty-vt usage from Zig (and will
eventually be exposed to C, too) since a Terminal on its own is ready to
go as a full VT parser and state machine without needing to build any
custom types!

There's a second big bonus here which is that our `stream_readonly.zig`
tests are true end-to-end tests for raw bytes to terminal state. This
will let us test a wider variety of situations more broadly. To start,
there are only a handful of tests implemented here.

**AI disclosure:** Amp wrote basically this whole thing, but I reviewed
it. https://ampcode.com/threads/T-3490efd2-1137-4112-96f6-4bf8a0141ff5
2025-10-25 14:52:33 -07:00
Mitchell Hashimoto
1d03451d4f terminal: OSC color operations 2025-10-25 07:03:21 -07:00
Mitchell Hashimoto
e13f9b9e8c terminal: kitty color 2025-10-25 06:42:20 -07:00
Mitchell Hashimoto
e49694439c terminal: setAttribute 2025-10-24 11:53:25 -07:00
Mitchell Hashimoto
5ba451d073 terminal: configureCharset 2025-10-24 11:27:48 -07:00
Mitchell Hashimoto
4d028dac1f terminal: some osc types 2025-10-24 11:17:31 -07:00
Mitchell Hashimoto
bce1164ae6 terminal: cursor style 2025-10-24 07:26:04 -07:00
Mitchell Hashimoto
fd0f9bb843 terminal: device attributes 2025-10-24 07:17:44 -07:00
Mitchell Hashimoto
e347ab6915 terminal: device attributes 2025-10-24 07:08:34 -07:00
Mitchell Hashimoto
109376115b terminal: convert dcs 2025-10-23 21:29:18 -07:00
Mitchell Hashimoto
6902d89d91 terminal: convert APC 2025-10-23 21:24:31 -07:00
Mitchell Hashimoto
b91149f0fe terminal: simple esc dispatch 2025-10-23 21:18:51 -07:00
Mitchell Hashimoto
9cd4594356 terminal: active status display 2025-10-23 21:14:21 -07:00
Mitchell Hashimoto
f68ea7c907 terminal: many more conversions 2025-10-23 21:10:25 -07:00
Mitchell Hashimoto
2520e27aef terminal: kitty keyboard actions 2025-10-23 20:55:08 -07:00
Mitchell Hashimoto
b7ea979f38 terminal: zero-arg actions 2025-10-23 20:47:02 -07:00
Mitchell Hashimoto
0df4d5c5a4 terminal: margins 2025-10-23 20:37:34 -07:00
Mitchell Hashimoto
c1e57dd330 terminal: setprotectedmode 2025-10-23 20:31:17 -07:00
Mitchell Hashimoto
25eee9379d terminal: request mode 2025-10-23 20:26:14 -07:00
Mitchell Hashimoto
b6ac4c764f terminal: modify_other_keys 2025-10-23 20:26:11 -07:00
Mitchell Hashimoto
94a8fa05cb terminal: convert modes 2025-10-23 20:07:45 -07:00
Mitchell Hashimoto
dc5406781f terminal: many more conversions 2025-10-23 19:56:13 -07:00
Mitchell Hashimoto
37016d8b89 terminal: erase/insert lines, characters, etc. 2025-10-23 16:44:49 -07:00
Mitchell Hashimoto
b0fb3ef9a9 terminal: erase display conversion 2025-10-23 16:38:10 -07:00
Mitchell Hashimoto
b5da54d925 terminal: horizontal tab 2025-10-23 16:28:38 -07:00
Mitchell Hashimoto
ccd821a0ff terminal: convert cursor movements 2025-10-23 16:22:43 -07:00
Mitchell Hashimoto
2ef89c153a terminal: convert C0 2025-10-23 15:52:42 -07:00
Mitchell Hashimoto
f7189d14b9 terminal: convert Stream to use Action tagged union 2025-10-23 15:50:56 -07:00
Mitchell Hashimoto
1b86691896 termio: use a union to represent how a process is started (#9278)
This cleans up some of our termio exec code by unifying process launch
state into a single union type. This makes it easier to distinguish
between the current two mutually exclusive modes of launching a process:
fork/exec and flatpak dbus commands.

It also ensures everyplace we touch related to process launching is
forced to address every case (exhaustive switch handling). I did find
one resource cleanup bug based on this cleanup, which is also fixed
here. This just improves memory slightly so it's not a big deal.

If we add future ways to launch processes, we can add a new union case.
For example, I originally had a `posix_spawn` option while I was
experimenting with that before abandoning it (see #9274).
2025-10-19 20:43:28 -07:00
Mitchell Hashimoto
014a2e0042 termio: color change operations must gracefully handle renderer mailbox full (#9224)
Fixes #9191

This changes our color change operations from writing to the renderer
mailbox directly to using our `rendererMailboxWriter` function which
handles the scenario where the mailbox is full by yielding the lock,
waking up the renderer, and retrying later.

This is a known deadlock scenario we've worked around since the private
beta days, but unfortunately this slipped through and I didn't catch it
in review.

What happens here is it's possible with certain escape sequences for the
IO thread to saturate other mailboxes with messages while holding the
terminal state lock. This can happen to any thread. This ultimately
leads to starvation and all threads deadlock.

Our IO thread is the only thread that produces this kind of massive
stream of events while holding the lock, so we have helpers in it to
attempt to queue (cheap, fast) and if that fails then to yield the lock,
wakeup the target thread, requeue, and grab the lock again (expensive,
slow).
2025-10-15 16:01:26 -07:00
Jon Parise
e5247f6d10 termio: reimplement OSC 7 URI handling (#9193)
This reimplements the MAC address-aware URI parsing logic used by the
OSC 7 handler and adds an additional .raw_path option that returns the
full, unencoded path string (including query and fragment values), which
is needed for compliant kitty-shell-cwd:// handling.

Notably, this implementation takes an options-based approach that allows
these additional behaviors to be enabled at runtime. It also leverages
two std.Uri.parse guarantees:

1. Return slices point into the original text string.
2. .raw components don't require unescaping (.percent_encoded does).

The implementation is in a new 'os.uri' module because its now generic
enough to not be hostname-oriented.

We use os.uri.parseUri and its parsing options to reimplement our OSC 7
file-style URI handling. This has two advantages:

First, it fixes kitty-shell-cwd scheme handling. This scheme expects the
full, unencoded path string, whereas the file scheme expects normal URI
percent encoding. This was preventing paths containing "special" URI
characters (like "path?") from working correctly in our bash, zsh, and
elvish shell integrations, which report working directories using the
kitty-shell-cwd scheme. (fish uses file URIs, which work as expected.)

Second, we can greatly simplify our hostname and path string handling
because we can now rely on the "raw" std.Uri component form to always
provide the correct representation.

Lastly, this lets us remove the previous URI-related code from the
os.hostname module, restoring its focus to hostname-related functions.

See: #5289
2025-10-14 12:12:45 -07:00
Mitchell Hashimoto
17a20e5b1c termio: don't start scroll timer if its already active (#9195)
This might fix #9191, but since I don't have a reproduction I can't be
sure. In any case, this is a bad bug that should be fixed.

The issue is that we weren't checking our scroll timer completion state.
This meant that if `start_scroll_timer` was called multiple times within
a single loop tick, we'd enqueue our completion multiple times, leading
to various undefined behaviors.

If we don't enqueue anything else in the interim, this is safe by
chance. But if we enqueue something else, then we'd hit a queue
assertion failure and honestly I'm not totally sure what would happen.

I wasn't able to trigger the "bad" case, but I was able to trigger the
benign case very easily. Our other timers such as the renderer cursor
timer already have this protection.

Let's fix this and continue looking...
2025-10-13 20:44:32 -07:00
Mitchell Hashimoto
4e3e0ed056 Zig 0.15: Flatpak 2025-10-03 07:10:43 -07:00