Closes#5372
Discretionary ligatures (denoted by the OpenType feature tag `dlig`) are
sometimes used by programming fonts (e.g. Iosevka) to provide more
"complex" and uncommon ligatures that may be useful in a programming
context. Unfortunately, this has some nasty side effects with certain
Japanese fallback fonts (#5372) due to perhaps a misaligned understanding
of the OpenType spec[^spec].
The spec details that `dlig` ligatures should only be used to contract
sequences of glyphs together into one glyph, and that it should be used
only for "special effect", **at the user's preference** (emphasis mine).
Indeed, it also suggests that:
> UI suggestion: This feature should be off by default.
All of this, combined with the fact that historical, nowadays unused and
even unintelligible Kanji ligatures are explicitly included as examples
of discretionary ligatures, shows that in the Japanese context at least
that the "level of discretion" is significantly higher than what is found
in programming fonts, where it is more understood to be "opinionated and
uncommon", rather than "obsolete and unreadable".
Furthermore, it appears that a lot of common programming fonts don't even
make use of the `dlig` feature — JetBrains Mono, FiraCode and MonoLisa
lack a `dlig` feature altogether, while Inconsolata seems to only use it
for ligatures that are more commonly found in `liga` or `calt`, such as
the `->` ligature. To a lot of people, then, this change would literally
alter nothing.
Therefore, it's my opinion that we should disable `dlig` by default.
It's arguably not being used correctly in the programming font space
(or at least not in a way that's coherent with other fonts), and it only
provides a marginal benefit while potentially rendering entire sentences
in Japanese (and possibly other languages) unreadable out of the box.
If someone upgrades to tip or 1.2 and then asks "why aren't the ligatures
working anymore", then at least they can always just turn on `dlig` by
themselves.
[^spec]: https://learn.microsoft.com/en-us/typography/opentype/spec/features_ae#tag-dlig
GNU gettext simply is a PITA on certain platforms (i.e. Windows, musl
Linux, etc.) and currently it's not possible to cleanly remove i18n
from the build process, making building Ghostty on the aforementioned
platforms difficult. By providing users with a way to opt-out of the
i18n mechanisms (or opt-in, on platforms where i18n is disabled by
default) we can make sure that people at least have *some* way of
building Ghostty before i18n mechanisms can be integrated neatly.
Bumps
[actions/download-artifact](https://github.com/actions/download-artifact)
from 4.3.0 to 5.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/download-artifact/releases">actions/download-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v5.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@nebuk89</code></a> in <a
href="https://redirect.github.com/actions/download-artifact/pull/407">actions/download-artifact#407</a></li>
<li>BREAKING fix: inconsistent path behavior for single artifact
downloads by ID by <a
href="https://github.com/GrantBirki"><code>@GrantBirki</code></a> in <a
href="https://redirect.github.com/actions/download-artifact/pull/416">actions/download-artifact#416</a></li>
</ul>
<h2>v5.0.0</h2>
<h3>🚨 Breaking Change</h3>
<p>This release fixes an inconsistency in path behavior for single
artifact downloads by ID. <strong>If you're downloading single artifacts
by ID, the output path may change.</strong></p>
<h4>What Changed</h4>
<p>Previously, <strong>single artifact downloads</strong> behaved
differently depending on how you specified the artifact:</p>
<ul>
<li><strong>By name</strong>: <code>name: my-artifact</code> → extracted
to <code>path/</code> (direct)</li>
<li><strong>By ID</strong>: <code>artifact-ids: 12345</code> → extracted
to <code>path/my-artifact/</code> (nested)</li>
</ul>
<p>Now both methods are consistent:</p>
<ul>
<li><strong>By name</strong>: <code>name: my-artifact</code> → extracted
to <code>path/</code> (unchanged)</li>
<li><strong>By ID</strong>: <code>artifact-ids: 12345</code> → extracted
to <code>path/</code> (fixed - now direct)</li>
</ul>
<h4>Migration Guide</h4>
<h5>✅ No Action Needed If:</h5>
<ul>
<li>You download artifacts by <strong>name</strong></li>
<li>You download <strong>multiple</strong> artifacts by ID</li>
<li>You already use <code>merge-multiple: true</code> as a
workaround</li>
</ul>
<h5>⚠️ Action Required If:</h5>
<p>You download <strong>single artifacts by ID</strong> and your
workflows expect the nested directory structure.</p>
<p><strong>Before v5 (nested structure):</strong></p>
<pre lang="yaml"><code>- uses: actions/download-artifact@v4
with:
artifact-ids: 12345
path: dist
# Files were in: dist/my-artifact/
</code></pre>
<blockquote>
<p>Where <code>my-artifact</code> is the name of the artifact you
previously uploaded</p>
</blockquote>
<p><strong>To maintain old behavior (if needed):</strong></p>
<pre lang="yaml"><code></tr></table>
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="634f93cb29"><code>634f93c</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/download-artifact/issues/416">#416</a>
from actions/single-artifact-id-download-path</li>
<li><a
href="b19ff43027"><code>b19ff43</code></a>
refactor: resolve download path correctly in artifact download tests
(mainly ...</li>
<li><a
href="e262cbee4a"><code>e262cbe</code></a>
bundle dist</li>
<li><a
href="bff23f9308"><code>bff23f9</code></a>
update docs</li>
<li><a
href="fff8c148a8"><code>fff8c14</code></a>
fix download path logic when downloading a single artifact by id</li>
<li><a
href="448e3f862a"><code>448e3f8</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/download-artifact/issues/407">#407</a>
from actions/nebuk89-patch-1</li>
<li><a
href="47225c44b3"><code>47225c4</code></a>
Update README.md</li>
<li>See full diff in <a
href="d3f86a106a...634f93cb29">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
A couple of minor fixes that I found while exploring tonight:
- OSC 22 wasn't working on gtk-ng. Fixed by setting the cursor shape
directly on the surface.
- Removed use of deprecated property on GLArea
Fix a bug introduced by #6885
`fixZhLocale` returns locale string literal without copying it into the
buffer, causing the `LANGUAGE` environment variable to be set
incorrectly.
```log
$ LANG="" zig build run
...
debug(os_locale): setting LANGUAGE from preferred languages value=�����.UTF-8:�����.UTF-8:en_US.UTF-8:ja_CN.UTF-8
...
```
Bumps
[namespacelabs/nscloud-cache-action](https://github.com/namespacelabs/nscloud-cache-action)
from 1.2.13 to 1.2.14.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/namespacelabs/nscloud-cache-action/releases">namespacelabs/nscloud-cache-action's
releases</a>.</em></p>
<blockquote>
<h2>v1.2.14</h2>
<ul>
<li><a
href="93ab075400">Fix
post path cache summary and wipe non-cacheable contents in post
step.</a></li>
<li>[PNPM] <a
href="48cddb643a">Set
copy mode and avoid spurious warnings.</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a2c6b4830e"><code>a2c6b48</code></a>
Merge pull request <a
href="https://redirect.github.com/namespacelabs/nscloud-cache-action/issues/29">#29</a>
from namespacelabs/niklas-wipe</li>
<li><a
href="93ab075400"><code>93ab075</code></a>
Fix post path cache summary and wipe non-cacheable contents in post
step.</li>
<li><a
href="fa4ddeb1d7"><code>fa4ddeb</code></a>
Merge pull request <a
href="https://redirect.github.com/namespacelabs/nscloud-cache-action/issues/28">#28</a>
from namespacelabs/niklas-pnpm-copy</li>
<li><a
href="48cddb643a"><code>48cddb6</code></a>
Set copy mode and avoid spurious warnings.</li>
<li>See full diff in <a
href="9ff6d4004d...a2c6b4830e">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Not a lot here, ported the action accelerators which was small.
Besides that, cleaned up a bunch of explicit error sets which allowed us
to remove some forwarded errors because they're so unlikely, and could
unify others.
We only need properties for things that are bound via the blueprint
files. Otherwise, its kind of just a pain. This fixes a bug where it
wasn't being properly set initially anyways because we didn't trigger
syncAppearance.
Port with changes:
* Utilizes the Surface blueprint for defining the `PopoverMenu`
* We can't attach it directly to the Overlay using blueprints because an
overlay can only have a single child property and you can't see other
children via Blueprint. To overcome this, use a `Box`
* Utilizing a `menu` signal the window can listen to to refresh its
action map instead of digging into ancestor hierarchy.
Ports global shortcuts.
This is mostly a direct logic copy. The primary difference is I
converted `GlobalShortcuts` to a `GObject` which has a config and dbus
property and emits a trigger signal. Importantly, it's no longer tied or
dependent on the `gio.Application` in any way. The config and dbus
connection are updated as normal properties.
Verified with Valgrind we're clean. Found one memory leak I ported back
to legacy.
Without this, if you create a new tab by clicking on the split button it
will be the focus for any new input. So for example if you create a new
tab and then immediately press the space bar a bunch of new tabs will be
created. Other keypresses will just "disappear". Only by clicking in the
new tab to focus it will keyboard input go to "the right place".
As discussed here
https://github.com/ghostty-org/ghostty/discussions/8021
This fixes invalid fish shell syntax.
As an example, run ghostty like so: `XDG_CONFIG_HOME=/tmp ghostty
--shell-integration-features=ssh-env --command="/usr/bin/env fish"`.
Setting `XDG_CONFIG_HOME` to `/tmp` is just to start from the default
configs for ghostty and fish.
Before:
```
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
robbiev@neo ~/s/ghostty (fish-shell-ssh)> ssh git@github.com
env: ‘command’: No such file or directory
robbiev@neo ~/s/ghostty (fish-shell-ssh) [127]>
```
After:
```
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
robbiev@neo ~/s/ghostty (fish-shell-ssh)> ssh git@github.com
PTY allocation request failed on channel 0
Hi robbiev! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
robbiev@neo ~/s/ghostty (fish-shell-ssh) [1]>
```
(This fails correctly)
I've also tried with a correctly accessible ssh server but of course you
can't repro that easily if you don't have some place to ssh to.
```
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
robbiev@neo ~/s/ghostty (fish-shell-ssh)> ssh trinity
[robbiev@trinity:~]$ echo $TERM
xterm-ghostty
```
My understanding of the fix follows.
The script is using `command` to make sure it calls the actual ssh
binary and not some intermediate shell function with the same name (`man
command` explains).
`env` can be useful for fish compat < 3.1, where [the KEY=value syntax
was
introduced](https://fishshell.com/docs/current/faq.html#how-do-i-set-or-clear-an-environment-variable).
However because `command` is a builtin it doesn't work in this case.
So a simple solution is this, requiring fish >= 3.1
```
TERM="$ssh_term" command ssh $ssh_opts $argv
```
An
[alternative](https://serverfault.com/questions/164305/how-can-i-set-environment-variable-for-just-one-command-in-fish-shell)
for maximum fish compat could be the following:
```
begin
set -lx TERM "$ssh_term"
command ssh $ssh_opts $argv
end
```
According to `man set`, `-l` means local to the block and `-x` means
export.
I'm in favour of keeping `command` as it makes the integration more
predicable.
The reason I went with the current fix:
- It's easier to understand without knowing fish shell.
- [kat found that fish 3.1 should be widely
available](https://github.com/ghostty-org/ghostty/discussions/8021#discussioncomment-13877129).
As discussed here https://github.com/ghostty-org/ghostty/discussions/8021
This fixes invalid fish shell syntax.
As an example, run ghostty like so: `XDG_CONFIG_HOME=/tmp ghostty --shell-integration-features=ssh-env --command="/usr/bin/env fish"`. Setting XDG_CONFIG_HOME to /tmp is just to start from the default config.
Before:
```
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
robbiev@neo ~/s/ghostty (fish-shell-ssh)> ssh git@github.com
env: ‘command’: No such file or directory
robbiev@neo ~/s/ghostty (fish-shell-ssh) [127]>
```
After:
```
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
robbiev@neo ~/s/ghostty (fish-shell-ssh)> ssh git@github.com
PTY allocation request failed on channel 0
Hi robbiev! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
robbiev@neo ~/s/ghostty (fish-shell-ssh) [1]>
```
My understanding of the fix follows.
The script is using `command` to make sure it calls the actual ssh binary and not some intermediate shell function with the same name (`man command` explains).
`env` can be useful for fish compat < 3.1, where [the KEY=value syntax was introduced](https://fishshell.com/docs/current/faq.html#how-do-i-set-or-clear-an-environment-variable). However because `command` is a builtin it doesn't work in this case.
So a simple solution is this, requiring fish >= 3.1
```
TERM="$ssh_term" command ssh $ssh_opts $argv
```
An [alternative](https://serverfault.com/questions/164305/how-can-i-set-environment-variable-for-just-one-command-in-fish-shell) for maximum fish compat could be the following:
```
begin
set -lx TERM "$ssh_term"
command ssh $ssh_opts $argv
end
```
According to `man set`, `-l` means local to the block and `-x` means export.
I'm in favour of keeping `command` as it makes the integration more predicable.
The reason I went with the current fix:
- It's easier to understand without knowing fish shell.
- [kat found that fish 3.1 should be widely available](https://github.com/ghostty-org/ghostty/discussions/8021#discussioncomment-13877129).
This ports over the winproto behaviors to gtk-ng. The core winproto
logic is unchanged except for trivial typing changes. The interaction
with winproto is a bit different in ng due to the class separation of
logic between surfaces and windows, but functionally the same.
Ran against Valgrind and all looks good.