6865 Commits

Author SHA1 Message Date
Tristan Partin
f2fa47bca7 apprt/gtk: fix typo
I had a copy-paste error when I used right instead of up.

Signed-off-by: Tristan Partin <tristan@partin.io>
2025-04-21 12:12:54 -05:00
Mitchell Hashimoto
6d2685b5a2 add toggle command palette binding 2025-04-21 10:05:30 -07:00
Mitchell Hashimoto
8615dfb73d libghostty: add API for getting commands 2025-04-21 08:32:05 -07:00
Mitchell Hashimoto
a34134e643 input: defind Command struct and default commands 2025-04-21 08:32:05 -07:00
Kat
160b26708c Remove note about default from bell-features→system's description. 2025-04-21 03:24:05 +00:00
Mitchell Hashimoto
31b2ac4b79 macOS: Do not send control characters as UTF8 keyboard text
Fixes a regression where `ctrl+enter` was not encoding properly since
our input stack changes.
2025-04-19 06:54:36 -07:00
Mitchell Hashimoto
18d6faf597 macOS: translation mods should never have "control"
This also lets us get rid of our `C-/` special handling to prevent a
system beep.
2025-04-18 15:10:57 -07:00
Mitchell Hashimoto
65356c25da macOS/libghostty: rework keyboard input handling (#7121)
This is a large refactor of the keyboard input handling code in
libghostty and macOS. Previously, libghostty did a lot of things that
felt out of scope or was repeated work due to lacking context. For
example, libghostty would do full key translation from key event to
character (including unshifted translation) as well as managing dead key
states and setting the proper preedit text.

This is all information the apprt can and should have on its own.
NSEvent on macOS already provides us with all of this information,
there's no need to redo the work. The reason we did in the first place
is mostly historical: libghostty powered our initial macOS port years
ago when we didn't have an AppKit runtime yet.

This cruft has already practically been the source of numerous issues,
e.g.
https://github.com/ghostty-org/ghostty/issues/5558, but many other hacks
along the way, too.

This commit pushes all preedit (e.g. dead key) handling and key
translation
including unshifted keys up into the caller of libghostty.

Besides code cleanup, a practical benefit of this is that key event
handling on macOS is now about 10x faster on average. That's because
we're avoiding repeated key translations as well as other unnecessary
work. This should have a meaningful impact on input latency but I didn't
measure the full end-to-end latency.

A scarier part of this commit is that key handling is not well tested
since its a GUI component. I suspect we'll have some fallout for certain
keyboard layouts or input methods, but I did my best to run through
everything I could think of.

This also fixes one bug where preedit state didn't properly clear when
changing keyboard layouts. This now does and matches the behavior
of native apps like TextEdit and Terminal.app
2025-04-18 12:06:32 -07:00
Tristan Partin
85268d4f82 apprt/gtk: refactor action callbacks to reduce code duplication (#7126)
It was getting very monotonous reading the code.
2025-04-18 13:11:12 -05:00
Tristan Partin
793c727986 apprt/gtk: refactor action callbacks to reduce code duplication
It was getting very monotonous reading the code.

Signed-off-by: Tristan Partin <tristan@partin.io>
2025-04-18 12:54:36 -05:00
phanium
9bab900c75 vim: fix syntax highlight on scratch buffer 2025-04-18 21:50:24 +08:00
Mitchell Hashimoto
b3cb38c3fa macOS/libghostty: rework keyboard input handling
This is a large refactor of the keyboard input handling code in
libghostty and macOS. Previously, libghostty did a lot of things that
felt out of scope or was repeated work due to lacking context. For
example, libghostty would do full key translation from key event to
character (including unshifted translation) as well as managing dead key
states and setting the proper preedit text.

This is all information the apprt can and should have on its own.
NSEvent on macOS already provides us with all of this information,
there's no need to redo the work. The reason we did in the first place
is mostly historical: libghostty powered our initial macOS port years
ago when we didn't have an AppKit runtime yet.

This cruft has already practically been the source of numerous issues, e.g.
#5558, but many other hacks along the way, too.

This commit pushes all preedit (e.g. dead key) handling and key translation
including unshifted keys up into the caller of libghostty.

Besides code cleanup, a practical benefit of this is that key event
handling on macOS is now about 10x faster on average. That's because
we're avoiding repeated key translations as well as other unnecessary
work. This should have a meaningful impact on input latency but I didn't
measure the full end-to-end latency.

A scarier part of this commit is that key handling is not well tested
since its a GUI component. I suspect we'll have some fallout for certain
keyboard layouts or input methods, but I did my best to run through
everything I could think of.
2025-04-17 14:24:12 -07:00
Mitchell Hashimoto
cc690eddb5 macOS: Implement basic bell features (no sound)
Fixes #7099

This adds basic bell features to macOS to conceptually match the GTK
implementation. When a bell is triggered, macOS will do the following:

  1. Bounce the dock icon once, if the app isn't already in focus.
  2. Add a bell emoji (🔔) to the title of the surface that triggered
     the bell. This emoji will be removed after the surface is focused
     or a keyboard event if the surface is already focused. This
     behavior matches iTerm2.

This doesn't add an icon badge because macOS's dockTitle.badgeLabel API
wasn't doing anything for me and I wasn't able to fully figure out
why...
2025-04-15 10:41:15 -07:00
Mitchell Hashimoto
da6b478fbe terminal: clear correct row on index operation in certain edge cases
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.
2025-04-14 15:54:00 -07:00
Mitchell Hashimoto
c23b389cf1 gtk: implement bell (#7087)
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.
2025-04-14 11:19:19 -07:00
Leah Amelia Chen
3a973c692a gtk(bell): add bell-features config option
Co-authored-by: Jeffrey C. Ollie <jeff@ocjtech.us>
2025-04-15 00:18:05 +08:00
Leah Amelia Chen
abd7d9202b gtk(bell): mark tab as needing attention on bell 2025-04-14 23:44:13 +08:00
Leah Amelia Chen
10a591fba2 gtk(bell): use gdk.Surface.beep for bell
Co-authored-by: Jeffrey C. Ollie <jeff@ocjtech.us>
2025-04-14 23:44:13 +08:00
Leah Amelia Chen
a0760cabd6 gtk: implement bell
Co-authored-by: Jeffrey C. Ollie <jeff@ocjtech.us>
2025-04-14 23:44:13 +08:00
Mitchell Hashimoto
6d3f97ec1e Mouse drag while clicked should cancel any mouse link actions
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.
2025-04-13 14:56:40 -07:00
Andrej Daskalov
dcc2e9eaf8 Merge branch 'main' into mk-localization 2025-04-11 21:47:07 +02:00
Francesc Arpi Roca
d749e1b87e i18n: fix the "deny" catalan translation 2025-04-11 10:20:53 -07:00
Francesc Arpi Roca
a092d7ae42 i18n: add catalan translations 2025-04-11 10:20:44 -07:00
g
c19f2aa1bc Add pt-BR translations to ghostty 2025-04-11 10:12:06 -07:00
Mitchell Hashimoto
9751f43529 Add Spanish translations (419 = Latin America) (#6940)
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!
2025-04-11 10:11:26 -07:00
MiguelElGallo
a9f9abd615 add Spanish (Latin America) locale support 2025-04-11 10:08:44 -07:00
Emir SARI
913c6dc7df feat: Add Turkish translations 2025-04-11 09:57:19 -07:00
Nico Geesink
e52aad5dea Add nl_NL (Dutch) translations 2025-04-11 09:50:44 -07:00
Mitchell Hashimoto
52ac670913 CODEOWNERS 2025-04-11 09:47:11 -07:00
blackzeshi
2b0a81d982 Merge branch 'main' into add_russian 2025-04-11 09:45:55 -07:00
blackzeshi
df5dd1858a add russian translation 2025-04-11 09:45:37 -07:00
Kirwiisp
e2a8a3243c i18n: Add French translation 2025-04-11 09:41:49 -07:00
Lon Sagisawa
20ef2150de i18n: Add Japanese translations 2025-04-11 09:38:37 -07:00
halosatrio
1222e80eb1 i18n: add id_ID code locale 2025-04-11 09:26:00 -07:00
Mitchell Hashimoto
d7f75b348d config: allow commands to specify whether they shell expand or not (#7044)
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.
2025-04-10 16:32:18 -04:00
Mitchell Hashimoto
d4a5e5f88e elvish: use kitty-shell-cwd:// to report pwd (#7033)
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.
2025-04-10 16:19:26 -04:00
Mitchell Hashimoto
722d41a359 config: allow commands to specify whether they shell expand or not
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.
2025-04-10 13:15:14 -07:00
Jeffrey C. Ollie
cb1b447e8c gtk: fix forcing the window theme to light or dark
Fixes #7038
2025-04-08 18:33:12 -05:00
Jon Parise
5b4976f6ef elvish: fix platform:hostname function call syntax 2025-04-08 10:54:26 -04:00
Jon Parise
b213c157f0 elvish: use kitty-shell-cwd:// to report pwd
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.
2025-04-08 10:38:57 -04:00
Mitchell Hashimoto
dc0b9a703d fix(kittygfx): accept commands with no control data (#7023)
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.
2025-04-07 20:31:41 -07:00
Hanna
a8f760c6d2 fix: undo accidental replace 2025-04-07 16:10:50 -04:00
Hanna
77f5fe2560 fix: parenthesis are unneeded around builtins 2025-04-07 16:09:43 -04:00
Hanna
9808c13796 refactor: use builtin hostname function 2025-04-07 16:02:53 -04:00
Qwerasd
b64f49a0d7 fix(kittygfx): accept commands with no control data
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.
2025-04-07 13:31:51 -06:00
Fabian Boehm
df174a74f8 shell-integration: Fix condition for sudo
A missing ";" meant the check for $TERMINFO was never executed.
2025-04-07 21:20:21 +02:00
Mitchell Hashimoto
60da3cf6a0 shell-integration: switch to $GHOSTTY_SHELL_FEATURES (#6871)
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
2025-04-04 17:05:37 -04:00
Mitchell Hashimoto
17a19e4837 docs: use Command instead of super for macOS (#6987)
Command is the name Apple uses for this key and that's printed on the
keyboard 😉
2025-04-03 21:31:05 -04:00
Mitchell Hashimoto
e19b5a150a libghostty: Action CValue should be untagged extern union
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.
2025-04-03 20:57:31 -04:00
Simon Olofsson
af0004eb52 docs: use Command instead of super for macOS
Command is the name Apple uses for this key and that's printed on the keyboard 😉
2025-04-03 11:03:48 +02:00