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
Introduces host resources directory as a new concept: A directory
containing application resources that can only be accessed from the host
operating system. This is significant for sandboxed application runtimes
like Flatpak where shells spawned on the host should have access to
application resources to enable integrations.
Alongside this, apprt is now allowed to override the resources lookup
logic.
This adds a new CLI `ghostty +edit-config`. This will open the config
file in the user's specified `$EDITOR`. If Ghostty has never been
configured, this will also create the initial config file with some
default templated contents (the same as that which we introduced back in
Ghostty 1.0.1 or something -- not new behavior here).
This is useful on its own because it will find the correct configuration
path to open. If users are terminal users anyway (not a big stretch
since this is a terminal app), this will allow them to easily edit
config right away.
This is also forward looking: I want to replace our "Open Config" action
to open a Ghostty window executing this command so that users can edit
their config in a terminal editor. This has been heavily requested since
forever (short of a full GUI settings editor, which is not ready yet). I
don't do this in this PR but plan to in a future PR.
Related to #7433
This extracts our "launched from desktop" logic into a config option.
The default value is detection using the same logic as before, but now
this can be overridden by the user.
This also adds the systemd and dbus activation sources from #7433.
There are a number of reasons why we decided to do this:
1. It automatically gets us caching since the configuration is only
loaded once (per reload, a rare occurrence).
2. It allows us to override the logic when testing. Previously, we
had to do more complex environment faking to get the same
behavior.
3. It forces exhaustive switches in any desktop handling code, which
will make it easier to ensure valid behaviors if we introduce new
launch sources (as we are in #7433).
4. It lowers code complexity since callsites don't need to have N
`launchedFromX()` checks and can use a single value.
Sets the LANGUAGE environment variable based on the preferred languages
as reported by NSLocale.
macOS has a concept of preferred languages separate from the system
locale. The set of preferred languages is a list in priority order
of what translations the user prefers. A user can have, for example,
"fr_FR" as their locale but "en" as their preferred language. This would
mean that they want to use French units, date formats, etc. but they
prefer English translations.
gettext uses the LANGUAGE environment variable to override only
translations and a priority order can be specified by separating
the languages with colons. For example, "en:fr" would mean that
English translations are preferred but if they are not available
then French translations should be used.
To further complicate things, Apple reports the languages in BCP-47
format which is not compatible with gettext's POSIX locale format so
we have to canonicalize them. To canonicalize the languages we use
an internal function from libintl. This isn't normally available but
since we compile from source on macOS we can use it. This isn't
necessary for other platforms.
`WINDOWID` is the conventional environment variable for scripts that
want to know the X11 window ID of the terminal, so that it may call
tools like `xprop` or `xdotool`. We already know the window ID for
window protocol handling, so we might as well throw this in for
convenience.
Fixes#3953Fixes#3284
This fixes two issues. In fixing one issue, the other became apparent so
I fixed both in this one commit.
The first issue is that on macOS, the `open` command should take the
`-t` flag to open text files in a text editor. To do this, the `os.open`
function now takes a type hint that is used to better do the right
thing.
Second, the order of the paths that we attempt to open when editing a
config on macOS is wrong. Our priority when loading configs is well documented:
https://ghostty.org/docs/config#macos-specific-path-(macos-only). But
open_config does the opposite. This makes it too easy for people to have
configs that are being overridden without them realizing it.
This commit changes the order of the paths to match the documented
order. If neither path exists, we prefer AppSupport.
Fixes#2432
On macOS, processes with an NSApplicationMain entrypoint do not have
access to libc argc/argv. Instead, we must use NSProcessInfo. This
commit introduces an args iterator that uses NSProcessInfo, giving us
access to the args.
This also fixes an issue where we were not properly skipping argv0 when
iterating over the args. This happened to be fine because we happened to
ignore invalid args but it introduces a config error.