Fixes#7066
This fixes an issue where under certain conditions (expanded below), we
would not clear the correct row, leading to the screen having duplicate
data.
This was triggered by a page state of the following:
```
+----------+ = PAGE 0
... : :
4305 |1ABCD00000|
4306 |2EFGH00000|
:^ : = PIN 0
+-------------+ ACTIVE
4307 |3IJKL00000| | 0
+----------+ :
+----------+ : = PAGE 1
0 | | | 1
1 | | | 2
+----------+ :
+-------------+
```
Namely, the cursor had to NOT be on the last row of the first page,
but somewhere on the first page. Then, when an `index` (LF) operation
was performed the result would look like this:
```
+----------+ = PAGE 0
... : :
4305 |1ABCD00000|
4306 |2EFGH00000|
+-------------+ ACTIVE
4307 |3IJKL00000| | 0
:^ : : = PIN 0
+----------+ :
+----------+ : = PAGE 1
0 |3IJKL00000| | 1
1 | | | 2
+----------+ :
+-------------+
```
The `3IJKL` line was duplicated. What was happening here is that we
performed the index operation correctly but failed to clear the cursor
line as expected.
This is because we were always clearing the first row in the page
instead of the row of the cursor.
Test added.
This PR implements a more lightweight alternative to #5326 that contains
features that I personally think Just Make Sense for the bell.
No configs, no GStreamer stuff, just sane defaults to get us started.
Fixes#7077
This follows pretty standard behavior across native or popular applications
on both platforms macOS and Linux. The basic behavior is that if you
do a mouse down event and then drag the mouse beyond the current
character, then any mouse up actions are canceled (beyond emiting the
event itself).
This fixes a specific scenario where you could do the following:
1. Click anywhere (mouse down)
2. Drag over a valid link
3. Press command/control (to activate the link)
4. Release the mouse button (mouse up)
5. The link is triggered
Now, step 3 and step 5 do not happen. Links are not even highlighted in
this scenario. This matches iTerm2 on macOS which has a similar
command-to-activate-links behavior.
Hi!
I have followed the instructions and added translations for Spanish,
Country Latin America 419 according to
[this](https://localizely.com/locale-code/es-419/) and other online
sources.
In the provided links there was no references to 419, but I created it
via the suggested command:
`msginit -i po/com.mitchellh.ghostty.pot -l es_419.UTF-8 -o
"po/es_419.UTF-8.po" `
Glad to be able to contribute to this excellent product!
Cheers!
Fixes#7032
This introduces a syntax for `command` and `initial-command` that allows
the user to specify whether it should be run via `/bin/sh -c` or not.
The syntax is a prefix `direct:` or `shell:` prior to the command, with
no prefix implying a default behavior as documented.
Previously, we unconditionally ran commands via `/bin/sh -c`, primarily
to avoid having to do any shell expansion ourselves. We also leaned on
it as a crutch for PATH-expansion but this is an easy problem compared
to shell expansion.
For the principle of least surprise, this worked well for configurations
specified via the config file, and is still the default. However, these
configurations are also set via the `-e` special flag to the CLI, and it
is very much not the principle of least surprise to have the command run
via `/bin/sh -c` in that scenario since a shell has already expanded all
the arguments and given them to us in a nice separated format. But we
had no way to toggle this behavior.
This commit introduces the ability to do this, and changes the defaults
so that `-e` doesn't shell expand. Further, we also do PATH lookups
ourselves for the non-shell expanded case because thats easy (using
execvpe style extensions but implemented as part of the Zig stdlib). We
don't do path expansion (e.g. `~/`) because thats a shell expansion.
So to be clear, there are no two polar opposite behavioes here with
clear semantics:
1. Direct commands are passed to `execvpe` directly, space separated.
This will not handle quoted strings, environment variables, path
expansion (e.g. `~/`), command expansion (e.g. `$()`), etc.
2. Shell commands are passed to `/bin/sh -c` and will be shell expanded
as per the shell's rules. This will handle everything that `sh`
supports.
In doing this work, I also stumbled upon a variety of smaller
improvements that could be made:
- A number of allocations have been removed from the startup path that
only existed to add a null terminator to various strings. We now have
null terminators from the beginning since we are almost always on a
system that's going to need it anyways.
- For bash shell integration, we no longer wrap the new bash command in
a shell since we've formed a full parsed command line.
- The process of creating the command to execute by termio is now unit
tested, so we can test the various complex cases particularly on macOS
of wrapping commands in the login command.
- `xdg-terminal-exec` on Linux uses the `direct:` method by default
since it is also assumed to be executed via a shell environment.
OSC 7's standard body is a percent-encoded file:// URL. There isn't an
easy way for us to percent-encode the path ($pwd) component here without
implementing a custom function.
Instead, switch to the kitty-shell-cwd:// scheme, which Kitty introduced
to ease this implementation challenge in shell scripts. It accepts the
path string verbatim, without an encoding.
In Ghostty, we accept both the file:// and kitty-shell-cwd:// schemes,
and we attempt to URI-decode them both, so in practice this is more
about the "correctness" of this protocol than a functional change. It's
also possible we might decide to treat these schemes differently in the
runtime, like Kitty does.
Also, fix the `platform:hostname` function call syntax.
This introduces a syntax for `command` and `initial-command` that allows
the user to specify whether it should be run via `/bin/sh -c` or not.
The syntax is a prefix `direct:` or `shell:` prior to the command,
with no prefix implying a default behavior as documented.
Previously, we unconditionally ran commands via `/bin/sh -c`, primarily
to avoid having to do any shell expansion ourselves. We also leaned on
it as a crutch for PATH-expansion but this is an easy problem compared
to shell expansion.
For the principle of least surprise, this worked well for configurations
specified via the config file, and is still the default. However, these
configurations are also set via the `-e` special flag to the CLI, and it
is very much not the principle of least surprise to have the command run via
`/bin/sh -c` in that scenario since a shell has already expanded all the
arguments and given them to us in a nice separated format. But we had no
way to toggle this behavior.
This commit introduces the ability to do this, and changes the defaults
so that `-e` doesn't shell expand. Further, we also do PATH lookups
ourselves for the non-shell expanded case because thats easy (using
execvpe style extensions but implemented as part of the Zig stdlib). We don't
do path expansion (e.g. `~/`) because thats a shell expansion.
So to be clear, there are no two polar opposite behavioes here with
clear semantics:
1. Direct commands are passed to `execvpe` directly, space separated.
This will not handle quoted strings, environment variables, path
expansion (e.g. `~/`), command expansion (e.g. `$()`), etc.
2. Shell commands are passed to `/bin/sh -c` and will be shell expanded
as per the shell's rules. This will handle everything that `sh`
supports.
In doing this work, I also stumbled upon a variety of smaller
improvements that could be made:
- A number of allocations have been removed from the startup path that
only existed to add a null terminator to various strings. We now
have null terminators from the beginning since we are almost always
on a system that's going to need it anyways.
- For bash shell integration, we no longer wrap the new bash command
in a shell since we've formed a full parsed command line.
- The process of creating the command to execute by termio is now unit
tested, so we can test the various complex cases particularly on
macOS of wrapping commands in the login command.
- `xdg-terminal-exec` on Linux uses the `direct:` method by default
since it is also assumed to be executed via a shell environment.
OSC 7's standard body is a percent-encoded file:// URL. There isn't an
easy way for us to percent-encode the path ($pwd) component here without
implementing a custom function.
Instead, switch to the kitty-shell-cwd:// scheme, which Kitty introduced
to ease this implementation challenge in shell scripts. It accepts the
path string verbatim, without an encoding.
In Ghostty, we accept both the file:// and kitty-shell-cwd:// schemes,
and we attempt to URI-decode them both, so in practice this is more
about the "correctness" of this protocol than a functional change. It's
also possible we might decide to treat these schemes differently in the
runtime, like Kitty does.
This sort of command is treated as valid by Kitty so we should too. In
fact, it occurs with the example `send-png` script provided in the docs
for the protocol.
This sort of command is treated as valid by Kitty so we should too. In
fact, it occurs with the example `send-png` script provided in the docs
for the protocol.
This change consolidates all three opt-out shell integration environment
variables into a single opt-in $GHOSTTY_SHELL_FEATURES variable. Its
value is a comma-delimited list of the enabled shell feature names (e.g.
"cursor,title").
$GHOSTTY_SHELL_FEATURES is set at runtime and automatically added to the
shell environment. Its value is based on the shell-integration-features
configuration option.
$GHOSTTY_SHELL_FEATURES is only set when at least one shell feature is
enabled. It won't be set when 'shell-integration-features = false'.
$GHOSTTY_SHELL_FEATURES lists only the enabled shell feature names. We
could have alternatively gone in the opposite direction and listed the
disabled features, letting the scripts assume each feature is on by
default like we did before, but I think this explicit approach is a
little safer and easier to reason about / debug.
It also doesn't support the "no-" negation prefix used by the config
system (e.g. "cursor,no-title"). This simplifies the implementation
requirements of our (multiple) shell integration scripts, and because
$GHOSTTY_SHELL_FEATURES is derived from shell-integration-features, the
user-facing configuration interface retains that expressiveness.
$GHOSTTY_SHELL_FEATURES is intended to primarily be an internal concern:
an interface between the runtime and our shell integration scripts. It
could be used by people with particular use cases who want to manually
source those scripts, but that isn't the intended audience.
... and because the previous $GHOSTTY_SHELL_INTEGRATION_NO_* variables
were also meant to be an internal concern, this change does not include
backwards compatibility support for those names.
One last advantage of a using a single $GHOSTTY_SHELL_FEATURES variable
is that it can be easily forwarded to e.g. ssh sessions or other shell
environments.
See: #5070
Fixes#6962
I believe this is an upstream bug
(https://github.com/ziglang/zig/issues/23454), where Zig is allowing
extern unions to be tagged when created via type reification. This
results in a CValue that has an extra trailing byte (the tag).
This wasn't causing any noticeable issues for Ghostty for some reason
but others using our pattern were seeing issues. And I did confirm that
our CValue was indeed tagged and was the wrong byte size. I assume Swift
was just ignoring it because it was extra data. I don't know, but we
should fix this in general for libghostty.
See #6957
We were not considering GTK's internal scale factor that converts between
"surface coordinates" and actual device coordinates, and that worked fine
until the scale factor reached 2x (200%).
Since the code is now dependent on the scale factor (which could change
at any given moment), we also listen to scale factor changes and then
unconditionally call `winproto.syncAppearance`. Even though it's somewhat
overkill, I don't expect people to change their scale factor dramatically
all the time anyway...
We can't use nearest neighbor filtering for sampling from the atlas
because we might not actually be doing pixel perfect sampling if the
glyph has been constrained. This will change in the future, but this
will have to be set to linear for now.