Based on both context and observed behavior, "now" was intended to be "not" in the paragraph describing the behavior of `focus-follows-mouse` is set to `true`.
Fixes#3114
I forgot that the format gets parsed as a Zig string so putting it in
already parsed made `+list-keybinds` incorrect. It worked either way but
this fixes the `+list-keybinds` CLI action.
# Description
This commit introduces the ability to launch the quick terminal in the
middle position.

## Note to reviewer
- The quick terminal is currently centered. Should we consider adding a
top offset to better align with the screenshot in [the issue](#2494 )?
Should it be configurable?
- On large monitors, half the visible frame might be excessively large.
To mitigate, I am planning to implement #2384 but we should probably
agree on a good default maximum width/height in middle position.
- I also figured out, reloading the configuration does not update the
quick terminal configuration. That is also an issue I will try to fix.
Resolves#2494
I agree to relicense my commit to MIT.
Fixes#3106
Related to #2838
Discussion in #2363
This breaks fixterms encodings for these specific keys so that shells
and other programs that rely on the legacy encoding for these keys will
work by default.
This only does this for macOS because for whatever reason during the
large beta period, only macOS users found this as lacking.
If users want to restore fixterms behaviors, they can rebind these keys
as `unbind`.
From: https://github.com/ghostty-org/ghostty/discussions/2363#discussioncomment-11645228
The justification there makes sense to me and I think it would be a good
change to make. Copied here:
> There are a few bindings that feel a little weird on macOS. My suggestions:
>
> (1) Equalize Splits
> ```
> keybind = shift+opt+equal=unbind
> keybind = ctrl+cmd+equal=equalize_splits
> ```
> The default hijacks the `±` character on US keyboards. Believe it or not, I do use ± in the terminal. Ctrl+cmd+equal matches the arrow key bindings in the Window > Resize Split menu and thus looks more elegant and is easier to memorize.
>
> (2) Jump to Prompt
> ```
> keybind = cmd+up=jump_to_prompt:-1
> keybind = cmd+down=jump_to_prompt:1
> ```
> These are the bindings in Terminal.app. The default shift-cmd-up/down is usually associated with extending a selection. Cmd-up/down are available (they currently act as simple up/down). I bind them additionally to the defaults.
In a [Discord
thread](https://discord.com/channels/1005603569187160125/1319727495473397791)
someone was having problems running Ghostty because they had
accidentally created a directory called `~/.config/ghostty/config`.
Instead of erroring out Ghostty would hang trying to "read" the
directory. Crashes can also happen if the argument to `--config-file` on
the CLI or a recursively loaded config file.
This patch prevents those hangs or crashes by refusing to read anything
but a plain file (symbolic links to plain files continue to work as
well).
Subsumes #2580 (which has multiple conflicts with main due to recent
changes to metrics); I figured it'd be easier to just implement it this
way.
#2580 claimed to solve #2487 but I don't think it really does- ideally
we can think of a good way to configure each individual cursor type, but
I don't wanna just do something ad hoc and add a bunch of config keys
blindly so I limited the scope of this.
## Description
Introduce a setting allowing to customize the behavior of the quick
terminal when it loses focus. By default, the quick terminal will
automatically hide. However, you can now configure it to remain open by
setting `quick-terminal-autohide: false`.
Resolves#2558
Introduce a setting allowing to customize the behavior of the quick terminal
when it loses focus. By default, the quick terminal will automatically hide.
However, you can now configure it to remain open by setting
`quick-terminal-autohide: false`.
Resolves#2558
Ghostty now has a release channel build configuration. Current valid
values are "tip" and "stable" but I imagine more will be added in the
future.
The release channel is inferred whether the version we specify with the
`-Dversion-string` build flag has a prerelease tag or not. If it does,
the release channel is "tip". If it doesn't, the release channel is
"stable".
This also adds a configuration to specify the release channel for
auto-updates for the macOS application.
This prevents forcibly injecting any configured shell integration into
the command's environment. Automatic shell detection is enabled, unless
shell integration has been explicitly disabled.
**Context**
Currently, if there are multiple keybindings with a shared prefix,
they are grouped into a nested series of Binding.Sets.
For example, as reported in #2734, the following bindings:
keybind = ctrl+z>1=goto_tab:1
keybind = ctrl+z>2=goto_tab:2
keybind = ctrl+z>3=goto_tab:3
Result in roughly the following structure (in pseudo-code):
Keybinds{
Trigger("ctrl+z"): Value.leader{
Trigger("1"): Value.leaf{action: "goto_tab:1"},
Trigger("2"): Value.leaf{action: "goto_tab:2"},
Trigger("3"): Value.leaf{action: "goto_tab:3"},
}
}
When this is formatted into a string (and therefore in +list-keybinds),
it is turned into the following as Value.format just concatenates
all the sibling bindings ('1', '2', '3') into consecutive bindings,
and this is then fed into a single configuration entry:
keybind = ctrl+z>1=goto_tab:1>3=goto_tab:3>2=goto_tab:2
**Fix**
To fix this, Value needs to produce a separate configuration entry
for each sibling binding in the Value.leader case.
So we can't produce the entry (formatter.formatEntry) in Keybinds
and need to pass information down the Value tree to the leaf nodes,
each of which will produce a separate entry with that function.
This is accomplished with the help of a new Value.formatEntries method
that recursively builds up the prefix for the keybinding,
finally flushing it to the formatter when it reaches a leaf node.
This is done without extra allocations by using a FixedBufferStream
with the same buffer as before, sharing it between calls to nested
siblings of the same prefix.
**Testing**
Besides the included unit tests, I ran the GLFW-based app
and verified that the resulting binary produced the correct output
with `ghostty +show-config`:
```
❯ .zig-cache//o/02a32e7ba516d2692577a46f1a0df682/ghostty +show-config 2>/dev/null | grep goto_tab
keybind = ctrl+z>1=goto_tab:1
keybind = ctrl+z>3=goto_tab:3
keybind = ctrl+z>2=goto_tab:2
```
**Caveats**
We do not track the order in which the bindings were added
so the order is not retained in the formatConfig output.
Resolves#2734
A common issue for US-centric users of a terminal is that the "option"
key on macOS is not treated as the "alt" key in the terminal.
## Background
macOS does not have an "alt" key, but instead has an "option" key. The "option"
key is used for a variety of purposes, but the troublesome behavior for some
(and expected/desired behavior for others) is that it is used to input special
characters.
For example, on a US standard layout, `option-b` inputs `∫`. This is not
a typically desired character when using a terminal and most users will
instead expect that `option-b` maps to `alt-b` for keybinding purposes
with whatever shell, TUI, editor, etc. they're using.
On non-US layouts, the "option" key is a critical modifier key for
inputting certain characters in the same way "shift" is a critical
modifier key for inputting certain characters on US layouts.
We previously tried to change the default for `macos-option-as-alt`
to `left` (so that the left option key behaves as alt) because I had the
wrong assumption that international users always used the right option
key with terminals or were used to this. But very quickly beta users
with different layouts (such as German, I believe) noted that this is
not the case and broke their idiomatic input behavior. This behavior was
therefore reverted.
## Solution
This confusing behavior happened frequently enough that I decided to
implement the more complex behavior in this commit. The new behavior is
that when a US layout is active, `macos-option-as-alt` defaults to true
if it is unset. When a non-US layout is active, `macos-option-as-alt`
defaults to false if it is unset. This happens live as users change
their keyboard layout.
**An important goal of Ghostty is to have zero-config defaults** that
satisfy the majority of users. Fiddling with configurations is -- for
most -- an annoying task and software that works well enough out of the
box is delightful. Based on surveying beta users, I believe this commit
will result in less configuration for the majority of users.
## Other Terminals
This behavior is unique amongst terminals as far as I know.
Terminal.app, Kitty, iTerm2, Alacritty (I stopped checking there) all
default to the default macOS behavior (option is option and special
characters are inputted).
All of the aforementioned terminals have a setting to change this
behavior, identical to Ghostty (or, Ghostty identical to them perhaps
since they all predate Ghostty).
I couldn't find any history where users requested the behavior of
defaulting this to something else for US based keyboards. That's
interesting since this has come up so frequently during the Ghostty
beta!
**Context**
Currently, if there are multiple keybindings with a shared prefix,
they are grouped into a nested series of Binding.Sets.
For example, as reported in #2734, the following bindings:
keybind = ctrl+z>1=goto_tab:1
keybind = ctrl+z>2=goto_tab:2
keybind = ctrl+z>3=goto_tab:3
Result in roughly the following structure (in pseudo-code):
Keybinds{
Trigger("ctrl+z"): Value.leader{
Trigger("1"): Value.leaf{action: "goto_tab:1"}),
Trigger("2"): Value.leaf{action: "goto_tab:2"}),
Trigger("3"): Value.leaf{action: "goto_tab:3"}),
}
}
When this is formatted into a string (and therefore in +list-keybinds),
it is turned into the following as Value.format just concatenates
all the sibling bindings ('1', '2', '3') into consecutive bindings,
and this is then fed into a single configuration entry:
keybind = ctrl+z>1=goto_tab:1>3=goto_tab:3>2=goto_tab:2
**Fix**
To fix this, Value needs to produce a separate configuration entry
for each sibling binding in the Value.leader case.
So we can't produce the entry (formatter.formatEntry) in Keybinds
and need to pass information down the Value tree to the leaf nodes,
each of which will produce a separate entry with that function.
This is accomplished with the help of a new Value.formatEntries method
that recursively builds up the prefix for the keybinding,
finally flushing it to the formatter when it reaches a leaf node.
This is done without extra allocations by using a FixedBufferStream
with the same buffer as before, sharing it between calls to nested
siblings of the same prefix.
**Caveats**
We do not track the order in which the bindings were added
so the order is not retained in the formatConfig output.
Resolves#2734
Fixes#2908
When loading `config-file`, we need to ensure that all loaded
configuration is loaded _prior_ to any `-e` values from the CLI.
To do this, I inserted a new `-e` special tag type in our replay steps.
This can be used to find when `-e` starts and ensure it remains at the
end of replay steps when the replay steps are being modified.
This commit also found a similar (but not exercised) issue where this
could happen with light/dark themeing.