Merge remote-tracking branch 'origin/main' into close-split-gtk
# Conflicts: # po/hu.po # po/id.popull/11173/head
commit
bcf12937d0
|
|
@ -1,64 +0,0 @@
|
|||
#!/usr/bin/env nu
|
||||
|
||||
# A command to generate an agent prompt to diagnose and formulate
|
||||
# a plan for resolving a GitHub issue.
|
||||
#
|
||||
# IMPORTANT: This command is prompted to NOT write any code and to ONLY
|
||||
# produce a plan. You should still be vigilant when running this but that
|
||||
# is the expected behavior.
|
||||
#
|
||||
# The `<issue>` parameter can be either an issue number or a full GitHub
|
||||
# issue URL.
|
||||
def main [
|
||||
issue: any, # Ghostty issue number or URL
|
||||
--repo: string = "ghostty-org/ghostty" # GitHub repository in the format "owner/repo"
|
||||
] {
|
||||
# TODO: This whole script doesn't handle errors very well. I actually
|
||||
# don't know Nu well enough to know the proper way to handle it all.
|
||||
|
||||
let issueData = gh issue view $issue --json author,title,number,body,comments | from json
|
||||
let comments = $issueData.comments | each { |comment|
|
||||
$"
|
||||
### Comment by ($comment.author.login)
|
||||
($comment.body)
|
||||
" | str trim
|
||||
} | str join "\n\n"
|
||||
|
||||
$"
|
||||
Deep-dive on this GitHub issue. Find the problem and generate a plan.
|
||||
Do not write code. Explain the problem clearly and propose a comprehensive plan
|
||||
to solve it.
|
||||
|
||||
# ($issueData.title) \(($issueData.number)\)
|
||||
|
||||
## Description
|
||||
($issueData.body)
|
||||
|
||||
## Comments
|
||||
($comments)
|
||||
|
||||
## Your Tasks
|
||||
|
||||
You are an experienced software developer tasked with diagnosing issues.
|
||||
|
||||
1. Review the issue context and details.
|
||||
2. Examine the relevant parts of the codebase. Analyze the code thoroughly
|
||||
until you have a solid understanding of how it works.
|
||||
3. Explain the issue in detail, including the problem and its root cause.
|
||||
4. Create a comprehensive plan to solve the issue. The plan should include:
|
||||
- Required code changes
|
||||
- Potential impacts on other parts of the system
|
||||
- Necessary tests to be written or updated
|
||||
- Documentation updates
|
||||
- Performance considerations
|
||||
- Security implications
|
||||
- Backwards compatibility \(if applicable\)
|
||||
- Include the reference link to the source issue and any related discussions
|
||||
4. Think deeply about all aspects of the task. Consider edge cases, potential
|
||||
challenges, and best practices for addressing the issue. Review the plan
|
||||
with the oracle and adjust it based on its feedback.
|
||||
|
||||
**ONLY CREATE A PLAN. DO NOT WRITE ANY CODE.** Your task is to create
|
||||
a thorough, comprehensive strategy for understanding and resolving the issue.
|
||||
" | str trim
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
---
|
||||
name: writing-commit-messages
|
||||
description: >-
|
||||
Writes Git commit messages. Activates when the user asks to write
|
||||
a commit message, draft a commit message, or similar.
|
||||
---
|
||||
|
||||
# Writing Commit Messages
|
||||
|
||||
Write commit messages that follow commit style guidelines for the project.
|
||||
|
||||
## Format
|
||||
|
||||
```
|
||||
<subsystem>: <summary>
|
||||
|
||||
<reference issues/PRs/etc.>
|
||||
|
||||
<long form description>
|
||||
```
|
||||
|
||||
## Rules
|
||||
|
||||
### Subject line
|
||||
|
||||
- **Subsystem prefix**: Use a short, lowercase identifier for the
|
||||
area of code changed (e.g., `terminal`, `vt`, `lib`, `config`,
|
||||
`font`). Determine this from the file paths in the diff. If
|
||||
changes span the macOS app, use `macos`. For GTK, use `gtk`. For
|
||||
build system, use `build`. Use nested subsystems with `/` when
|
||||
helpful and exclusive (e.g., `terminal/osc`).
|
||||
- **Summary**: Lowercase start (not capitalized), imperative mood,
|
||||
no trailing period. Keep it concise—ideally under 60 characters
|
||||
total for the whole subject line.
|
||||
|
||||
### References
|
||||
|
||||
- If the change relates to a GitHub issue, PR, or discussion, list
|
||||
the relevant numbers on their own lines after the subject, separated
|
||||
by a blank line. E.g. `#1234`
|
||||
- If there are no references, omit this section entirely (no blank
|
||||
line).
|
||||
|
||||
### Long form description
|
||||
|
||||
- Describe **what changed**, **what the previous behavior was**,
|
||||
and **how the new behavior works** at a high level.
|
||||
- Use plain prose, not bullet points. Wrap lines at ~72 characters.
|
||||
- Focus on the _why_ and _how_ rather than restating the diff.
|
||||
- Keep the tone direct and technical without no filler phrases.
|
||||
- Don't exceed a handful of paragraphs; less is more.
|
||||
|
||||
## Workflow
|
||||
|
||||
- If `.jj` is present, use `jj` instead of `git` for all commands.
|
||||
- Run a diff to see what changes are present since the last commit.
|
||||
- Identify the subsystem from the changed file paths.
|
||||
- Identify any referenced issues/PRs from the diff context or
|
||||
branch name.
|
||||
- Draft the commit message following the format above.
|
||||
- Apply the commit
|
||||
- Don't push the commit; leave that to the user.
|
||||
|
|
@ -12,3 +12,4 @@ src/font/nerd_font_attributes.zig linguist-generated=true
|
|||
src/font/nerd_font_codepoint_tables.py linguist-generated=true
|
||||
src/font/res/** linguist-vendored
|
||||
src/terminal/res/** linguist-vendored
|
||||
src/terminal/res/rgb.txt -text
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
# discussion by the author. Maintainers can denounce users by commenting
|
||||
# "!denounce" or "!denounce [username]" on a discussion.
|
||||
00-kat
|
||||
04cb
|
||||
aalhendi
|
||||
abdurrahmanski
|
||||
abudvytis
|
||||
|
|
@ -28,8 +29,12 @@ alaasdk
|
|||
alanmoyano
|
||||
alexfeijoo44
|
||||
alexjuca
|
||||
alosarjos
|
||||
amadeus
|
||||
andrejdaskalov
|
||||
anhthang
|
||||
anmitalidev
|
||||
anthonyzhoon
|
||||
atomk
|
||||
balazs-szucs
|
||||
bennettp123
|
||||
|
|
@ -40,24 +45,36 @@ bitigchi
|
|||
bkircher
|
||||
bo2themax
|
||||
brentschroeter
|
||||
brianc442
|
||||
cespare
|
||||
charliie-dev
|
||||
chernetskyi
|
||||
chronologos
|
||||
cmwetherell
|
||||
crayxt
|
||||
craziestowl
|
||||
curtismoncoq
|
||||
d-dudas
|
||||
daiimus
|
||||
damyanbogoev
|
||||
danulqua
|
||||
dariogriffo
|
||||
davidsanchez222
|
||||
deblasis
|
||||
dervedro
|
||||
devsunb
|
||||
diaaeddin
|
||||
dmehala
|
||||
doprz
|
||||
douglance
|
||||
douglas
|
||||
drepper
|
||||
dzhlobo
|
||||
ekaterinepapava
|
||||
elias8
|
||||
ephemera
|
||||
eriksremess
|
||||
faukah
|
||||
filip7
|
||||
flou
|
||||
francescarpi
|
||||
|
|
@ -69,12 +86,20 @@ gpanders
|
|||
guilhermetk
|
||||
hakonhagland
|
||||
halosatrio
|
||||
heaths
|
||||
heddxh heddxh
|
||||
-highimpact-dev Disrespectful AI user
|
||||
hlcfan
|
||||
hqnna
|
||||
hulet
|
||||
icodesign
|
||||
j0hnm4r5
|
||||
jacobsandlund
|
||||
jake-stewart
|
||||
jcollie
|
||||
jesusvazquez
|
||||
jguthmiller
|
||||
jmcgover
|
||||
johnslavik
|
||||
josephmart
|
||||
jparise
|
||||
|
|
@ -85,6 +110,7 @@ khipp
|
|||
kirwiisp
|
||||
kjvdven
|
||||
kloneets
|
||||
-kody-w
|
||||
koranir
|
||||
kristina8888
|
||||
kristofersoler
|
||||
|
|
@ -92,12 +118,18 @@ laxystem
|
|||
liby
|
||||
linustalacko
|
||||
lonsagisawa
|
||||
luisnquin
|
||||
lynicis
|
||||
mac0ne
|
||||
mahnokropotkinvich
|
||||
marijagjorgjieva
|
||||
markdorison
|
||||
markhuot
|
||||
marler8997
|
||||
marrocco-simone
|
||||
matkotiric
|
||||
micaeljarniac
|
||||
michielvk
|
||||
miguelelgallo
|
||||
mihi314
|
||||
mikailmm
|
||||
|
|
@ -105,6 +137,7 @@ misairuzame
|
|||
mischief
|
||||
mitchellh
|
||||
miupa
|
||||
molechowski
|
||||
mrmage
|
||||
mtak
|
||||
natesmyth
|
||||
|
|
@ -113,17 +146,23 @@ nicosuave
|
|||
nmggithub
|
||||
noib3
|
||||
nwehg
|
||||
ocean6954
|
||||
oshdubh
|
||||
paaloeye
|
||||
pan93412
|
||||
pangoraw
|
||||
pauley-unsaturated
|
||||
peilingjiang
|
||||
peterdavehello
|
||||
philocalyst
|
||||
phush0
|
||||
piedrahitac
|
||||
pluiedev
|
||||
pouwerkerk
|
||||
poweruser64
|
||||
prakhar54-byte
|
||||
priyans-hu
|
||||
puzza007
|
||||
qwerasd205
|
||||
reo101
|
||||
rgehan
|
||||
|
|
@ -133,18 +172,26 @@ rmunn
|
|||
rockorager
|
||||
rpfaeffle
|
||||
secrus
|
||||
seruman
|
||||
silveirapf
|
||||
slsrepo
|
||||
sunshine-syz
|
||||
tdgroot
|
||||
tdslot
|
||||
ticclick
|
||||
tnagatomi
|
||||
trag1c
|
||||
tristan957
|
||||
turbolent
|
||||
tweedbeetle
|
||||
uhojin
|
||||
unphased
|
||||
uzaaft
|
||||
vaughanandrews
|
||||
viruslobster
|
||||
vlsi
|
||||
wyounas
|
||||
yamshta
|
||||
ydah
|
||||
zenyr
|
||||
zeshi09
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ jobs:
|
|||
runs-on: ${{ matrix.variant.runner }}
|
||||
steps:
|
||||
- name: Download Source Tarball Artifacts
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
run-id: ${{ inputs.source-run-id }}
|
||||
artifact-ids: ${{ inputs.source-artifact-id }}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,15 @@ on:
|
|||
|
||||
jobs:
|
||||
update-milestone:
|
||||
# Ignore bot-authored pull requests (dependabot, app bots, etc)
|
||||
# and CI-only PRs.
|
||||
if: github.event_name == 'issues' || (github.event.pull_request.user.type != 'Bot' && !startsWith(github.event.pull_request.title, 'ci:'))
|
||||
runs-on: namespace-profile-ghostty-sm
|
||||
name: Milestone Update
|
||||
steps:
|
||||
- name: Set Milestone for PR
|
||||
uses: hustcer/milestone-action@ebed8d5daafd855a600d7e665c1b130f06d24130 # v3.1
|
||||
if: github.event.pull_request.merged == true
|
||||
if: github.event.pull_request.merged == true && !contains(github.event.pull_request.title, 'VOUCHED') && !startsWith(github.event.pull_request.title, 'ci:')
|
||||
with:
|
||||
action: bind-pr # `bind-pr` is the default action
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ jobs:
|
|||
/nix
|
||||
/zig
|
||||
- name: Setup Nix
|
||||
uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
|
|||
|
|
@ -89,11 +89,11 @@ jobs:
|
|||
/nix
|
||||
/zig
|
||||
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -147,7 +147,7 @@ jobs:
|
|||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -299,7 +299,7 @@ jobs:
|
|||
curl -sL https://sentry.io/get-cli/ | bash
|
||||
|
||||
- name: Download macOS Artifacts
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: macos
|
||||
|
||||
|
|
@ -322,7 +322,7 @@ jobs:
|
|||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Download macOS Artifacts
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: macos
|
||||
|
||||
|
|
@ -370,17 +370,17 @@ jobs:
|
|||
GHOSTTY_VERSION: ${{ needs.setup.outputs.version }}
|
||||
steps:
|
||||
- name: Download macOS Artifacts
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: macos
|
||||
|
||||
- name: Download Sparkle Artifacts
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: sparkle
|
||||
|
||||
- name: Download Source Tarball Artifacts
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: source-tarball
|
||||
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@ jobs:
|
|||
with:
|
||||
path: |
|
||||
/nix
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -175,10 +175,10 @@ jobs:
|
|||
path: |
|
||||
/nix
|
||||
/zig
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -195,7 +195,7 @@ jobs:
|
|||
nix develop -c minisign -S -m ghostty-source.tar.gz -s minisign.key < minisign.password
|
||||
|
||||
- name: Update Release
|
||||
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
|
||||
with:
|
||||
name: 'Ghostty Tip ("Nightly")'
|
||||
prerelease: true
|
||||
|
|
@ -245,7 +245,7 @@ jobs:
|
|||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -378,7 +378,7 @@ jobs:
|
|||
|
||||
# Update Release
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
|
||||
with:
|
||||
name: 'Ghostty Tip ("Nightly")'
|
||||
prerelease: true
|
||||
|
|
@ -501,7 +501,7 @@ jobs:
|
|||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -627,7 +627,7 @@ jobs:
|
|||
|
||||
# Update Release
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
|
||||
with:
|
||||
name: 'Ghostty Tip ("Nightly")'
|
||||
prerelease: true
|
||||
|
|
@ -698,7 +698,7 @@ jobs:
|
|||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -824,7 +824,7 @@ jobs:
|
|||
|
||||
# Update Release
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
|
||||
with:
|
||||
name: 'Ghostty Tip ("Nightly")'
|
||||
prerelease: true
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ jobs:
|
|||
ZIG_GLOBAL_CACHE_DIR: /zig/global-cache
|
||||
steps:
|
||||
- name: Download Source Tarball Artifacts
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
run-id: ${{ inputs.source-run-id }}
|
||||
artifact-ids: ${{ inputs.source-artifact-id }}
|
||||
|
|
|
|||
|
|
@ -31,19 +31,19 @@ jobs:
|
|||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: filter_every
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
token: ""
|
||||
predicate-quantifier: "every"
|
||||
filters: |
|
||||
code:
|
||||
- '**'
|
||||
- '!.github/VOUCHED.td'
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: filter_any
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
token: ""
|
||||
filters: |
|
||||
macos:
|
||||
- '.swiftlint.yml'
|
||||
|
|
@ -85,24 +85,28 @@ jobs:
|
|||
- skip
|
||||
- build-bench
|
||||
- build-dist
|
||||
- build-examples
|
||||
- build-examples-zig
|
||||
- build-examples-cmake
|
||||
- build-examples-cmake-windows
|
||||
- build-cmake
|
||||
- build-flatpak
|
||||
- build-libghostty-vt
|
||||
- build-libghostty-vt-android
|
||||
- build-libghostty-vt-macos
|
||||
- build-libghostty-vt-windows
|
||||
- build-linux
|
||||
- build-linux-libghostty
|
||||
- build-nix
|
||||
- build-macos
|
||||
- build-macos-freetype
|
||||
- build-snap
|
||||
- build-windows
|
||||
- test
|
||||
- test-simd
|
||||
- test-gtk
|
||||
- test-sentry-linux
|
||||
- test-i18n
|
||||
- test-fuzz-libghostty
|
||||
- test-lib-vt
|
||||
- test-macos
|
||||
- pinact
|
||||
- prettier
|
||||
|
|
@ -156,10 +160,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -167,21 +171,123 @@ jobs:
|
|||
- name: Build Benchmarks
|
||||
run: nix develop -c zig build -Demit-bench
|
||||
|
||||
build-examples:
|
||||
list-examples:
|
||||
if: github.repository == 'ghostty-org/ghostty' && needs.skip.outputs.skip != 'true'
|
||||
needs: skip
|
||||
runs-on: namespace-profile-ghostty-xsm
|
||||
outputs:
|
||||
zig: ${{ steps.list.outputs.zig }}
|
||||
cmake: ${{ steps.list.outputs.cmake }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- id: list
|
||||
name: List example directories
|
||||
run: |
|
||||
zig=$(ls example/*/build.zig.zon 2>/dev/null | xargs -n1 dirname | xargs -n1 basename | jq -R -s -c 'split("\n") | map(select(. != ""))')
|
||||
echo "$zig" | jq .
|
||||
echo "zig=$zig" >> "$GITHUB_OUTPUT"
|
||||
cmake=$(ls example/*/CMakeLists.txt 2>/dev/null | xargs -n1 dirname | xargs -n1 basename | jq -R -s -c 'split("\n") | map(select(. != ""))')
|
||||
echo "$cmake" | jq .
|
||||
echo "cmake=$cmake" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build-examples-zig:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
dir:
|
||||
[
|
||||
c-vt,
|
||||
c-vt-key-encode,
|
||||
c-vt-paste,
|
||||
c-vt-sgr,
|
||||
zig-formatter,
|
||||
zig-vt,
|
||||
zig-vt-stream,
|
||||
]
|
||||
dir: ${{ fromJSON(needs.list-examples.outputs.zig) }}
|
||||
name: Example ${{ matrix.dir }}
|
||||
runs-on: namespace-profile-ghostty-xsm
|
||||
needs: [test, list-examples]
|
||||
env:
|
||||
ZIG_LOCAL_CACHE_DIR: /zig/local-cache
|
||||
ZIG_GLOBAL_CACHE_DIR: /zig/global-cache
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Setup Cache
|
||||
uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
|
||||
with:
|
||||
path: |
|
||||
/nix
|
||||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Build Example
|
||||
run: |
|
||||
cd example/${{ matrix.dir }}
|
||||
nix develop -c zig build
|
||||
|
||||
build-examples-cmake:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
dir: ${{ fromJSON(needs.list-examples.outputs.cmake) }}
|
||||
name: Example ${{ matrix.dir }}
|
||||
runs-on: namespace-profile-ghostty-xsm
|
||||
needs: [test, list-examples]
|
||||
env:
|
||||
ZIG_LOCAL_CACHE_DIR: /zig/local-cache
|
||||
ZIG_GLOBAL_CACHE_DIR: /zig/global-cache
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Setup Cache
|
||||
uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
|
||||
with:
|
||||
path: |
|
||||
/nix
|
||||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Build Example
|
||||
run: |
|
||||
cd example/${{ matrix.dir }}
|
||||
nix develop -c cmake -B build -DFETCHCONTENT_SOURCE_DIR_GHOSTTY=${{ github.workspace }}
|
||||
nix develop -c cmake --build build
|
||||
|
||||
build-examples-cmake-windows:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
dir: ${{ fromJSON(needs.list-examples.outputs.cmake) }}
|
||||
name: Example ${{ matrix.dir }} (Windows)
|
||||
runs-on: windows-2025
|
||||
timeout-minutes: 45
|
||||
needs: [test, list-examples]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Install zig
|
||||
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
|
||||
|
||||
- name: Build Example
|
||||
shell: pwsh
|
||||
run: |
|
||||
cd example/${{ matrix.dir }}
|
||||
cmake -B build -DFETCHCONTENT_SOURCE_DIR_GHOSTTY=${{ github.workspace }}
|
||||
cmake --build build
|
||||
|
||||
build-cmake:
|
||||
runs-on: namespace-profile-ghostty-sm
|
||||
needs: test
|
||||
env:
|
||||
|
|
@ -199,18 +305,25 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Build Example
|
||||
- name: Build
|
||||
run: |
|
||||
cd example/${{ matrix.dir }}
|
||||
nix develop -c zig build
|
||||
nix develop -c cmake -B build
|
||||
nix develop -c cmake --build build
|
||||
|
||||
- name: Verify artifacts
|
||||
run: |
|
||||
test -f zig-out/lib/libghostty-vt.so.0.1.0
|
||||
test -d zig-out/include/ghostty
|
||||
ls -la zig-out/lib/
|
||||
ls -la zig-out/include/ghostty/
|
||||
|
||||
build-flatpak:
|
||||
strategy:
|
||||
|
|
@ -232,10 +345,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -266,10 +379,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -310,21 +423,21 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
nix develop -c zig build lib-vt \
|
||||
nix develop -c zig build -Demit-lib-vt \
|
||||
-Dtarget=${{ matrix.target }} \
|
||||
-Dsimd=false
|
||||
|
||||
# lib-vt requires macOS runner for macOS/iOS builds becauase it requires the `apple_sdk` path
|
||||
# lib-vt requires macOS runner for macOS/iOS builds because it requires the `apple_sdk` path
|
||||
build-libghostty-vt-macos:
|
||||
strategy:
|
||||
matrix:
|
||||
|
|
@ -350,7 +463,7 @@ jobs:
|
|||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -360,7 +473,7 @@ jobs:
|
|||
|
||||
- name: Build
|
||||
run: |
|
||||
nix develop -c zig build lib-vt \
|
||||
nix develop -c zig build -Demit-lib-vt \
|
||||
-Dtarget=${{ matrix.target }}
|
||||
|
||||
# lib-vt requires the Android NDK for Android builds
|
||||
|
|
@ -387,10 +500,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -406,11 +519,28 @@ jobs:
|
|||
|
||||
- name: Build
|
||||
run: |
|
||||
nix develop -c zig build lib-vt \
|
||||
nix develop -c zig build -Demit-lib-vt \
|
||||
-Dtarget=${{ matrix.target }}
|
||||
env:
|
||||
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||
|
||||
build-libghostty-vt-windows:
|
||||
runs-on: windows-2025
|
||||
timeout-minutes: 45
|
||||
needs: test
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Setup Zig
|
||||
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
|
||||
|
||||
- name: Test libghostty-vt
|
||||
run: zig build test-lib-vt
|
||||
|
||||
- name: Build libghostty-vt
|
||||
run: zig build -Demit-lib-vt
|
||||
|
||||
build-linux:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
@ -433,10 +563,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -462,10 +592,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -495,10 +625,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -541,10 +671,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -621,7 +751,7 @@ jobs:
|
|||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -681,7 +811,7 @@ jobs:
|
|||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -696,83 +826,16 @@ jobs:
|
|||
id: deps
|
||||
run: nix build -L .#deps && echo "deps=$(readlink ./result)" >> $GITHUB_OUTPUT
|
||||
|
||||
# We run tests with an empty test filter so it runs all unit tests
|
||||
# but skips Xcode tests
|
||||
- name: Test All
|
||||
run: |
|
||||
nix develop -c zig build test --system ${{ steps.deps.outputs.deps }} -Drenderer=metal -Dfont-backend=coretext_freetype
|
||||
nix develop -c zig build test --system ${{ steps.deps.outputs.deps }} -Drenderer=metal -Dfont-backend=coretext_freetype -Dtest-filter=""
|
||||
|
||||
- name: Build All
|
||||
run: |
|
||||
nix develop -c zig build --system ${{ steps.deps.outputs.deps }} -Demit-macos-app=false -Drenderer=metal -Dfont-backend=coretext_freetype
|
||||
|
||||
build-windows:
|
||||
runs-on: windows-2022
|
||||
# this will not stop other jobs from running
|
||||
continue-on-error: true
|
||||
timeout-minutes: 45
|
||||
needs: test
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
# This could be from a script if we wanted to but inlining here for now
|
||||
# in one place.
|
||||
# Using powershell so that we do not need to install WSL components. Also,
|
||||
# WSLv1 is only installed on Github runners.
|
||||
- name: Install zig
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Get the zig version from build.zig.zon so that it only needs to be updated
|
||||
$fileContent = Get-Content -Path "build.zig.zon" -Raw
|
||||
$pattern = 'minimum_zig_version\s*=\s*"([^"]+)"'
|
||||
$zigVersion = [regex]::Match($fileContent, $pattern).Groups[1].Value
|
||||
$version = "zig-x86_64-windows-$zigVersion"
|
||||
Write-Output $version
|
||||
$uri = "https://ziglang.org/download/$zigVersion/$version.zip"
|
||||
Invoke-WebRequest -Uri "$uri" -OutFile ".\zig-windows.zip"
|
||||
Expand-Archive -Path ".\zig-windows.zip" -DestinationPath ".\" -Force
|
||||
Remove-Item -Path ".\zig-windows.zip"
|
||||
Rename-Item -Path ".\$version" -NewName ".\zig"
|
||||
Write-Host "Zig installed."
|
||||
.\zig\zig.exe version
|
||||
|
||||
- name: Generate build testing script
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Generate a script so that we can swallow the errors
|
||||
$scriptContent = @"
|
||||
.\zig\zig.exe build test 2>&1 | Out-File -FilePath "build.log" -Append
|
||||
exit 0
|
||||
"@
|
||||
$scriptPath = "zigbuild.ps1"
|
||||
# Write the script content to a file
|
||||
$scriptContent | Set-Content -Path $scriptPath
|
||||
Write-Host "Script generated at: $scriptPath"
|
||||
|
||||
- name: Test Windows
|
||||
shell: pwsh
|
||||
run: .\zigbuild.ps1 -ErrorAction SilentlyContinue
|
||||
|
||||
- name: Generate build script
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Generate a script so that we can swallow the errors
|
||||
$scriptContent = @"
|
||||
.\zig\zig.exe build 2>&1 | Out-File -FilePath "build.log" -Append
|
||||
exit 0
|
||||
"@
|
||||
$scriptPath = "zigbuild.ps1"
|
||||
# Write the script content to a file
|
||||
$scriptContent | Set-Content -Path $scriptPath
|
||||
Write-Host "Script generated at: $scriptPath"
|
||||
|
||||
- name: Build Windows
|
||||
shell: pwsh
|
||||
run: .\zigbuild.ps1 -ErrorAction SilentlyContinue
|
||||
|
||||
- name: Dump logs
|
||||
shell: pwsh
|
||||
run: Get-Content -Path ".\build.log"
|
||||
|
||||
test:
|
||||
if: github.repository == 'ghostty-org/ghostty' && needs.skip.outputs.skip != 'true'
|
||||
needs: skip
|
||||
|
|
@ -799,10 +862,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -817,6 +880,36 @@ jobs:
|
|||
- name: Test System Build
|
||||
run: nix develop -c zig build --system ${ZIG_GLOBAL_CACHE_DIR}/p
|
||||
|
||||
test-lib-vt:
|
||||
if: github.repository == 'ghostty-org/ghostty' && needs.skip.outputs.skip != 'true'
|
||||
needs: skip
|
||||
runs-on: namespace-profile-ghostty-md
|
||||
env:
|
||||
ZIG_LOCAL_CACHE_DIR: /zig/local-cache
|
||||
ZIG_GLOBAL_CACHE_DIR: /zig/global-cache
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Setup Cache
|
||||
uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
|
||||
with:
|
||||
path: |
|
||||
/nix
|
||||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Test
|
||||
run: nix develop -c zig build test-lib-vt
|
||||
|
||||
test-gtk:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
@ -841,10 +934,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -889,10 +982,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -924,10 +1017,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -958,7 +1051,7 @@ jobs:
|
|||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -999,10 +1092,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1030,10 +1123,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1072,10 +1165,10 @@ jobs:
|
|||
path: |
|
||||
/nix
|
||||
/zig
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1103,10 +1196,10 @@ jobs:
|
|||
path: |
|
||||
/nix
|
||||
/zig
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1133,10 +1226,10 @@ jobs:
|
|||
path: |
|
||||
/nix
|
||||
/zig
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1165,7 +1258,7 @@ jobs:
|
|||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1191,10 +1284,10 @@ jobs:
|
|||
path: |
|
||||
/nix
|
||||
/zig
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1219,10 +1312,10 @@ jobs:
|
|||
path: |
|
||||
/nix
|
||||
/zig
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1247,10 +1340,10 @@ jobs:
|
|||
path: |
|
||||
/nix
|
||||
/zig
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1280,10 +1373,10 @@ jobs:
|
|||
path: |
|
||||
/nix
|
||||
/zig
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1308,10 +1401,10 @@ jobs:
|
|||
path: |
|
||||
/nix
|
||||
/zig
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1345,10 +1438,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
@ -1364,13 +1457,13 @@ jobs:
|
|||
needs: [test, build-dist]
|
||||
steps:
|
||||
- name: Install and configure Namespace CLI
|
||||
uses: namespacelabs/nscloud-setup@f378676225212387f1283f4da878712af2c4cd60 # v0.0.11
|
||||
uses: namespacelabs/nscloud-setup@df198f982fcecfb8264bea3f1274b56a61b6dfdc # v0.0.12
|
||||
|
||||
- name: Configure Namespace powered Buildx
|
||||
uses: namespacelabs/nscloud-setup-buildx-action@f5814dcf37a16cce0624d5bec2ab879654294aa0 # v0.0.22
|
||||
uses: namespacelabs/nscloud-setup-buildx-action@d059ed7184f0bc7c8b27e8810cea153d02bcc6dd # v0.0.23
|
||||
|
||||
- name: Download Source Tarball Artifacts
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: source-tarball
|
||||
|
||||
|
|
@ -1380,7 +1473,7 @@ jobs:
|
|||
tar --verbose --extract --strip-components 1 --directory dist --file ghostty-source.tar.gz
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
context: dist
|
||||
file: dist/src/build/docker/debian/Dockerfile
|
||||
|
|
@ -1407,10 +1500,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
- uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ jobs:
|
|||
/zig
|
||||
|
||||
- name: Setup Nix
|
||||
uses: cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
|
||||
uses: cachix/install-nix-action@51f3067b56fe8ae331890c77d4e454f6d60615ff # v31.10.2
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ jobs:
|
|||
check:
|
||||
runs-on: namespace-profile-ghostty-xsm
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
|
||||
- uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.VOUCH_APP_ID }}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ jobs:
|
|||
check:
|
||||
runs-on: namespace-profile-ghostty-xsm
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
|
||||
- uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.VOUCH_APP_ID }}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
manage:
|
||||
runs-on: namespace-profile-ghostty-xsm
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
|
||||
- uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.VOUCH_APP_ID }}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
manage:
|
||||
runs-on: namespace-profile-ghostty-xsm
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
|
||||
- uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.VOUCH_APP_ID }}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ jobs:
|
|||
sync:
|
||||
runs-on: namespace-profile-ghostty-xsm
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
|
||||
- uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.VOUCH_APP_ID }}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
zig-cache/
|
||||
.zig-cache/
|
||||
zig-out/
|
||||
build-cmake/
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
/build.zig.zon.bak
|
||||
/result*
|
||||
/.nixos-test-history
|
||||
|
|
@ -25,3 +28,4 @@ glad.zip
|
|||
/ghostty.qcow2
|
||||
|
||||
vgcore.*
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ zig-out/
|
|||
# macos is managed by XCode GUI
|
||||
macos/
|
||||
|
||||
# Xcode asset catalogs
|
||||
**/*.xcassets/
|
||||
|
||||
# produced by Icon Composer on macOS
|
||||
images/Ghostty.icon/icon.json
|
||||
|
||||
|
|
|
|||
|
|
@ -5,16 +5,20 @@ A file for [guiding coding agents](https://agents.md/).
|
|||
## Commands
|
||||
|
||||
- **Build:** `zig build`
|
||||
- If you're on macOS and don't need to build the macOS app, use
|
||||
`-Demit-macos-app=false` to skip building the app bundle and speed up
|
||||
compilation.
|
||||
- **Test (Zig):** `zig build test`
|
||||
- Prefer to run targeted tests with `-Dtest-filter` because the full
|
||||
test suite is slow to run.
|
||||
- **Test filter (Zig)**: `zig build test -Dtest-filter=<test name>`
|
||||
- **Formatting (Zig)**: `zig fmt .`
|
||||
- **Formatting (Swift)**: `swiftlint lint --fix`
|
||||
- **Formatting (Swift)**: `swiftlint lint --strict --fix`
|
||||
- **Formatting (other)**: `prettier -w .`
|
||||
|
||||
## Directory Structure
|
||||
|
||||
- Shared Zig core: `src/`
|
||||
- C API: `include`
|
||||
- macOS app: `macos/`
|
||||
- GTK (Linux and FreeBSD) app: `src/apprt/gtk`
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,230 @@
|
|||
# CMake wrapper for libghostty-vt
|
||||
#
|
||||
# This file delegates to `zig build -Demit-lib-vt` to produce the shared library,
|
||||
# headers, and pkg-config file. It exists so that CMake-based projects can
|
||||
# consume libghostty-vt without interacting with the Zig build system
|
||||
# directly. However, downstream users do still require `zig` on the PATH.
|
||||
# Please consult the Ghostty docs for the required Zig version:
|
||||
#
|
||||
# https://ghostty.org/docs/install/build
|
||||
#
|
||||
# Building within the Ghostty repo
|
||||
# ---------------------------------
|
||||
#
|
||||
# cmake -B build
|
||||
# cmake --build build
|
||||
# cmake --install build --prefix /usr/local
|
||||
#
|
||||
# Pass extra flags to the Zig build with GHOSTTY_ZIG_BUILD_FLAGS:
|
||||
#
|
||||
# cmake -B build -DGHOSTTY_ZIG_BUILD_FLAGS="-Demit-macos-app=false"
|
||||
#
|
||||
# Integrating into a downstream CMake project
|
||||
# ---------------------------------------------
|
||||
#
|
||||
# Option 1 — FetchContent (recommended, no manual install step):
|
||||
#
|
||||
# include(FetchContent)
|
||||
# FetchContent_Declare(ghostty
|
||||
# GIT_REPOSITORY https://github.com/ghostty-org/ghostty.git
|
||||
# GIT_TAG main
|
||||
# )
|
||||
# FetchContent_MakeAvailable(ghostty)
|
||||
#
|
||||
# target_link_libraries(myapp PRIVATE ghostty-vt) # shared
|
||||
# target_link_libraries(myapp PRIVATE ghostty-vt-static) # static
|
||||
#
|
||||
# To use a local checkout instead of fetching:
|
||||
#
|
||||
# cmake -B build -DFETCHCONTENT_SOURCE_DIR_GHOSTTY=/path/to/ghostty
|
||||
#
|
||||
# Option 2 — find_package (after installing to a prefix):
|
||||
#
|
||||
# find_package(ghostty-vt REQUIRED)
|
||||
# target_link_libraries(myapp PRIVATE ghostty-vt::ghostty-vt) # shared
|
||||
# target_link_libraries(myapp PRIVATE ghostty-vt::ghostty-vt-static) # static
|
||||
#
|
||||
# See dist/cmake/README.md for more details and example/c-vt-cmake/ for a
|
||||
# complete working example.
|
||||
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(ghostty-vt VERSION 0.1.0 LANGUAGES C)
|
||||
|
||||
# --- Options ----------------------------------------------------------------
|
||||
|
||||
set(GHOSTTY_ZIG_BUILD_FLAGS "" CACHE STRING "Additional flags to pass to zig build")
|
||||
|
||||
# Map CMake build types to Zig optimization levels.
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" _bt)
|
||||
if(_bt STREQUAL "RELEASE" OR _bt STREQUAL "MINSIZEREL" OR _bt STREQUAL "RELWITHDEBINFO")
|
||||
list(APPEND GHOSTTY_ZIG_BUILD_FLAGS "-Doptimize=ReleaseFast")
|
||||
endif()
|
||||
unset(_bt)
|
||||
endif()
|
||||
|
||||
# --- Find Zig ----------------------------------------------------------------
|
||||
|
||||
find_program(ZIG_EXECUTABLE zig REQUIRED)
|
||||
message(STATUS "Found zig: ${ZIG_EXECUTABLE}")
|
||||
|
||||
# --- Build via zig build -----------------------------------------------------
|
||||
|
||||
# The zig build installs into zig-out/ relative to the source tree.
|
||||
set(ZIG_OUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/zig-out")
|
||||
|
||||
# Shared library names (zig build produces both shared and static).
|
||||
if(APPLE)
|
||||
set(GHOSTTY_VT_LIBNAME "${CMAKE_SHARED_LIBRARY_PREFIX}ghostty-vt${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
set(GHOSTTY_VT_SONAME "${CMAKE_SHARED_LIBRARY_PREFIX}ghostty-vt.0${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
set(GHOSTTY_VT_REALNAME "${CMAKE_SHARED_LIBRARY_PREFIX}ghostty-vt.0.1.0${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
elseif(WIN32)
|
||||
set(GHOSTTY_VT_LIBNAME "ghostty-vt.dll")
|
||||
set(GHOSTTY_VT_REALNAME "ghostty-vt.dll")
|
||||
set(GHOSTTY_VT_IMPLIB "ghostty-vt.lib")
|
||||
else()
|
||||
set(GHOSTTY_VT_LIBNAME "${CMAKE_SHARED_LIBRARY_PREFIX}ghostty-vt${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
set(GHOSTTY_VT_SONAME "${CMAKE_SHARED_LIBRARY_PREFIX}ghostty-vt${CMAKE_SHARED_LIBRARY_SUFFIX}.0")
|
||||
set(GHOSTTY_VT_REALNAME "${CMAKE_SHARED_LIBRARY_PREFIX}ghostty-vt${CMAKE_SHARED_LIBRARY_SUFFIX}.0.1.0")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(GHOSTTY_VT_SHARED_LIBRARY "${ZIG_OUT_DIR}/bin/${GHOSTTY_VT_REALNAME}")
|
||||
else()
|
||||
set(GHOSTTY_VT_SHARED_LIBRARY "${ZIG_OUT_DIR}/lib/${GHOSTTY_VT_REALNAME}")
|
||||
endif()
|
||||
|
||||
# Static library name.
|
||||
# On Windows, the static lib is named "ghostty-vt-static.lib" to avoid
|
||||
# colliding with the DLL import library "ghostty-vt.lib".
|
||||
if(WIN32)
|
||||
set(GHOSTTY_VT_STATIC_REALNAME "ghostty-vt-static.lib")
|
||||
else()
|
||||
set(GHOSTTY_VT_STATIC_REALNAME "libghostty-vt.a")
|
||||
endif()
|
||||
set(GHOSTTY_VT_STATIC_LIBRARY "${ZIG_OUT_DIR}/lib/${GHOSTTY_VT_STATIC_REALNAME}")
|
||||
|
||||
# Ensure the output directories exist so CMake doesn't reject the
|
||||
# INTERFACE_INCLUDE_DIRECTORIES before the zig build has run.
|
||||
file(MAKE_DIRECTORY "${ZIG_OUT_DIR}/include")
|
||||
|
||||
# Custom command: run zig build -Demit-lib-vt (produces both shared and static)
|
||||
add_custom_command(
|
||||
OUTPUT "${GHOSTTY_VT_SHARED_LIBRARY}" "${GHOSTTY_VT_STATIC_LIBRARY}" "${ZIG_OUT_DIR}/lib/${GHOSTTY_VT_IMPLIB}"
|
||||
COMMAND "${ZIG_EXECUTABLE}" build -Demit-lib-vt ${GHOSTTY_ZIG_BUILD_FLAGS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Building libghostty-vt via zig build..."
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
add_custom_target(zig_build_lib_vt ALL
|
||||
DEPENDS "${GHOSTTY_VT_SHARED_LIBRARY}" "${GHOSTTY_VT_STATIC_LIBRARY}"
|
||||
)
|
||||
|
||||
# Tell CMake's clean target to also remove Zig's output directory.
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_CLEAN_FILES "${ZIG_OUT_DIR}"
|
||||
)
|
||||
|
||||
# --- IMPORTED library targets ------------------------------------------------
|
||||
|
||||
# Shared
|
||||
add_library(ghostty-vt SHARED IMPORTED GLOBAL)
|
||||
set_target_properties(ghostty-vt PROPERTIES
|
||||
IMPORTED_LOCATION "${GHOSTTY_VT_SHARED_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${ZIG_OUT_DIR}/include"
|
||||
)
|
||||
if(APPLE)
|
||||
set_target_properties(ghostty-vt PROPERTIES
|
||||
IMPORTED_SONAME "@rpath/${GHOSTTY_VT_SONAME}"
|
||||
)
|
||||
elseif(WIN32)
|
||||
set_target_properties(ghostty-vt PROPERTIES
|
||||
IMPORTED_IMPLIB "${ZIG_OUT_DIR}/lib/${GHOSTTY_VT_IMPLIB}"
|
||||
)
|
||||
else()
|
||||
set_target_properties(ghostty-vt PROPERTIES
|
||||
IMPORTED_SONAME "${GHOSTTY_VT_SONAME}"
|
||||
)
|
||||
endif()
|
||||
add_dependencies(ghostty-vt zig_build_lib_vt)
|
||||
|
||||
# Static
|
||||
#
|
||||
# When linking the static library, consumers must also link its transitive
|
||||
# dependencies. By default (with SIMD enabled), these are:
|
||||
# - libc
|
||||
# - libc++ (or libstdc++ on Linux)
|
||||
# - highway
|
||||
# - simdutf
|
||||
#
|
||||
# Building with -Dsimd=false removes the C++ / highway / simdutf
|
||||
# dependencies, leaving only libc.
|
||||
add_library(ghostty-vt-static STATIC IMPORTED GLOBAL)
|
||||
set_target_properties(ghostty-vt-static PROPERTIES
|
||||
IMPORTED_LOCATION "${GHOSTTY_VT_STATIC_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${ZIG_OUT_DIR}/include"
|
||||
)
|
||||
if(WIN32)
|
||||
# On Windows, the Zig standard library uses NT API functions
|
||||
# (NtClose, NtCreateSection, etc.) and kernel32 functions that
|
||||
# consumers must link when using the static library.
|
||||
set_target_properties(ghostty-vt-static PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES "ntdll;kernel32"
|
||||
)
|
||||
endif()
|
||||
add_dependencies(ghostty-vt-static zig_build_lib_vt)
|
||||
|
||||
# --- Install ------------------------------------------------------------------
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Install shared library
|
||||
if(WIN32)
|
||||
# On Windows, install the DLL and PDB to bin/ and the import library to lib/
|
||||
install(FILES "${GHOSTTY_VT_SHARED_LIBRARY}" "${ZIG_OUT_DIR}/bin/ghostty-vt.pdb" TYPE BIN)
|
||||
install(FILES "${ZIG_OUT_DIR}/lib/${GHOSTTY_VT_IMPLIB}" TYPE LIB)
|
||||
else()
|
||||
install(FILES "${GHOSTTY_VT_SHARED_LIBRARY}" TYPE LIB)
|
||||
# Install symlinks
|
||||
install(CODE "
|
||||
execute_process(COMMAND \${CMAKE_COMMAND} -E create_symlink
|
||||
\"${GHOSTTY_VT_REALNAME}\"
|
||||
\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${GHOSTTY_VT_SONAME}\")
|
||||
execute_process(COMMAND \${CMAKE_COMMAND} -E create_symlink
|
||||
\"${GHOSTTY_VT_SONAME}\"
|
||||
\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${GHOSTTY_VT_LIBNAME}\")
|
||||
")
|
||||
endif()
|
||||
|
||||
# Install static library
|
||||
install(FILES "${GHOSTTY_VT_STATIC_LIBRARY}" TYPE LIB)
|
||||
|
||||
# Install headers
|
||||
install(DIRECTORY "${ZIG_OUT_DIR}/include/ghostty" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
|
||||
# --- CMake package config for find_package() ----------------------------------
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
# Generate the config file
|
||||
configure_package_config_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist/cmake/ghostty-vt-config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/ghostty-vt-config.cmake"
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghostty-vt"
|
||||
)
|
||||
|
||||
# Generate the version file
|
||||
write_basic_package_version_file(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/ghostty-vt-config-version.cmake"
|
||||
VERSION "${PROJECT_VERSION}"
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
# Install the config files
|
||||
install(
|
||||
FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/ghostty-vt-config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/ghostty-vt-config-version.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghostty-vt"
|
||||
)
|
||||
|
|
@ -169,6 +169,7 @@
|
|||
/po/de.po @ghostty-org/de_DE
|
||||
/po/es_AR.po @ghostty-org/es_AR
|
||||
/po/es_BO.po @ghostty-org/es_BO
|
||||
/po/es_ES.po @ghostty-org/es_ES
|
||||
/po/fr.po @ghostty-org/fr_FR
|
||||
/po/ga.po @ghostty-org/ga_IE
|
||||
/po/he.po @ghostty-org/he_IL
|
||||
|
|
@ -189,6 +190,7 @@
|
|||
/po/ru.po @ghostty-org/ru_RU
|
||||
/po/tr.po @ghostty-org/tr_TR
|
||||
/po/uk.po @ghostty-org/uk_UA
|
||||
/po/vi.po @ghostty-org/vi_VN
|
||||
/po/zh_CN.po @ghostty-org/zh_CN
|
||||
/po/zh_TW.po @ghostty-org/zh_TW
|
||||
|
||||
|
|
|
|||
143
README.md
143
README.md
|
|
@ -7,6 +7,8 @@
|
|||
<p align="center">
|
||||
Fast, native, feature-rich terminal emulator pushing modern features.
|
||||
<br />
|
||||
A native GUI or embeddable library via <code>libghostty</code>.
|
||||
<br />
|
||||
<a href="#about">About</a>
|
||||
·
|
||||
<a href="https://ghostty.org/download">Download</a>
|
||||
|
|
@ -26,20 +28,13 @@ fast, feature-rich, and native. While there are many excellent terminal
|
|||
emulators available, they all force you to choose between speed,
|
||||
features, or native UIs. Ghostty provides all three.
|
||||
|
||||
In all categories, I am not trying to claim that Ghostty is the
|
||||
best (i.e. the fastest, most feature-rich, or most native). But
|
||||
Ghostty is competitive in all three categories and Ghostty
|
||||
doesn't make you choose between them.
|
||||
|
||||
Ghostty also intends to push the boundaries of what is possible with a
|
||||
terminal emulator by exposing modern, opt-in features that enable CLI tool
|
||||
developers to build more feature rich, interactive applications.
|
||||
|
||||
While aiming for this ambitious goal, our first step is to make Ghostty
|
||||
one of the best fully standards compliant terminal emulator, remaining
|
||||
compatible with all existing shells and software while supporting all of
|
||||
the latest terminal innovations in the ecosystem. You can use Ghostty
|
||||
as a drop-in replacement for your existing terminal emulator.
|
||||
**`libghostty`** is a cross-platform, zero-dependency C and Zig library
|
||||
for building terminal emulators or utilizing terminal functionality
|
||||
(such as style parsing). Anyone can use `libghostty` to build a terminal
|
||||
emulator or embed a terminal into their own applications. See
|
||||
[Ghostling](https://github.com/ghostty-org/ghostling) for a minimal complete project
|
||||
example or the [`examples` directory](https://github.com/ghostty-org/ghostty/tree/main/example)
|
||||
for smaller examples of using `libghostty` in C and Zig.
|
||||
|
||||
For more details, see [About Ghostty](https://ghostty.org/docs/about).
|
||||
|
||||
|
|
@ -61,30 +56,37 @@ to get involved with Ghostty's development as well should also read the
|
|||
|
||||
## Roadmap and Status
|
||||
|
||||
Ghostty is stable and in use by millions of people and machines daily.
|
||||
|
||||
The high-level ambitious plan for the project, in order:
|
||||
|
||||
| # | Step | Status |
|
||||
| :-: | --------------------------------------------------------- | :----: |
|
||||
| 1 | Standards-compliant terminal emulation | ✅ |
|
||||
| 2 | Competitive performance | ✅ |
|
||||
| 3 | Basic customizability -- fonts, bg colors, etc. | ✅ |
|
||||
| 4 | Richer windowing features -- multi-window, tabbing, panes | ✅ |
|
||||
| 5 | Native Platform Experiences (i.e. Mac Preference Panel) | ⚠️ |
|
||||
| 6 | Cross-platform `libghostty` for Embeddable Terminals | ⚠️ |
|
||||
| 7 | Windows Terminals (including PowerShell, Cmd, WSL) | ❌ |
|
||||
| N | Fancy features (to be expanded upon later) | ❌ |
|
||||
| # | Step | Status |
|
||||
| :-: | ------------------------------------------------------- | :----: |
|
||||
| 1 | Standards-compliant terminal emulation | ✅ |
|
||||
| 2 | Competitive performance | ✅ |
|
||||
| 3 | Rich windowing features -- multi-window, tabbing, panes | ✅ |
|
||||
| 4 | Native Platform Experiences | ✅ |
|
||||
| 5 | Cross-platform `libghostty` for Embeddable Terminals | ✅ |
|
||||
| 6 | Ghostty-only Terminal Control Sequences | ❌ |
|
||||
|
||||
Additional details for each step in the big roadmap below:
|
||||
|
||||
#### Standards-Compliant Terminal Emulation
|
||||
|
||||
Ghostty implements enough control sequences to be used by hundreds of
|
||||
testers daily for over the past year. Further, we've done a
|
||||
[comprehensive xterm audit](https://github.com/ghostty-org/ghostty/issues/632)
|
||||
Ghostty implements all of the regularly used control sequences and
|
||||
can run every mainstream terminal program without issue. For legacy sequences,
|
||||
we've done a [comprehensive xterm audit](https://github.com/ghostty-org/ghostty/issues/632)
|
||||
comparing Ghostty's behavior to xterm and building a set of conformance
|
||||
test cases.
|
||||
|
||||
We believe Ghostty is one of the most compliant terminal emulators available.
|
||||
In addition to legacy sequences (what you'd call real "terminal" emulation),
|
||||
Ghostty also supports more modern sequences than almost any other terminal
|
||||
emulator. These features include things like the Kitty graphics protocol,
|
||||
Kitty image protocol, clipboard sequences, synchronized rendering,
|
||||
light/dark mode notifications, and many, many more.
|
||||
|
||||
We believe Ghostty is one of the most compliant and feature-rich terminal
|
||||
emulators available.
|
||||
|
||||
Terminal behavior is partially a de jure standard
|
||||
(i.e. [ECMA-48](https://ecma-international.org/publications-and-standards/standards/ecma-48/))
|
||||
|
|
@ -96,33 +98,30 @@ views as a "standard."
|
|||
|
||||
#### Competitive Performance
|
||||
|
||||
We need better benchmarks to continuously verify this, but Ghostty is
|
||||
generally in the same performance category as the other highest performing
|
||||
terminal emulators.
|
||||
Ghostty is generally in the same performance category as the other highest
|
||||
performing terminal emulators.
|
||||
|
||||
For rendering, we have a multi-renderer architecture that uses OpenGL on
|
||||
Linux and Metal on macOS. As far as I'm aware, we're the only terminal
|
||||
emulator other than iTerm that uses Metal directly. And we're the only
|
||||
terminal emulator that has a Metal renderer that supports ligatures (iTerm
|
||||
uses a CPU renderer if ligatures are enabled). We can maintain around 60fps
|
||||
under heavy load and much more generally -- though the terminal is
|
||||
usually rendering much lower due to little screen changes.
|
||||
"The same performance category" means that Ghostty is much faster than
|
||||
traditional or "slow" terminals and is within an unnoticeable margin of the
|
||||
well-known "fast" terminals. For example, Ghostty and Alacritty are usually within
|
||||
a few percentage points of each other on various benchmarks, but are both
|
||||
something like 100x faster than Terminal.app and iTerm. However, Ghostty
|
||||
is much more feature rich than Alacritty and has a much more native app
|
||||
experience.
|
||||
|
||||
For IO, we have a dedicated IO thread that maintains very little jitter
|
||||
under heavy IO load (i.e. `cat <big file>.txt`). On benchmarks for IO,
|
||||
we're usually within a small margin of other fast terminal emulators.
|
||||
For example, reading a dump of plain text is 4x faster compared to iTerm and
|
||||
Kitty, and 2x faster than Terminal.app. Alacritty is very fast but we're still
|
||||
around the same speed (give or take) and our app experience is much more
|
||||
feature rich.
|
||||
This performance is achieved through high-level architectural decisions and
|
||||
low-level optimizations. At a high-level, Ghostty has a multi-threaded
|
||||
architecture with a dedicated read thread, write thread, and render thread
|
||||
per terminal. Our renderer uses OpenGL on Linux and Metal on macOS.
|
||||
Our read thread has a heavily optimized terminal parser that leverages
|
||||
CPU-specific SIMD instructions. Etc.
|
||||
|
||||
> [!NOTE]
|
||||
> Despite being _very fast_, there is a lot of room for improvement here.
|
||||
|
||||
#### Richer Windowing Features
|
||||
#### Rich Windowing Features
|
||||
|
||||
The Mac and Linux (build with GTK) apps support multi-window, tabbing, and
|
||||
splits.
|
||||
splits with additional features such as tab renaming, coloring, etc. These
|
||||
features allow for a higher degree of organization and customization than
|
||||
single-window terminals.
|
||||
|
||||
#### Native Platform Experiences
|
||||
|
||||
|
|
@ -133,10 +132,15 @@ in Zig but we do a lot of platform-native things:
|
|||
- The macOS app is a true SwiftUI-based application with all the things you
|
||||
would expect such as real windowing, menu bars, a settings GUI, etc.
|
||||
- macOS uses a true Metal renderer with CoreText for font discovery.
|
||||
- macOS supports AppleScript, Apple Shortcuts (AppIntents), etc.
|
||||
- The Linux app is built with GTK.
|
||||
- The Linux app integrates deeply with systemd if available for things
|
||||
like always-on, new windows in a single instance, cgroup isolation, etc.
|
||||
|
||||
There are more improvements to be made. The macOS settings window is still
|
||||
a work-in-progress. Similar improvements will follow with Linux.
|
||||
Our goal with Ghostty is for users of whatever platform they run Ghostty
|
||||
on to think that Ghostty was built for their platform first and maybe even
|
||||
exclusively. We want Ghostty to feel like a native app on every platform,
|
||||
for the best definition of "native" on each platform.
|
||||
|
||||
#### Cross-platform `libghostty` for Embeddable Terminals
|
||||
|
||||
|
|
@ -151,15 +155,34 @@ terminal state. This is covered in more detail in this
|
|||
[blog post](https://mitchellh.com/writing/libghostty-is-coming).
|
||||
|
||||
`libghostty-vt` is already available and usable today for Zig and C and
|
||||
is compatible for macOS, Linux, Windows, and WebAssembly. At the time of
|
||||
writing this, the API isn't stable yet and we haven't tagged an official
|
||||
release, but the core logic is well proven (since Ghostty uses it) and
|
||||
we're working hard on it now.
|
||||
is compatible for macOS, Linux, Windows, and WebAssembly. The functionality
|
||||
is extremely stable (since its been proven in Ghostty GUI for a long time),
|
||||
but the API signatures are still in flux.
|
||||
|
||||
The ultimate goal is not hypothetical! The macOS app is a `libghostty` consumer.
|
||||
The macOS app is a native Swift app developed in Xcode and `main()` is
|
||||
within Swift. The Swift app links to `libghostty` and uses the C API to
|
||||
render terminals.
|
||||
`libghostty` is already heavily in use. See [`examples`](https://github.com/ghostty-org/ghostty/tree/main/example)
|
||||
for small examples of using `libghostty` in C and Zig or the
|
||||
[Ghostling](https://github.com/ghostty-org/ghostling) project for a
|
||||
complete example. See [awesome-libghostty](https://github.com/Uzaaft/awesome-libghostty)
|
||||
for a list of projects and resources related to `libghostty`.
|
||||
|
||||
We haven't tagged libghostty with a version yet and we're still working
|
||||
on a better docs experience, but our [Doxygen website](https://libghostty.tip.ghostty.org/)
|
||||
is a good resource for the C API.
|
||||
|
||||
#### Ghostty-only Terminal Control Sequences
|
||||
|
||||
We want and believe that terminal applications can and should be able
|
||||
to do so much more. We've worked hard to support a wide variety of modern
|
||||
sequences created by other terminal emulators towards this end, but we also
|
||||
want to fill the gaps by creating our own sequences.
|
||||
|
||||
We've been hesitant to do this up until now because we don't want to create
|
||||
more fragmentation in the terminal ecosystem by creating sequences that only
|
||||
work in Ghostty. But, we do want to balance that with the desire to push the
|
||||
terminal forward with stagnant standards and the slow pace of change in the
|
||||
terminal ecosystem.
|
||||
|
||||
We haven't done any of this yet.
|
||||
|
||||
## Crash Reports
|
||||
|
||||
|
|
|
|||
67
build.zig
67
build.zig
|
|
@ -35,7 +35,6 @@ pub fn build(b: *std.Build) !void {
|
|||
|
||||
// All our steps which we'll hook up later. The steps are shown
|
||||
// up here just so that they are more self-documenting.
|
||||
const libvt_step = b.step("lib-vt", "Build libghostty-vt");
|
||||
const run_step = b.step("run", "Run the app");
|
||||
const run_valgrind_step = b.step(
|
||||
"run-valgrind",
|
||||
|
|
@ -91,16 +90,6 @@ pub fn build(b: *std.Build) !void {
|
|||
check_step.dependOn(dist.install_step);
|
||||
}
|
||||
|
||||
// libghostty (internal, big)
|
||||
const libghostty_shared = try buildpkg.GhosttyLib.initShared(
|
||||
b,
|
||||
&deps,
|
||||
);
|
||||
const libghostty_static = try buildpkg.GhosttyLib.initStatic(
|
||||
b,
|
||||
&deps,
|
||||
);
|
||||
|
||||
// libghostty-vt
|
||||
const libghostty_vt_shared = shared: {
|
||||
if (config.target.result.cpu.arch.isWasm()) {
|
||||
|
|
@ -115,9 +104,31 @@ pub fn build(b: *std.Build) !void {
|
|||
&mod,
|
||||
);
|
||||
};
|
||||
libghostty_vt_shared.install(libvt_step);
|
||||
libghostty_vt_shared.install(b.getInstallStep());
|
||||
|
||||
// libghostty-vt static lib
|
||||
const libghostty_vt_static = try buildpkg.GhosttyLibVt.initStatic(
|
||||
b,
|
||||
&mod,
|
||||
);
|
||||
if (config.is_dep) {
|
||||
// If we're a dependency, we need to install everything as-is
|
||||
// so that dep.artifact("ghostty-vt-static") works.
|
||||
libghostty_vt_static.install(b.getInstallStep());
|
||||
} else {
|
||||
// If we're not a dependency, we rename the static lib to
|
||||
// be idiomatic. On Windows, we use a distinct name to avoid
|
||||
// colliding with the DLL import library (ghostty-vt.lib).
|
||||
const static_lib_name = if (config.target.result.os.tag == .windows)
|
||||
"ghostty-vt-static.lib"
|
||||
else
|
||||
"libghostty-vt.a";
|
||||
b.getInstallStep().dependOn(&b.addInstallLibFile(
|
||||
libghostty_vt_static.output,
|
||||
static_lib_name,
|
||||
).step);
|
||||
}
|
||||
|
||||
// Helpgen
|
||||
if (config.emit_helpgen) deps.help_strings.install();
|
||||
|
||||
|
|
@ -128,26 +139,34 @@ pub fn build(b: *std.Build) !void {
|
|||
resources.install();
|
||||
if (i18n) |v| v.install();
|
||||
}
|
||||
} else {
|
||||
// Libghostty
|
||||
} else if (!config.emit_lib_vt) {
|
||||
// The macOS Ghostty Library
|
||||
//
|
||||
// Note: libghostty is not stable for general purpose use. It is used
|
||||
// heavily by Ghostty on macOS but it isn't built to be reusable yet.
|
||||
// As such, these build steps are lacking. For example, the Darwin
|
||||
// build only produces an xcframework.
|
||||
// This is NOT libghostty (even though its named that for historical
|
||||
// reasons). It is just the glue between Ghostty GUI on macOS and
|
||||
// the full Ghostty GUI core.
|
||||
const lib_shared = try buildpkg.GhosttyLib.initShared(b, &deps);
|
||||
const lib_static = try buildpkg.GhosttyLib.initStatic(b, &deps);
|
||||
|
||||
// We shouldn't have this guard but we don't currently
|
||||
// build on macOS this way ironically so we need to fix that.
|
||||
if (!config.target.result.os.tag.isDarwin()) {
|
||||
libghostty_shared.installHeader(); // Only need one header
|
||||
libghostty_shared.install("libghostty.so");
|
||||
libghostty_static.install("libghostty.a");
|
||||
lib_shared.installHeader(); // Only need one header
|
||||
if (config.target.result.os.tag == .windows) {
|
||||
lib_shared.install("ghostty.dll");
|
||||
lib_static.install("ghostty-static.lib");
|
||||
} else {
|
||||
lib_shared.install("libghostty.so");
|
||||
lib_static.install("libghostty.a");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// macOS only artifacts. These will error if they're initialized for
|
||||
// other targets.
|
||||
if (config.target.result.os.tag.isDarwin()) {
|
||||
if (config.target.result.os.tag.isDarwin() and
|
||||
(config.emit_xcframework or config.emit_macos_app))
|
||||
{
|
||||
// Ghostty xcframework
|
||||
const xcframework = try buildpkg.GhosttyXCFramework.init(
|
||||
b,
|
||||
|
|
@ -202,7 +221,9 @@ pub fn build(b: *std.Build) !void {
|
|||
|
||||
// On macOS we can run the macOS app. For "run" we always force
|
||||
// a native-only build so that we can run as quickly as possible.
|
||||
if (config.target.result.os.tag.isDarwin()) {
|
||||
if (config.target.result.os.tag.isDarwin() and
|
||||
(config.emit_xcframework or config.emit_macos_app))
|
||||
{
|
||||
const xcframework_native = try buildpkg.GhosttyXCFramework.init(
|
||||
b,
|
||||
&deps,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
.{
|
||||
.name = .ghostty,
|
||||
.version = "1.3.0-dev",
|
||||
.version = "1.3.2-dev",
|
||||
.paths = .{""},
|
||||
.fingerprint = 0x64407a2a0b4147e5,
|
||||
.minimum_zig_version = "0.15.2",
|
||||
|
|
@ -91,8 +91,8 @@
|
|||
.lazy = true,
|
||||
},
|
||||
.wayland_protocols = .{
|
||||
.url = "https://deps.files.ghostty.org/wayland-protocols-258d8f88f2c8c25a830c6316f87d23ce1a0f12d9.tar.gz",
|
||||
.hash = "N-V-__8AAKw-DAAaV8bOAAGqA0-oD7o-HNIlPFYKRXSPT03S",
|
||||
.url = "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/1.47/wayland-protocols-1.47.tar.gz",
|
||||
.hash = "N-V-__8AAFdWDwA0ktbNUi9pFBHCRN4weXIgIfCrVjfGxqgA",
|
||||
.lazy = true,
|
||||
},
|
||||
.plasma_wayland_protocols = .{
|
||||
|
|
|
|||
|
|
@ -139,6 +139,11 @@
|
|||
"url": "https://deps.files.ghostty.org/wayland-protocols-258d8f88f2c8c25a830c6316f87d23ce1a0f12d9.tar.gz",
|
||||
"hash": "sha256-XO3K3egbdeYPI+XoO13SuOtO+5+Peb16NH0UiusFMPg="
|
||||
},
|
||||
"N-V-__8AAFdWDwA0ktbNUi9pFBHCRN4weXIgIfCrVjfGxqgA": {
|
||||
"name": "wayland_protocols",
|
||||
"url": "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/1.47/wayland-protocols-1.47.tar.gz",
|
||||
"hash": "sha256-3S3xSrX0EDgleq7cxLX7msDuAY8/D5SvkJcCjmDTMiM="
|
||||
},
|
||||
"N-V-__8AAAzZywE3s51XfsLbP9eyEw57ae9swYB9aGB6fCMs": {
|
||||
"name": "wuffs",
|
||||
"url": "https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd.tar.gz",
|
||||
|
|
|
|||
|
|
@ -306,6 +306,14 @@ in
|
|||
hash = "sha256-XO3K3egbdeYPI+XoO13SuOtO+5+Peb16NH0UiusFMPg=";
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "N-V-__8AAFdWDwA0ktbNUi9pFBHCRN4weXIgIfCrVjfGxqgA";
|
||||
path = fetchZigArtifact {
|
||||
name = "wayland_protocols";
|
||||
url = "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/1.47/wayland-protocols-1.47.tar.gz";
|
||||
hash = "sha256-3S3xSrX0EDgleq7cxLX7msDuAY8/D5SvkJcCjmDTMiM=";
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "N-V-__8AAAzZywE3s51XfsLbP9eyEw57ae9swYB9aGB6fCMs";
|
||||
path = fetchZigArtifact {
|
||||
|
|
|
|||
|
|
@ -34,3 +34,4 @@ https://deps.files.ghostty.org/zig_wayland-1b5c038ec10da20ed3a15b0b2a6db1c21383e
|
|||
https://deps.files.ghostty.org/zlib-1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb.tar.gz
|
||||
https://github.com/ivanstepanovftw/zigimg/archive/d7b7ab0ba0899643831ef042bd73289510b39906.tar.gz
|
||||
https://github.com/ocornut/imgui/archive/refs/tags/v1.92.5-docking.tar.gz
|
||||
https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/1.47/wayland-protocols-1.47.tar.gz
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
# CMake Support for libghostty-vt
|
||||
|
||||
The top-level `CMakeLists.txt` wraps the Zig build system so that CMake
|
||||
projects can consume libghostty-vt without invoking `zig build` manually.
|
||||
Running `cmake --build` triggers `zig build -Demit-lib-vt` automatically.
|
||||
|
||||
This means downstream projects do require a working Zig compiler on
|
||||
`PATH` to build, but don't need to know any Zig-specific details.
|
||||
|
||||
## Using FetchContent (recommended)
|
||||
|
||||
Add the following to your project's `CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(ghostty
|
||||
GIT_REPOSITORY https://github.com/ghostty-org/ghostty.git
|
||||
GIT_TAG main
|
||||
)
|
||||
FetchContent_MakeAvailable(ghostty)
|
||||
|
||||
add_executable(myapp main.c)
|
||||
target_link_libraries(myapp PRIVATE ghostty-vt)
|
||||
```
|
||||
|
||||
This fetches the Ghostty source, builds libghostty-vt via Zig during your
|
||||
CMake build, and links it into your target. Headers are added to the
|
||||
include path automatically.
|
||||
|
||||
### Using a local checkout
|
||||
|
||||
If you already have the Ghostty source checked out, skip the download by
|
||||
pointing CMake at it:
|
||||
|
||||
```shell-session
|
||||
cmake -B build -DFETCHCONTENT_SOURCE_DIR_GHOSTTY=/path/to/ghostty
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
## Using find_package (install-based)
|
||||
|
||||
Build and install libghostty-vt first:
|
||||
|
||||
```shell-session
|
||||
cd /path/to/ghostty
|
||||
cmake -B build
|
||||
cmake --build build
|
||||
cmake --install build --prefix /usr/local
|
||||
```
|
||||
|
||||
Then in your project:
|
||||
|
||||
```cmake
|
||||
find_package(ghostty-vt REQUIRED)
|
||||
|
||||
add_executable(myapp main.c)
|
||||
target_link_libraries(myapp PRIVATE ghostty-vt::ghostty-vt)
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
- `ghostty-vt-config.cmake.in` — template for the CMake package config
|
||||
file installed alongside the library, enabling `find_package()` support.
|
||||
|
||||
## Example
|
||||
|
||||
See `example/c-vt-cmake/` for a complete working example.
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
set(_ghostty_vt_libdir "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@")
|
||||
|
||||
# Shared library target
|
||||
if(NOT TARGET ghostty-vt::ghostty-vt)
|
||||
add_library(ghostty-vt::ghostty-vt SHARED IMPORTED)
|
||||
|
||||
if(WIN32)
|
||||
set(_ghostty_vt_shared_location "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_BINDIR@/@GHOSTTY_VT_REALNAME@")
|
||||
else()
|
||||
set(_ghostty_vt_shared_location "${_ghostty_vt_libdir}/@GHOSTTY_VT_REALNAME@")
|
||||
endif()
|
||||
|
||||
set_target_properties(ghostty-vt::ghostty-vt PROPERTIES
|
||||
IMPORTED_LOCATION "${_ghostty_vt_shared_location}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@"
|
||||
)
|
||||
unset(_ghostty_vt_shared_location)
|
||||
|
||||
if(APPLE)
|
||||
set_target_properties(ghostty-vt::ghostty-vt PROPERTIES
|
||||
IMPORTED_SONAME "@rpath/@GHOSTTY_VT_SONAME@"
|
||||
INTERFACE_LINK_DIRECTORIES "${_ghostty_vt_libdir}"
|
||||
)
|
||||
# Ensure consumers can find the @rpath dylib at runtime
|
||||
set_property(TARGET ghostty-vt::ghostty-vt APPEND PROPERTY
|
||||
INTERFACE_LINK_OPTIONS "LINKER:-rpath,${_ghostty_vt_libdir}"
|
||||
)
|
||||
elseif(WIN32)
|
||||
set_target_properties(ghostty-vt::ghostty-vt PROPERTIES
|
||||
IMPORTED_IMPLIB "${_ghostty_vt_libdir}/@GHOSTTY_VT_IMPLIB@"
|
||||
)
|
||||
else()
|
||||
set_target_properties(ghostty-vt::ghostty-vt PROPERTIES
|
||||
IMPORTED_SONAME "@GHOSTTY_VT_SONAME@"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Static library target
|
||||
#
|
||||
# Consumers must link transitive dependencies themselves. By default (with
|
||||
# SIMD enabled): libc, libc++ (or libstdc++ on Linux), highway, and
|
||||
# simdutf. Building with -Dsimd=false removes the C++ / highway / simdutf
|
||||
# dependencies.
|
||||
if(NOT TARGET ghostty-vt::ghostty-vt-static)
|
||||
add_library(ghostty-vt::ghostty-vt-static STATIC IMPORTED)
|
||||
|
||||
set_target_properties(ghostty-vt::ghostty-vt-static PROPERTIES
|
||||
IMPORTED_LOCATION "${_ghostty_vt_libdir}/@GHOSTTY_VT_STATIC_REALNAME@"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@"
|
||||
)
|
||||
if(WIN32)
|
||||
set_target_properties(ghostty-vt::ghostty-vt-static PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES "ntdll;kernel32"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
unset(_ghostty_vt_libdir)
|
||||
|
||||
check_required_components(ghostty-vt)
|
||||
|
|
@ -52,6 +52,12 @@
|
|||
|
||||
<releases>
|
||||
<!-- TODO: Generate this automatically -->
|
||||
<release version="1.3.1" date="2026-03-13">
|
||||
<url type="details">https://ghostty.org/docs/install/release-notes/1-3-1</url>
|
||||
</release>
|
||||
<release version="1.3.0" date="2026-03-09">
|
||||
<url type="details">https://ghostty.org/docs/install/release-notes/1-3-0</url>
|
||||
</release>
|
||||
<release version="1.0.1" date="2024-12-31">
|
||||
<url type="details">https://ghostty.org/docs/install/release-notes/1-0-1</url>
|
||||
</release>
|
||||
|
|
|
|||
|
|
@ -7,5 +7,4 @@ Actions=RunGhosttyDir
|
|||
[Desktop Action RunGhosttyDir]
|
||||
Name=Open Ghostty Here
|
||||
Icon=com.mitchellh.ghostty
|
||||
Exec=ghostty --working-directory=%F --gtk-single-instance=false
|
||||
|
||||
Exec=ghostty +new-window --working-directory=%F
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@
|
|||
dist/
|
||||
node_modules/
|
||||
example.wasm*
|
||||
build/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
# Example Libghostty Projects
|
||||
|
||||
Each example is a standalone project with its own `build.zig`,
|
||||
`build.zig.zon`, `README.md`, and `src/main.c` (or `.zig`). Examples are
|
||||
auto-discovered by CI via `example/*/build.zig.zon`, so no workflow file
|
||||
edits are needed when adding a new example.
|
||||
|
||||
## Adding a New Example
|
||||
|
||||
1. Copy an existing example directory (e.g., `c-vt-encode-focus/`) as a
|
||||
starting point.
|
||||
2. Update `build.zig.zon`: change `.name`, generate a **new unique**
|
||||
`.fingerprint` value (a random `u64` hex literal), and keep
|
||||
`.minimum_zig_version` matching the others.
|
||||
3. Update `build.zig`: change the executable `.name` to match the directory.
|
||||
4. Write a `README.md` following the existing format.
|
||||
|
||||
## Doxygen Snippet Tags
|
||||
|
||||
Example source files use Doxygen `@snippet` tags so the corresponding
|
||||
header in `include/ghostty/vt/` can reference them. Wrap the relevant
|
||||
code with `//! [snippet-name]` markers:
|
||||
|
||||
```c
|
||||
//! [my-snippet]
|
||||
int main() { ... }
|
||||
//! [my-snippet]
|
||||
```
|
||||
|
||||
The header then uses `@snippet <dir>/src/main.c my-snippet` instead of
|
||||
inline `@code` blocks. Never duplicate example code inline in the
|
||||
headers — always use `@snippet`. When modifying example code, keep the
|
||||
snippet markers in sync with the headers in `include/ghostty/vt/`.
|
||||
|
||||
## Conventions
|
||||
|
||||
- Executable names use underscores: `c_vt_encode_focus` (not hyphens).
|
||||
- All C examples link `ghostty-vt` via `lazyDependency("ghostty", ...)`.
|
||||
- `build.zig` files follow a common template — keep them consistent.
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# Examples
|
||||
|
||||
Standalone projects demonstrating the Ghostty library APIs.
|
||||
The directories starting with `c-` use the C API and the directories
|
||||
starting with `zig-` use the Zig API.
|
||||
|
||||
Every example can be built and run using `zig build` and `zig build run`
|
||||
from within the respective example directory.
|
||||
Even the C API examples use the Zig build system (not the language) to
|
||||
build the project.
|
||||
|
||||
## Running an Example
|
||||
|
||||
```shell-session
|
||||
cd example/<dir>
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# Example: `ghostty-vt` Build Info
|
||||
|
||||
This contains a simple example of how to use the `ghostty-vt` build info
|
||||
API to query compile-time build configuration.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -29,7 +29,7 @@ pub fn build(b: *std.Build) void {
|
|||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_key_encode",
|
||||
.name = "c_vt_build_info",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_build_info,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0xc6b57ed4f83fb16,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#include <stdio.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [build-info-query]
|
||||
void query_build_info() {
|
||||
bool simd = false;
|
||||
bool kitty_graphics = false;
|
||||
bool tmux_control_mode = false;
|
||||
|
||||
ghostty_build_info(GHOSTTY_BUILD_INFO_SIMD, &simd);
|
||||
ghostty_build_info(GHOSTTY_BUILD_INFO_KITTY_GRAPHICS, &kitty_graphics);
|
||||
ghostty_build_info(GHOSTTY_BUILD_INFO_TMUX_CONTROL_MODE, &tmux_control_mode);
|
||||
|
||||
printf("SIMD: %s\n", simd ? "enabled" : "disabled");
|
||||
printf("Kitty graphics: %s\n", kitty_graphics ? "enabled" : "disabled");
|
||||
printf("Tmux control mode: %s\n", tmux_control_mode ? "enabled" : "disabled");
|
||||
}
|
||||
//! [build-info-query]
|
||||
|
||||
int main() {
|
||||
query_build_info();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
cmake_minimum_required(VERSION 3.19)
|
||||
project(c-vt-cmake-static LANGUAGES C)
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(ghostty
|
||||
GIT_REPOSITORY https://github.com/ghostty-org/ghostty.git
|
||||
GIT_TAG main
|
||||
)
|
||||
set(GHOSTTY_ZIG_BUILD_FLAGS "-Dsimd=false" CACHE STRING "" FORCE)
|
||||
FetchContent_MakeAvailable(ghostty)
|
||||
|
||||
add_executable(c_vt_cmake_static src/main.c)
|
||||
target_link_libraries(c_vt_cmake_static PRIVATE ghostty-vt-static)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# c-vt-cmake-static
|
||||
|
||||
Demonstrates consuming libghostty-vt as a **static** library from a CMake
|
||||
project using `FetchContent`. Creates a terminal, writes VT sequences into
|
||||
it, and formats the screen contents as plain text.
|
||||
|
||||
## Building
|
||||
|
||||
```shell-session
|
||||
cd example/c-vt-cmake-static
|
||||
cmake -B build
|
||||
cmake --build build
|
||||
./build/c_vt_cmake_static
|
||||
```
|
||||
|
||||
To build against a local checkout instead of fetching from GitHub:
|
||||
|
||||
```shell-session
|
||||
cmake -B build -DFETCHCONTENT_SOURCE_DIR_GHOSTTY=../..
|
||||
cmake --build build
|
||||
```
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
// Create a terminal with a small grid
|
||||
GhosttyTerminal terminal;
|
||||
GhosttyTerminalOptions opts = {
|
||||
.cols = 80,
|
||||
.rows = 24,
|
||||
.max_scrollback = 0,
|
||||
};
|
||||
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Write some VT-encoded content into the terminal
|
||||
const char *commands[] = {
|
||||
"Hello from a \033[1mCMake\033[0m-built program (static)!\r\n",
|
||||
"Line 2: \033[4munderlined\033[0m text\r\n",
|
||||
"Line 3: \033[31mred\033[0m \033[32mgreen\033[0m \033[34mblue\033[0m\r\n",
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) {
|
||||
ghostty_terminal_vt_write(terminal, (const uint8_t *)commands[i],
|
||||
strlen(commands[i]));
|
||||
}
|
||||
|
||||
// Format the terminal contents as plain text
|
||||
GhosttyFormatterTerminalOptions fmt_opts =
|
||||
GHOSTTY_INIT_SIZED(GhosttyFormatterTerminalOptions);
|
||||
fmt_opts.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN;
|
||||
fmt_opts.trim = true;
|
||||
|
||||
GhosttyFormatter formatter;
|
||||
result = ghostty_formatter_terminal_new(NULL, &formatter, terminal, fmt_opts);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
uint8_t *buf = NULL;
|
||||
size_t len = 0;
|
||||
result = ghostty_formatter_format_alloc(formatter, NULL, &buf, &len);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
printf("Plain text (%zu bytes):\n", len);
|
||||
fwrite(buf, 1, len, stdout);
|
||||
printf("\n");
|
||||
|
||||
ghostty_free(NULL, buf, len);
|
||||
ghostty_formatter_free(formatter);
|
||||
ghostty_terminal_free(terminal);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
cmake_minimum_required(VERSION 3.19)
|
||||
project(c-vt-cmake LANGUAGES C)
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(ghostty
|
||||
GIT_REPOSITORY https://github.com/ghostty-org/ghostty.git
|
||||
GIT_TAG main
|
||||
)
|
||||
FetchContent_MakeAvailable(ghostty)
|
||||
|
||||
add_executable(c_vt_cmake src/main.c)
|
||||
target_link_libraries(c_vt_cmake PRIVATE ghostty-vt)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# c-vt-cmake
|
||||
|
||||
Demonstrates consuming libghostty-vt from a CMake project using
|
||||
`FetchContent`. Creates a terminal, writes VT sequences into it, and
|
||||
formats the screen contents as plain text.
|
||||
|
||||
## Building
|
||||
|
||||
```shell-session
|
||||
cd example/c-vt-cmake
|
||||
cmake -B build
|
||||
cmake --build build
|
||||
./build/c_vt_cmake
|
||||
```
|
||||
|
||||
To build against a local checkout instead of fetching from GitHub:
|
||||
|
||||
```shell-session
|
||||
cmake -B build -DFETCHCONTENT_SOURCE_DIR_GHOSTTY=../..
|
||||
cmake --build build
|
||||
```
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
// Create a terminal with a small grid
|
||||
GhosttyTerminal terminal;
|
||||
GhosttyTerminalOptions opts = {
|
||||
.cols = 80,
|
||||
.rows = 24,
|
||||
.max_scrollback = 0,
|
||||
};
|
||||
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Write some VT-encoded content into the terminal
|
||||
const char *commands[] = {
|
||||
"Hello from a \033[1mCMake\033[0m-built program!\r\n",
|
||||
"Line 2: \033[4munderlined\033[0m text\r\n",
|
||||
"Line 3: \033[31mred\033[0m \033[32mgreen\033[0m \033[34mblue\033[0m\r\n",
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) {
|
||||
ghostty_terminal_vt_write(terminal, (const uint8_t *)commands[i],
|
||||
strlen(commands[i]));
|
||||
}
|
||||
|
||||
// Format the terminal contents as plain text
|
||||
GhosttyFormatterTerminalOptions fmt_opts =
|
||||
GHOSTTY_INIT_SIZED(GhosttyFormatterTerminalOptions);
|
||||
fmt_opts.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN;
|
||||
fmt_opts.trim = true;
|
||||
|
||||
GhosttyFormatter formatter;
|
||||
result = ghostty_formatter_terminal_new(NULL, &formatter, terminal, fmt_opts);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
uint8_t *buf = NULL;
|
||||
size_t len = 0;
|
||||
result = ghostty_formatter_format_alloc(formatter, NULL, &buf, &len);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
printf("Plain text (%zu bytes):\n", len);
|
||||
fwrite(buf, 1, len, stdout);
|
||||
printf("\n");
|
||||
|
||||
ghostty_free(NULL, buf, len);
|
||||
ghostty_formatter_free(formatter);
|
||||
ghostty_terminal_free(terminal);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# Example: `ghostty-vt` Terminal Effects
|
||||
|
||||
This contains a simple example of how to register and use terminal
|
||||
effect callbacks (`write_pty`, `bell`, `title_changed`) with the
|
||||
`ghostty-vt` C library.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_effects",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_effects,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0xc02634cd65f5b583,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [effects-write-pty]
|
||||
void on_write_pty(GhosttyTerminal terminal,
|
||||
void* userdata,
|
||||
const uint8_t* data,
|
||||
size_t len) {
|
||||
(void)terminal;
|
||||
(void)userdata;
|
||||
printf(" write_pty (%zu bytes): ", len);
|
||||
fwrite(data, 1, len, stdout);
|
||||
printf("\n");
|
||||
}
|
||||
//! [effects-write-pty]
|
||||
|
||||
//! [effects-bell]
|
||||
void on_bell(GhosttyTerminal terminal, void* userdata) {
|
||||
(void)terminal;
|
||||
int* count = (int*)userdata;
|
||||
(*count)++;
|
||||
printf(" bell! (count=%d)\n", *count);
|
||||
}
|
||||
//! [effects-bell]
|
||||
|
||||
//! [effects-title-changed]
|
||||
void on_title_changed(GhosttyTerminal terminal, void* userdata) {
|
||||
(void)userdata;
|
||||
// Query the cursor position to confirm the terminal processed the
|
||||
// title change (the title itself is tracked by the embedder via the
|
||||
// OSC parser or its own state).
|
||||
uint16_t col = 0;
|
||||
ghostty_terminal_get(terminal, GHOSTTY_TERMINAL_DATA_CURSOR_X, &col);
|
||||
printf(" title changed (cursor at col %u)\n", col);
|
||||
}
|
||||
//! [effects-title-changed]
|
||||
|
||||
//! [effects-register]
|
||||
int main() {
|
||||
// Create a terminal
|
||||
GhosttyTerminal terminal = NULL;
|
||||
GhosttyTerminalOptions opts = {
|
||||
.cols = 80,
|
||||
.rows = 24,
|
||||
.max_scrollback = 0,
|
||||
};
|
||||
if (ghostty_terminal_new(NULL, &terminal, opts) != GHOSTTY_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create terminal\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set up userdata — a simple bell counter
|
||||
int bell_count = 0;
|
||||
ghostty_terminal_set(terminal, GHOSTTY_TERMINAL_OPT_USERDATA, &bell_count);
|
||||
|
||||
// Register effect callbacks
|
||||
ghostty_terminal_set(terminal, GHOSTTY_TERMINAL_OPT_WRITE_PTY,
|
||||
(const void *)on_write_pty);
|
||||
ghostty_terminal_set(terminal, GHOSTTY_TERMINAL_OPT_BELL,
|
||||
(const void *)on_bell);
|
||||
ghostty_terminal_set(terminal, GHOSTTY_TERMINAL_OPT_TITLE_CHANGED,
|
||||
(const void *)on_title_changed);
|
||||
|
||||
// Feed VT data that triggers effects:
|
||||
|
||||
// 1. Bell (BEL = 0x07)
|
||||
printf("Sending BEL:\n");
|
||||
const uint8_t bel = 0x07;
|
||||
ghostty_terminal_vt_write(terminal, &bel, 1);
|
||||
|
||||
// 2. Title change (OSC 2 ; <title> ST)
|
||||
printf("Sending title change:\n");
|
||||
const char* title_seq = "\x1B]2;Hello Effects\x1B\\";
|
||||
ghostty_terminal_vt_write(terminal, (const uint8_t*)title_seq,
|
||||
strlen(title_seq));
|
||||
|
||||
// 3. Device status report (DECRQM for wraparound mode ?7)
|
||||
// triggers write_pty with the response
|
||||
printf("Sending DECRQM query:\n");
|
||||
const char* decrqm = "\x1B[?7$p";
|
||||
ghostty_terminal_vt_write(terminal, (const uint8_t*)decrqm,
|
||||
strlen(decrqm));
|
||||
|
||||
// 4. Another bell to show the counter increments
|
||||
printf("Sending another BEL:\n");
|
||||
ghostty_terminal_vt_write(terminal, &bel, 1);
|
||||
|
||||
printf("Total bells: %d\n", bell_count);
|
||||
|
||||
ghostty_terminal_free(terminal);
|
||||
return 0;
|
||||
}
|
||||
//! [effects-register]
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# Example: `ghostty-vt` Encode Focus
|
||||
|
||||
This contains a simple example of how to use the `ghostty-vt` focus
|
||||
encoding API to encode focus gained/lost events into escape sequences.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_encode_focus",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_encode_focus,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0x89f01fd829fcc550,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include <stdio.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [focus-encode]
|
||||
int main() {
|
||||
char buf[8];
|
||||
size_t written = 0;
|
||||
|
||||
GhosttyResult result = ghostty_focus_encode(
|
||||
GHOSTTY_FOCUS_GAINED, buf, sizeof(buf), &written);
|
||||
|
||||
if (result == GHOSTTY_SUCCESS) {
|
||||
printf("Encoded %zu bytes: ", written);
|
||||
fwrite(buf, 1, written, stdout);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [focus-encode]
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_encode_key",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [key-encode]
|
||||
int main() {
|
||||
// Create encoder
|
||||
GhosttyKeyEncoder encoder;
|
||||
GhosttyResult result = ghostty_key_encoder_new(NULL, &encoder);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Enable Kitty keyboard protocol with all features
|
||||
ghostty_key_encoder_setopt(encoder, GHOSTTY_KEY_ENCODER_OPT_KITTY_FLAGS,
|
||||
&(uint8_t){GHOSTTY_KITTY_KEY_ALL});
|
||||
|
||||
// Create and configure key event for Ctrl+C press
|
||||
GhosttyKeyEvent event;
|
||||
result = ghostty_key_event_new(NULL, &event);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
ghostty_key_event_set_action(event, GHOSTTY_KEY_ACTION_PRESS);
|
||||
ghostty_key_event_set_key(event, GHOSTTY_KEY_C);
|
||||
ghostty_key_event_set_mods(event, GHOSTTY_MODS_CTRL);
|
||||
|
||||
// Encode the key event
|
||||
char buf[128];
|
||||
size_t written = 0;
|
||||
result = ghostty_key_encoder_encode(encoder, event, buf, sizeof(buf), &written);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Use the encoded sequence (e.g., write to terminal)
|
||||
fwrite(buf, 1, written, stdout);
|
||||
|
||||
// Cleanup
|
||||
ghostty_key_event_free(event);
|
||||
ghostty_key_encoder_free(encoder);
|
||||
return 0;
|
||||
}
|
||||
//! [key-encode]
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Example: `ghostty-vt` C Mouse Encoding
|
||||
|
||||
This example demonstrates how to use the `ghostty-vt` C library to encode mouse
|
||||
events into terminal escape sequences.
|
||||
|
||||
This example specifically shows how to:
|
||||
|
||||
1. Create a mouse encoder with the C API
|
||||
2. Configure tracking mode and output format (this example uses SGR)
|
||||
3. Set terminal geometry for pixel-to-cell coordinate mapping
|
||||
4. Create and configure a mouse event
|
||||
5. Encode the mouse event into a terminal escape sequence
|
||||
|
||||
The example encodes a left button press at pixel position (50, 40) using SGR
|
||||
format, producing an escape sequence like `\x1b[<0;6;3M`.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_encode_mouse",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0x413a8529a6dd3c51,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [mouse-encode]
|
||||
int main() {
|
||||
// Create encoder
|
||||
GhosttyMouseEncoder encoder;
|
||||
GhosttyResult result = ghostty_mouse_encoder_new(NULL, &encoder);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Configure SGR format with normal tracking
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_EVENT,
|
||||
&(GhosttyMouseTrackingMode){GHOSTTY_MOUSE_TRACKING_NORMAL});
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_FORMAT,
|
||||
&(GhosttyMouseFormat){GHOSTTY_MOUSE_FORMAT_SGR});
|
||||
|
||||
// Set terminal geometry for coordinate mapping
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_SIZE,
|
||||
&(GhosttyMouseEncoderSize){
|
||||
.size = sizeof(GhosttyMouseEncoderSize),
|
||||
.screen_width = 800, .screen_height = 600,
|
||||
.cell_width = 10, .cell_height = 20,
|
||||
});
|
||||
|
||||
// Create and configure a left button press event
|
||||
GhosttyMouseEvent event;
|
||||
result = ghostty_mouse_event_new(NULL, &event);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
ghostty_mouse_event_set_action(event, GHOSTTY_MOUSE_ACTION_PRESS);
|
||||
ghostty_mouse_event_set_button(event, GHOSTTY_MOUSE_BUTTON_LEFT);
|
||||
ghostty_mouse_event_set_position(event,
|
||||
(GhosttyMousePosition){.x = 50.0f, .y = 40.0f});
|
||||
|
||||
// Encode the mouse event
|
||||
char buf[128];
|
||||
size_t written = 0;
|
||||
result = ghostty_mouse_encoder_encode(encoder, event,
|
||||
buf, sizeof(buf), &written);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Use the encoded sequence (e.g., write to terminal)
|
||||
fwrite(buf, 1, written, stdout);
|
||||
|
||||
// Cleanup
|
||||
ghostty_mouse_event_free(event);
|
||||
ghostty_mouse_encoder_free(encoder);
|
||||
return 0;
|
||||
}
|
||||
//! [mouse-encode]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# Example: `ghostty-vt` Terminal Formatter
|
||||
|
||||
This contains a simple example of how to use the `ghostty-vt` terminal and
|
||||
formatter APIs to create a terminal, write VT-encoded content into it, and
|
||||
format the screen contents as plain text.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_formatter",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_formatter,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0x9e3758265677a0c4,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
// Create a terminal with a small grid
|
||||
GhosttyTerminal terminal;
|
||||
GhosttyTerminalOptions opts = {
|
||||
.cols = 80,
|
||||
.rows = 24,
|
||||
.max_scrollback = 0,
|
||||
};
|
||||
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Write VT-encoded content into the terminal to exercise various
|
||||
// cursor movement and styling sequences.
|
||||
const char *commands[] = {
|
||||
"Line 1: Hello World!\r\n", // Simple text on row 1
|
||||
"Line 2: \033[1mBold\033[0m and " // Bold text on row 2
|
||||
"\033[4mUnderline\033[0m\r\n",
|
||||
"Line 3: placeholder\r\n", // Will be overwritten below
|
||||
"\033[3;1H", // CUP: move cursor back to row 3, col 1
|
||||
"\033[2K", // EL: erase the entire line
|
||||
"Line 3: Overwritten!\r\n", // Rewrite row 3 with new content
|
||||
"\033[5;10H", // CUP: jump to row 5, col 10
|
||||
"Placed at (5,10)", // Write at that position
|
||||
"\033[1;72H", // CUP: jump to row 1, col 72
|
||||
"RIGHT->", // Near the right edge of row 1
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) {
|
||||
ghostty_terminal_vt_write(terminal, (const uint8_t *)commands[i],
|
||||
strlen(commands[i]));
|
||||
}
|
||||
|
||||
// Create a plain-text formatter for the terminal
|
||||
GhosttyFormatterTerminalOptions fmt_opts = GHOSTTY_INIT_SIZED(GhosttyFormatterTerminalOptions);
|
||||
fmt_opts.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN;
|
||||
fmt_opts.trim = true;
|
||||
|
||||
GhosttyFormatter formatter;
|
||||
result = ghostty_formatter_terminal_new(NULL, &formatter, terminal, fmt_opts);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Format into an allocated buffer
|
||||
uint8_t *buf = NULL;
|
||||
size_t len = 0;
|
||||
result = ghostty_formatter_format_alloc(formatter, NULL, &buf, &len);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Print the formatted output
|
||||
printf("Formatted output (%zu bytes):\n", len);
|
||||
fwrite(buf, 1, len, stdout);
|
||||
printf("\n");
|
||||
|
||||
// Clean up
|
||||
ghostty_free(NULL, buf, len);
|
||||
ghostty_formatter_free(formatter);
|
||||
ghostty_terminal_free(terminal);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# Example: `ghostty-vt` Grid Traversal
|
||||
|
||||
This contains a simple example of how to use the `ghostty-vt` terminal and
|
||||
grid reference APIs to create a terminal, write content into it, and then
|
||||
traverse the entire grid cell-by-cell using grid refs to inspect codepoints,
|
||||
row state, and styles.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_grid_traverse",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_grid_traverse,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0xf694dd12db9be040,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [grid-ref-traverse]
|
||||
int main() {
|
||||
// Create a small terminal
|
||||
GhosttyTerminal terminal;
|
||||
GhosttyTerminalOptions opts = {
|
||||
.cols = 10,
|
||||
.rows = 3,
|
||||
.max_scrollback = 0,
|
||||
};
|
||||
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Write some content so the grid has interesting data
|
||||
const char *text = "Hello!\r\n" // Row 0: H e l l o !
|
||||
"World\r\n" // Row 1: W o r l d
|
||||
"\033[1mBold"; // Row 2: B o l d (bold style)
|
||||
ghostty_terminal_vt_write(
|
||||
terminal, (const uint8_t *)text, strlen(text));
|
||||
|
||||
// Get terminal dimensions
|
||||
uint16_t cols, rows;
|
||||
ghostty_terminal_get(terminal, GHOSTTY_TERMINAL_DATA_COLS, &cols);
|
||||
ghostty_terminal_get(terminal, GHOSTTY_TERMINAL_DATA_ROWS, &rows);
|
||||
|
||||
// Traverse the entire grid using grid refs
|
||||
for (uint16_t row = 0; row < rows; row++) {
|
||||
printf("Row %u: ", row);
|
||||
for (uint16_t col = 0; col < cols; col++) {
|
||||
// Resolve the point to a grid reference
|
||||
GhosttyGridRef ref = GHOSTTY_INIT_SIZED(GhosttyGridRef);
|
||||
GhosttyPoint pt = {
|
||||
.tag = GHOSTTY_POINT_TAG_ACTIVE,
|
||||
.value = { .coordinate = { .x = col, .y = row } },
|
||||
};
|
||||
result = ghostty_terminal_grid_ref(terminal, pt, &ref);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Read the cell from the grid ref
|
||||
GhosttyCell cell;
|
||||
result = ghostty_grid_ref_cell(&ref, &cell);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Check if the cell has text
|
||||
bool has_text = false;
|
||||
ghostty_cell_get(cell, GHOSTTY_CELL_DATA_HAS_TEXT, &has_text);
|
||||
|
||||
if (has_text) {
|
||||
uint32_t codepoint = 0;
|
||||
ghostty_cell_get(cell, GHOSTTY_CELL_DATA_CODEPOINT, &codepoint);
|
||||
printf("%c", (char)codepoint);
|
||||
} else {
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
|
||||
// Also inspect the row for wrap state
|
||||
GhosttyGridRef ref = GHOSTTY_INIT_SIZED(GhosttyGridRef);
|
||||
GhosttyPoint pt = {
|
||||
.tag = GHOSTTY_POINT_TAG_ACTIVE,
|
||||
.value = { .coordinate = { .x = 0, .y = row } },
|
||||
};
|
||||
ghostty_terminal_grid_ref(terminal, pt, &ref);
|
||||
|
||||
GhosttyRow grid_row;
|
||||
ghostty_grid_ref_row(&ref, &grid_row);
|
||||
|
||||
bool wrap = false;
|
||||
ghostty_row_get(grid_row, GHOSTTY_ROW_DATA_WRAP, &wrap);
|
||||
printf(" (wrap=%s", wrap ? "true" : "false");
|
||||
|
||||
// Check the style of the first cell with text
|
||||
GhosttyStyle style = GHOSTTY_INIT_SIZED(GhosttyStyle);
|
||||
ghostty_grid_ref_style(&ref, &style);
|
||||
printf(", bold=%s)\n", style.bold ? "true" : "false");
|
||||
}
|
||||
|
||||
ghostty_terminal_free(terminal);
|
||||
return 0;
|
||||
}
|
||||
//! [grid-ref-traverse]
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
GhosttyKeyEncoder encoder;
|
||||
GhosttyResult result = ghostty_key_encoder_new(NULL, &encoder);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Set kitty flags with all features enabled
|
||||
ghostty_key_encoder_setopt(encoder, GHOSTTY_KEY_ENCODER_OPT_KITTY_FLAGS, &(uint8_t){GHOSTTY_KITTY_KEY_ALL});
|
||||
|
||||
// Create key event
|
||||
GhosttyKeyEvent event;
|
||||
result = ghostty_key_event_new(NULL, &event);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
ghostty_key_event_set_action(event, GHOSTTY_KEY_ACTION_RELEASE);
|
||||
ghostty_key_event_set_key(event, GHOSTTY_KEY_CONTROL_LEFT);
|
||||
ghostty_key_event_set_mods(event, GHOSTTY_MODS_CTRL);
|
||||
printf("Encoding event: left ctrl release with all Kitty flags enabled\n");
|
||||
|
||||
// Optionally, encode with null buffer to get required size. You can
|
||||
// skip this step and provide a sufficiently large buffer directly.
|
||||
// If there isn't enoug hspace, the function will return an out of memory
|
||||
// error.
|
||||
size_t required = 0;
|
||||
result = ghostty_key_encoder_encode(encoder, event, NULL, 0, &required);
|
||||
assert(result == GHOSTTY_OUT_OF_MEMORY);
|
||||
printf("Required buffer size: %zu bytes\n", required);
|
||||
|
||||
// Encode the key event. We don't use our required size above because
|
||||
// that was just an example; we know 128 bytes is enough.
|
||||
char buf[128];
|
||||
size_t written = 0;
|
||||
result = ghostty_key_encoder_encode(encoder, event, buf, sizeof(buf), &written);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
printf("Encoded %zu bytes\n", written);
|
||||
|
||||
// Print the encoded sequence (hex and string)
|
||||
printf("Hex: ");
|
||||
for (size_t i = 0; i < written; i++) printf("%02x ", (unsigned char)buf[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("String: ");
|
||||
for (size_t i = 0; i < written; i++) {
|
||||
if (buf[i] == 0x1b) {
|
||||
printf("\\x1b");
|
||||
} else {
|
||||
printf("%c", buf[i]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
ghostty_key_event_free(event);
|
||||
ghostty_key_encoder_free(encoder);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# Example: `ghostty-vt` Mode Utilities
|
||||
|
||||
This contains a simple example of how to use the `ghostty-vt` mode
|
||||
utilities to pack and unpack terminal mode identifiers and encode
|
||||
DECRPM responses.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_modes",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_modes,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0x67ce079ebc70a02a,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
#include <stdio.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [modes-pack-unpack]
|
||||
void modes_example() {
|
||||
// Create a mode for DEC mode 25 (cursor visible)
|
||||
GhosttyMode tag = ghostty_mode_new(25, false);
|
||||
printf("value=%u ansi=%d packed=0x%04x\n",
|
||||
ghostty_mode_value(tag),
|
||||
ghostty_mode_ansi(tag),
|
||||
tag);
|
||||
|
||||
// Create a mode for ANSI mode 4 (insert mode)
|
||||
GhosttyMode ansi_tag = ghostty_mode_new(4, true);
|
||||
printf("value=%u ansi=%d packed=0x%04x\n",
|
||||
ghostty_mode_value(ansi_tag),
|
||||
ghostty_mode_ansi(ansi_tag),
|
||||
ansi_tag);
|
||||
}
|
||||
//! [modes-pack-unpack]
|
||||
|
||||
//! [modes-decrpm]
|
||||
void decrpm_example() {
|
||||
char buf[32];
|
||||
size_t written = 0;
|
||||
|
||||
// Encode a report that DEC mode 25 (cursor visible) is set
|
||||
GhosttyResult result = ghostty_mode_report_encode(
|
||||
GHOSTTY_MODE_CURSOR_VISIBLE,
|
||||
GHOSTTY_MODE_REPORT_SET,
|
||||
buf, sizeof(buf), &written);
|
||||
|
||||
if (result == GHOSTTY_SUCCESS) {
|
||||
printf("Encoded %zu bytes: ", written);
|
||||
fwrite(buf, 1, written, stdout);
|
||||
printf("\n"); // prints: ESC[?25;1$y
|
||||
}
|
||||
}
|
||||
//! [modes-decrpm]
|
||||
|
||||
int main() {
|
||||
modes_example();
|
||||
decrpm_example();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2,18 +2,23 @@
|
|||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
// Test safe paste data
|
||||
const char *safe_data = "hello world";
|
||||
//! [paste-safety]
|
||||
void basic_example() {
|
||||
const char* safe_data = "hello world";
|
||||
const char* unsafe_data = "rm -rf /\n";
|
||||
|
||||
if (ghostty_paste_is_safe(safe_data, strlen(safe_data))) {
|
||||
printf("'%s' is safe to paste\n", safe_data);
|
||||
printf("Safe to paste\n");
|
||||
}
|
||||
|
||||
// Test unsafe paste data with newline
|
||||
const char *unsafe_newline = "rm -rf /\n";
|
||||
if (!ghostty_paste_is_safe(unsafe_newline, strlen(unsafe_newline))) {
|
||||
printf("'%s' is UNSAFE - contains newline\n", unsafe_newline);
|
||||
if (!ghostty_paste_is_safe(unsafe_data, strlen(unsafe_data))) {
|
||||
printf("Unsafe! Contains newline\n");
|
||||
}
|
||||
}
|
||||
//! [paste-safety]
|
||||
|
||||
int main() {
|
||||
basic_example();
|
||||
|
||||
// Test unsafe paste data with bracketed paste end sequence
|
||||
const char *unsafe_escape = "evil\x1b[201~code";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# Example: `ghostty-vt` Render State
|
||||
|
||||
This contains an example of how to use the `ghostty-vt` render-state API
|
||||
to create a render state, update it from terminal content, iterate rows
|
||||
and cells, read styles and colors, inspect cursor state, and manage dirty
|
||||
tracking.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_render",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_render,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0xb10e18b2fab773c9,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
/// Helper: resolve a style color to an RGB value using the palette.
|
||||
static GhosttyColorRgb resolve_color(GhosttyStyleColor color,
|
||||
const GhosttyRenderStateColors* colors,
|
||||
GhosttyColorRgb fallback) {
|
||||
switch (color.tag) {
|
||||
case GHOSTTY_STYLE_COLOR_RGB:
|
||||
return color.value.rgb;
|
||||
case GHOSTTY_STYLE_COLOR_PALETTE:
|
||||
return colors->palette[color.value.palette];
|
||||
default:
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
GhosttyResult result;
|
||||
|
||||
//! [render-state-update]
|
||||
// Create a terminal and render state, then update the render state
|
||||
// from the terminal. The render state captures a snapshot of everything
|
||||
// needed to draw a frame.
|
||||
GhosttyTerminal terminal = NULL;
|
||||
GhosttyTerminalOptions terminal_opts = {
|
||||
.cols = 40,
|
||||
.rows = 5,
|
||||
.max_scrollback = 10000,
|
||||
};
|
||||
result = ghostty_terminal_new(NULL, &terminal, terminal_opts);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
GhosttyRenderState render_state = NULL;
|
||||
result = ghostty_render_state_new(NULL, &render_state);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Feed some styled content into the terminal.
|
||||
const char* content =
|
||||
"Hello, \033[1;32mworld\033[0m!\r\n" // bold green "world"
|
||||
"\033[4munderlined\033[0m text\r\n" // underlined text
|
||||
"\033[38;2;255;128;0morange\033[0m\r\n"; // 24-bit orange fg
|
||||
ghostty_terminal_vt_write(
|
||||
terminal, (const uint8_t*)content, strlen(content));
|
||||
|
||||
result = ghostty_render_state_update(render_state, terminal);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
//! [render-state-update]
|
||||
|
||||
//! [render-dirty-check]
|
||||
// Check the global dirty state to decide how much work the renderer
|
||||
// needs to do. After rendering, reset it to false.
|
||||
GhosttyRenderStateDirty dirty;
|
||||
result = ghostty_render_state_get(
|
||||
render_state, GHOSTTY_RENDER_STATE_DATA_DIRTY, &dirty);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
switch (dirty) {
|
||||
case GHOSTTY_RENDER_STATE_DIRTY_FALSE:
|
||||
printf("Frame is clean, nothing to draw.\n");
|
||||
break;
|
||||
case GHOSTTY_RENDER_STATE_DIRTY_PARTIAL:
|
||||
printf("Partial redraw needed.\n");
|
||||
break;
|
||||
case GHOSTTY_RENDER_STATE_DIRTY_FULL:
|
||||
printf("Full redraw needed.\n");
|
||||
break;
|
||||
}
|
||||
//! [render-dirty-check]
|
||||
|
||||
//! [render-colors]
|
||||
// Retrieve colors (background, foreground, palette) from the render
|
||||
// state. These are needed to resolve palette-indexed cell colors.
|
||||
GhosttyRenderStateColors colors =
|
||||
GHOSTTY_INIT_SIZED(GhosttyRenderStateColors);
|
||||
result = ghostty_render_state_colors_get(render_state, &colors);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
printf("Background: #%02x%02x%02x\n",
|
||||
colors.background.r, colors.background.g, colors.background.b);
|
||||
printf("Foreground: #%02x%02x%02x\n",
|
||||
colors.foreground.r, colors.foreground.g, colors.foreground.b);
|
||||
//! [render-colors]
|
||||
|
||||
//! [render-cursor]
|
||||
// Read cursor position and visual style from the render state.
|
||||
bool cursor_visible = false;
|
||||
ghostty_render_state_get(
|
||||
render_state, GHOSTTY_RENDER_STATE_DATA_CURSOR_VISIBLE,
|
||||
&cursor_visible);
|
||||
|
||||
bool cursor_in_viewport = false;
|
||||
ghostty_render_state_get(
|
||||
render_state, GHOSTTY_RENDER_STATE_DATA_CURSOR_VIEWPORT_HAS_VALUE,
|
||||
&cursor_in_viewport);
|
||||
|
||||
if (cursor_visible && cursor_in_viewport) {
|
||||
uint16_t cx, cy;
|
||||
ghostty_render_state_get(
|
||||
render_state, GHOSTTY_RENDER_STATE_DATA_CURSOR_VIEWPORT_X, &cx);
|
||||
ghostty_render_state_get(
|
||||
render_state, GHOSTTY_RENDER_STATE_DATA_CURSOR_VIEWPORT_Y, &cy);
|
||||
|
||||
GhosttyRenderStateCursorVisualStyle style;
|
||||
ghostty_render_state_get(
|
||||
render_state, GHOSTTY_RENDER_STATE_DATA_CURSOR_VISUAL_STYLE,
|
||||
&style);
|
||||
|
||||
const char* style_name = "unknown";
|
||||
switch (style) {
|
||||
case GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_BAR:
|
||||
style_name = "bar";
|
||||
break;
|
||||
case GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_BLOCK:
|
||||
style_name = "block";
|
||||
break;
|
||||
case GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_UNDERLINE:
|
||||
style_name = "underline";
|
||||
break;
|
||||
case GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_BLOCK_HOLLOW:
|
||||
style_name = "hollow";
|
||||
break;
|
||||
}
|
||||
printf("Cursor at (%u, %u), style: %s\n", cx, cy, style_name);
|
||||
}
|
||||
//! [render-cursor]
|
||||
|
||||
//! [render-row-iterate]
|
||||
// Iterate rows via the row iterator. For each dirty row, iterate its
|
||||
// cells, read codepoints/graphemes and styles, and emit ANSI-colored
|
||||
// output as a simple "renderer".
|
||||
GhosttyRenderStateRowIterator row_iter = NULL;
|
||||
result = ghostty_render_state_row_iterator_new(NULL, &row_iter);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
result = ghostty_render_state_get(
|
||||
render_state, GHOSTTY_RENDER_STATE_DATA_ROW_ITERATOR, &row_iter);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
GhosttyRenderStateRowCells cells = NULL;
|
||||
result = ghostty_render_state_row_cells_new(NULL, &cells);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
int row_index = 0;
|
||||
while (ghostty_render_state_row_iterator_next(row_iter)) {
|
||||
// Check per-row dirty state; a real renderer would skip clean rows.
|
||||
bool row_dirty = false;
|
||||
ghostty_render_state_row_get(
|
||||
row_iter, GHOSTTY_RENDER_STATE_ROW_DATA_DIRTY, &row_dirty);
|
||||
|
||||
printf("Row %2d [%s]: ", row_index,
|
||||
row_dirty ? "dirty" : "clean");
|
||||
|
||||
// Get cells for this row (reuses the same cells handle).
|
||||
result = ghostty_render_state_row_get(
|
||||
row_iter, GHOSTTY_RENDER_STATE_ROW_DATA_CELLS, &cells);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
while (ghostty_render_state_row_cells_next(cells)) {
|
||||
// Get the grapheme length; 0 means the cell is empty.
|
||||
uint32_t grapheme_len = 0;
|
||||
ghostty_render_state_row_cells_get(
|
||||
cells, GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_GRAPHEMES_LEN,
|
||||
&grapheme_len);
|
||||
|
||||
if (grapheme_len == 0) {
|
||||
putchar(' ');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read the style for this cell. Returns the default style for
|
||||
// cells that have no explicit styling.
|
||||
GhosttyStyle style = GHOSTTY_INIT_SIZED(GhosttyStyle);
|
||||
ghostty_render_state_row_cells_get(
|
||||
cells, GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_STYLE, &style);
|
||||
|
||||
// Resolve foreground color for this cell.
|
||||
GhosttyColorRgb fg =
|
||||
resolve_color(style.fg_color, &colors, colors.foreground);
|
||||
|
||||
// Emit ANSI true-color escape for the foreground.
|
||||
printf("\033[38;2;%u;%u;%um", fg.r, fg.g, fg.b);
|
||||
if (style.bold) printf("\033[1m");
|
||||
if (style.underline) printf("\033[4m");
|
||||
|
||||
// Read grapheme codepoints into a buffer and print them.
|
||||
// The buffer must be at least grapheme_len elements.
|
||||
uint32_t codepoints[16];
|
||||
uint32_t len = grapheme_len < 16 ? grapheme_len : 16;
|
||||
ghostty_render_state_row_cells_get(
|
||||
cells, GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_GRAPHEMES_BUF,
|
||||
codepoints);
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
// Simple ASCII print; a real renderer would handle UTF-8.
|
||||
if (codepoints[i] < 128)
|
||||
putchar((char)codepoints[i]);
|
||||
else
|
||||
printf("U+%04X", codepoints[i]);
|
||||
}
|
||||
|
||||
printf("\033[0m"); // Reset style after each cell.
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
// Clear per-row dirty flag after "rendering" it.
|
||||
bool clean = false;
|
||||
ghostty_render_state_row_set(
|
||||
row_iter, GHOSTTY_RENDER_STATE_ROW_OPTION_DIRTY, &clean);
|
||||
|
||||
row_index++;
|
||||
}
|
||||
//! [render-row-iterate]
|
||||
|
||||
//! [render-dirty-reset]
|
||||
// After finishing the frame, reset the global dirty state so the next
|
||||
// update can report changes accurately.
|
||||
GhosttyRenderStateDirty clean_state = GHOSTTY_RENDER_STATE_DIRTY_FALSE;
|
||||
result = ghostty_render_state_set(
|
||||
render_state, GHOSTTY_RENDER_STATE_OPTION_DIRTY, &clean_state);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
//! [render-dirty-reset]
|
||||
|
||||
// Cleanup
|
||||
ghostty_render_state_row_cells_free(cells);
|
||||
ghostty_render_state_row_iterator_free(row_iter);
|
||||
ghostty_render_state_free(render_state);
|
||||
ghostty_terminal_free(terminal);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2,12 +2,43 @@
|
|||
#include <stdio.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
//! [sgr-basic]
|
||||
void basic_example() {
|
||||
// Create parser
|
||||
GhosttySgrParser parser;
|
||||
GhosttyResult result = ghostty_sgr_new(NULL, &parser);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Parse "bold, red foreground" sequence: ESC[1;31m
|
||||
uint16_t params[] = {1, 31};
|
||||
result = ghostty_sgr_set_params(parser, params, NULL, 2);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Iterate through attributes
|
||||
GhosttySgrAttribute attr;
|
||||
while (ghostty_sgr_next(parser, &attr)) {
|
||||
switch (attr.tag) {
|
||||
case GHOSTTY_SGR_ATTR_BOLD:
|
||||
printf("Bold enabled\n");
|
||||
break;
|
||||
case GHOSTTY_SGR_ATTR_FG_8:
|
||||
printf("Foreground color: %d\n", attr.value.fg_8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
ghostty_sgr_free(parser);
|
||||
}
|
||||
//! [sgr-basic]
|
||||
|
||||
void advanced_example() {
|
||||
GhosttySgrParser parser;
|
||||
GhosttyResult result = ghostty_sgr_new(NULL, &parser);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Parse a complex SGR sequence from Kakoune
|
||||
// This corresponds to the escape sequence:
|
||||
// ESC[4:3;38;2;51;51;51;48;2;170;170;170;58;2;255;97;136m
|
||||
|
|
@ -26,10 +57,9 @@ int main() {
|
|||
result = ghostty_sgr_set_params(parser, params, separators, sizeof(params) / sizeof(params[0]));
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
printf("Parsing Kakoune SGR sequence:\n");
|
||||
printf("\nParsing Kakoune SGR sequence:\n");
|
||||
printf("ESC[4:3;38;2;51;51;51;48;2;170;170;170;58;2;255;97;136m\n\n");
|
||||
|
||||
// Iterate through attributes
|
||||
GhosttySgrAttribute attr;
|
||||
int count = 0;
|
||||
while (ghostty_sgr_next(parser, &attr)) {
|
||||
|
|
@ -124,8 +154,11 @@ int main() {
|
|||
}
|
||||
|
||||
printf("\nTotal attributes parsed: %d\n", count);
|
||||
|
||||
// Cleanup
|
||||
ghostty_sgr_free(parser);
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_example();
|
||||
advanced_example();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# Example: `ghostty-vt` Size Report Encoding
|
||||
|
||||
This contains a simple example of how to use the `ghostty-vt` size report
|
||||
encoding API to encode terminal size reports into escape sequences.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_size_report",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_size_report,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0x17e8cdb658fab232,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include <stdio.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [size-report-encode]
|
||||
int main() {
|
||||
GhosttySizeReportSize size = {
|
||||
.rows = 24,
|
||||
.columns = 80,
|
||||
.cell_width = 9,
|
||||
.cell_height = 18,
|
||||
};
|
||||
|
||||
char buf[64];
|
||||
size_t written = 0;
|
||||
|
||||
GhosttyResult result = ghostty_size_report_encode(
|
||||
GHOSTTY_SIZE_REPORT_MODE_2048, size, buf, sizeof(buf), &written);
|
||||
|
||||
if (result == GHOSTTY_SUCCESS) {
|
||||
printf("Encoded %zu bytes: ", written);
|
||||
fwrite(buf, 1, written, stdout);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [size-report-encode]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# Example: `ghostty-vt` Static Linking
|
||||
|
||||
This contains a simple example of how to statically link the `ghostty-vt`
|
||||
C library with a C program using the `ghostty-vt-static` artifact. It is
|
||||
otherwise identical to the `c-vt` example.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
// Use "ghostty-vt-static" for static linking instead of
|
||||
// "ghostty-vt" which provides a shared library.
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt-static"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_static",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_static,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0xa592a9fdd5d87ed2,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
GhosttyOscParser parser;
|
||||
if (ghostty_osc_new(NULL, &parser) != GHOSTTY_SUCCESS) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Setup change window title command to change the title to "hello"
|
||||
ghostty_osc_next(parser, '0');
|
||||
ghostty_osc_next(parser, ';');
|
||||
const char *title = "hello";
|
||||
for (size_t i = 0; i < strlen(title); i++) {
|
||||
ghostty_osc_next(parser, title[i]);
|
||||
}
|
||||
|
||||
// End parsing and get command
|
||||
GhosttyOscCommand command = ghostty_osc_end(parser, 0);
|
||||
|
||||
// Get and print command type
|
||||
GhosttyOscCommandType type = ghostty_osc_command_type(command);
|
||||
printf("Command type: %d\n", type);
|
||||
|
||||
// Extract and print the title
|
||||
if (ghostty_osc_command_data(command, GHOSTTY_OSC_DATA_CHANGE_WINDOW_TITLE_STR, &title)) {
|
||||
printf("Extracted title: %s\n", title);
|
||||
} else {
|
||||
printf("Failed to extract title\n");
|
||||
}
|
||||
|
||||
ghostty_osc_free(parser);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ to encode key events into terminal escape sequences.
|
|||
First, build the WebAssembly module:
|
||||
|
||||
```bash
|
||||
zig build lib-vt -Dtarget=wasm32-freestanding -Doptimize=ReleaseSmall
|
||||
zig build -Demit-lib-vt -Dtarget=wasm32-freestanding -Doptimize=ReleaseSmall
|
||||
```
|
||||
|
||||
This will create `zig-out/bin/ghostty-vt.wasm`.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ styling attributes.
|
|||
First, build the WebAssembly module:
|
||||
|
||||
```bash
|
||||
zig build lib-vt -Dtarget=wasm32-freestanding -Doptimize=ReleaseSmall
|
||||
zig build -Demit-lib-vt -Dtarget=wasm32-freestanding -Doptimize=ReleaseSmall
|
||||
```
|
||||
|
||||
This will create `zig-out/bin/ghostty-vt.wasm`.
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ pub fn main() !void {
|
|||
|
||||
// Replace \n with \r\n
|
||||
for (buf[0..n]) |byte| {
|
||||
if (byte == '\n') try stream.next('\r');
|
||||
try stream.next(byte);
|
||||
if (byte == '\n') stream.next('\r');
|
||||
stream.next(byte);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,24 +14,24 @@ pub fn main() !void {
|
|||
defer stream.deinit();
|
||||
|
||||
// Basic text with newline
|
||||
try stream.nextSlice("Hello, World!\r\n");
|
||||
stream.nextSlice("Hello, World!\r\n");
|
||||
|
||||
// ANSI color codes: ESC[1;32m = bold green, ESC[0m = reset
|
||||
try stream.nextSlice("\x1b[1;32mGreen Text\x1b[0m\r\n");
|
||||
stream.nextSlice("\x1b[1;32mGreen Text\x1b[0m\r\n");
|
||||
|
||||
// Cursor positioning: ESC[1;1H = move to row 1, column 1
|
||||
try stream.nextSlice("\x1b[1;1HTop-left corner\r\n");
|
||||
stream.nextSlice("\x1b[1;1HTop-left corner\r\n");
|
||||
|
||||
// Cursor movement: ESC[5B = move down 5 lines
|
||||
try stream.nextSlice("\x1b[5B");
|
||||
try stream.nextSlice("Moved down!\r\n");
|
||||
stream.nextSlice("\x1b[5B");
|
||||
stream.nextSlice("Moved down!\r\n");
|
||||
|
||||
// Erase line: ESC[2K = clear entire line
|
||||
try stream.nextSlice("\x1b[2K");
|
||||
try stream.nextSlice("New content\r\n");
|
||||
stream.nextSlice("\x1b[2K");
|
||||
stream.nextSlice("New content\r\n");
|
||||
|
||||
// Multiple lines
|
||||
try stream.nextSlice("Line A\r\nLine B\r\nLine C\r\n");
|
||||
stream.nextSlice("Line A\r\nLine B\r\nLine C\r\n");
|
||||
|
||||
// Get the final terminal state as a plain string
|
||||
const str = try t.plainString(alloc);
|
||||
|
|
|
|||
33
flake.lock
33
flake.lock
|
|
@ -16,24 +16,6 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
|
@ -70,14 +52,15 @@
|
|||
"root": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"home-manager": "home-manager",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems",
|
||||
"zig": "zig",
|
||||
"zon2nix": "zon2nix"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
|
|
@ -97,19 +80,19 @@
|
|||
"flake-compat": [
|
||||
"flake-compat"
|
||||
],
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1763295135,
|
||||
"narHash": "sha256-sGv/NHCmEnJivguGwB5w8LRmVqr1P72OjS+NzcJsssE=",
|
||||
"lastModified": 1773145353,
|
||||
"narHash": "sha256-dE8zx8WA54TRmFFQBvA48x/sXGDTP7YaDmY6nNKMAYw=",
|
||||
"owner": "mitchellh",
|
||||
"repo": "zig-overlay",
|
||||
"rev": "64f8b42cfc615b2cf99144adf2b7728c7847c72a",
|
||||
"rev": "8666155d83bf792956a7c40915508e6d4b2b8716",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
# Gnome 49/Gtk 4.20.
|
||||
#
|
||||
nixpkgs.url = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
# Used for shell.nix
|
||||
flake-compat = {
|
||||
|
|
@ -18,12 +17,17 @@
|
|||
flake = false;
|
||||
};
|
||||
|
||||
systems = {
|
||||
url = "github:nix-systems/default";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
zig = {
|
||||
url = "github:mitchellh/zig-overlay";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
flake-utils.follows = "flake-utils";
|
||||
flake-compat.follows = "flake-compat";
|
||||
systems.follows = "systems";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -167,6 +167,12 @@
|
|||
"dest": "vendor/p/N-V-__8AAKw-DAAaV8bOAAGqA0-oD7o-HNIlPFYKRXSPT03S",
|
||||
"sha256": "5cedcadde81b75e60f23e5e83b5dd2b8eb4efb9f8f79bd7a347d148aeb0530f8"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/1.47/wayland-protocols-1.47.tar.gz",
|
||||
"dest": "vendor/p/N-V-__8AAFdWDwA0ktbNUi9pFBHCRN4weXIgIfCrVjfGxqgA",
|
||||
"sha256": "dd2df14ab5f41038257aaedcc4b5fb9ac0ee018f3f0f94af9097028e60d33223"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd.tar.gz",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ extern "C" {
|
|||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <BaseTsd.h>
|
||||
typedef SSIZE_T ssize_t;
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Macros
|
||||
|
||||
|
|
@ -889,6 +894,7 @@ typedef enum {
|
|||
GHOSTTY_ACTION_RENDER_INSPECTOR,
|
||||
GHOSTTY_ACTION_DESKTOP_NOTIFICATION,
|
||||
GHOSTTY_ACTION_SET_TITLE,
|
||||
GHOSTTY_ACTION_SET_TAB_TITLE,
|
||||
GHOSTTY_ACTION_PROMPT_TITLE,
|
||||
GHOSTTY_ACTION_PWD,
|
||||
GHOSTTY_ACTION_MOUSE_SHAPE,
|
||||
|
|
@ -937,6 +943,7 @@ typedef union {
|
|||
ghostty_action_inspector_e inspector;
|
||||
ghostty_action_desktop_notification_s desktop_notification;
|
||||
ghostty_action_set_title_s set_title;
|
||||
ghostty_action_set_title_s set_tab_title;
|
||||
ghostty_action_prompt_title_e prompt_title;
|
||||
ghostty_action_pwd_s pwd;
|
||||
ghostty_action_mouse_shape_e mouse_shape;
|
||||
|
|
@ -968,7 +975,7 @@ typedef struct {
|
|||
} ghostty_action_s;
|
||||
|
||||
typedef void (*ghostty_runtime_wakeup_cb)(void*);
|
||||
typedef void (*ghostty_runtime_read_clipboard_cb)(void*,
|
||||
typedef bool (*ghostty_runtime_read_clipboard_cb)(void*,
|
||||
ghostty_clipboard_e,
|
||||
void*);
|
||||
typedef void (*ghostty_runtime_confirm_read_clipboard_cb)(
|
||||
|
|
|
|||
|
|
@ -28,33 +28,55 @@
|
|||
* @section groups_sec API Reference
|
||||
*
|
||||
* The API is organized into the following groups:
|
||||
* - @ref key "Key Encoding" - Encode key events into terminal sequences
|
||||
* - @ref terminal "Terminal" - Complete terminal emulator state and rendering
|
||||
* - @ref render "Render State" - Incremental render state updates for custom renderers
|
||||
* - @ref formatter "Formatter" - Format terminal content as plain text, VT sequences, or HTML
|
||||
* - @ref osc "OSC Parser" - Parse OSC (Operating System Command) sequences
|
||||
* - @ref sgr "SGR Parser" - Parse SGR (Select Graphic Rendition) sequences
|
||||
* - @ref paste "Paste Utilities" - Validate paste data safety
|
||||
* - @ref build_info "Build Info" - Query compile-time build configuration
|
||||
* - @ref allocator "Memory Management" - Memory management and custom allocators
|
||||
* - @ref wasm "WebAssembly Utilities" - WebAssembly convenience functions
|
||||
*
|
||||
* Encoding related APIs:
|
||||
* - @ref focus "Focus Encoding" - Encode focus in/out events into terminal sequences
|
||||
* - @ref key "Key Encoding" - Encode key events into terminal sequences
|
||||
* - @ref mouse "Mouse Encoding" - Encode mouse events into terminal sequences
|
||||
*
|
||||
* @section examples_sec Examples
|
||||
*
|
||||
* Complete working examples:
|
||||
* - @ref c-vt-build-info/src/main.c - Build info query example
|
||||
* - @ref c-vt/src/main.c - OSC parser example
|
||||
* - @ref c-vt-key-encode/src/main.c - Key encoding example
|
||||
* - @ref c-vt-encode-key/src/main.c - Key encoding example
|
||||
* - @ref c-vt-encode-mouse/src/main.c - Mouse encoding example
|
||||
* - @ref c-vt-paste/src/main.c - Paste safety check example
|
||||
* - @ref c-vt-sgr/src/main.c - SGR parser example
|
||||
* - @ref c-vt-formatter/src/main.c - Terminal formatter example
|
||||
* - @ref c-vt-grid-traverse/src/main.c - Grid traversal example using grid refs
|
||||
*
|
||||
*/
|
||||
|
||||
/** @example c-vt-build-info/src/main.c
|
||||
* This example demonstrates how to query compile-time build configuration
|
||||
* such as SIMD support, Kitty graphics, and tmux control mode availability.
|
||||
*/
|
||||
|
||||
/** @example c-vt/src/main.c
|
||||
* This example demonstrates how to use the OSC parser to parse an OSC sequence,
|
||||
* extract command information, and retrieve command-specific data like window titles.
|
||||
*/
|
||||
|
||||
/** @example c-vt-key-encode/src/main.c
|
||||
/** @example c-vt-encode-key/src/main.c
|
||||
* This example demonstrates how to use the key encoder to convert key events
|
||||
* into terminal escape sequences using the Kitty keyboard protocol.
|
||||
*/
|
||||
|
||||
/** @example c-vt-encode-mouse/src/main.c
|
||||
* This example demonstrates how to use the mouse encoder to convert mouse events
|
||||
* into terminal escape sequences using the SGR mouse format.
|
||||
*/
|
||||
|
||||
/** @example c-vt-paste/src/main.c
|
||||
* This example demonstrates how to use the paste utilities to check if
|
||||
* paste data is safe before sending it to the terminal.
|
||||
|
|
@ -65,6 +87,17 @@
|
|||
* styling sequences and extract text attributes like colors and underline styles.
|
||||
*/
|
||||
|
||||
/** @example c-vt-formatter/src/main.c
|
||||
* This example demonstrates how to use the terminal and formatter APIs to
|
||||
* create a terminal, write VT-encoded content into it, and format the screen
|
||||
* contents as plain text.
|
||||
*/
|
||||
|
||||
/** @example c-vt-grid-traverse/src/main.c
|
||||
* This example demonstrates how to traverse the entire terminal grid using
|
||||
* grid refs to inspect cell codepoints, row wrap state, and cell styles.
|
||||
*/
|
||||
|
||||
#ifndef GHOSTTY_VT_H
|
||||
#define GHOSTTY_VT_H
|
||||
|
||||
|
|
@ -72,12 +105,25 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <ghostty/vt/result.h>
|
||||
#include <ghostty/vt/types.h>
|
||||
#include <ghostty/vt/allocator.h>
|
||||
#include <ghostty/vt/build_info.h>
|
||||
#include <ghostty/vt/color.h>
|
||||
#include <ghostty/vt/device.h>
|
||||
#include <ghostty/vt/focus.h>
|
||||
#include <ghostty/vt/formatter.h>
|
||||
#include <ghostty/vt/render.h>
|
||||
#include <ghostty/vt/terminal.h>
|
||||
#include <ghostty/vt/grid_ref.h>
|
||||
#include <ghostty/vt/osc.h>
|
||||
#include <ghostty/vt/sgr.h>
|
||||
#include <ghostty/vt/style.h>
|
||||
#include <ghostty/vt/key.h>
|
||||
#include <ghostty/vt/modes.h>
|
||||
#include <ghostty/vt/mouse.h>
|
||||
#include <ghostty/vt/paste.h>
|
||||
#include <ghostty/vt/screen.h>
|
||||
#include <ghostty/vt/size_report.h>
|
||||
#include <ghostty/vt/wasm.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -44,6 +44,24 @@
|
|||
* 2. Create a GhosttyAllocator struct with your vtable and context
|
||||
* 3. Pass the allocator to functions that accept one
|
||||
*
|
||||
* ## Alloc/Free Helpers
|
||||
*
|
||||
* ghostty_alloc() and ghostty_free() provide a simple malloc/free-style
|
||||
* interface for allocating and freeing byte buffers through the library's
|
||||
* allocator. These are useful when:
|
||||
*
|
||||
* - You need to allocate a buffer to pass into a libghostty-vt function
|
||||
* (e.g. preparing input data for ghostty_terminal_vt_write()).
|
||||
* - You need to free a buffer returned by a libghostty-vt function
|
||||
* (e.g. the output of ghostty_formatter_format_alloc()).
|
||||
* - You are on a platform where the library's internal allocator differs
|
||||
* from the consumer's C runtime (e.g. Windows, where Zig's libc and
|
||||
* MSVC's CRT maintain separate heaps), so calling the standard C
|
||||
* free() on library-allocated memory would be undefined behavior.
|
||||
*
|
||||
* Always use the same allocator (or NULL) for both the allocation and
|
||||
* the corresponding free.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
|
@ -191,6 +209,46 @@ typedef struct GhosttyAllocator {
|
|||
const GhosttyAllocatorVtable *vtable;
|
||||
} GhosttyAllocator;
|
||||
|
||||
/**
|
||||
* Allocate a buffer of `len` bytes.
|
||||
*
|
||||
* Uses the provided allocator, or the default allocator if NULL is passed.
|
||||
* The returned buffer must be freed with ghostty_free() using the same
|
||||
* allocator.
|
||||
*
|
||||
* @param allocator Pointer to the allocator to use, or NULL for the default
|
||||
* @param len Number of bytes to allocate
|
||||
* @return Pointer to the allocated buffer, or NULL if allocation failed
|
||||
*
|
||||
* @ingroup allocator
|
||||
*/
|
||||
uint8_t* ghostty_alloc(const GhosttyAllocator* allocator, size_t len);
|
||||
|
||||
/**
|
||||
* Free memory that was allocated by a libghostty-vt function.
|
||||
*
|
||||
* Use this to free buffers returned by functions such as
|
||||
* ghostty_formatter_format_alloc(). Pass the same allocator that was
|
||||
* used for the allocation, or NULL if the default allocator was used.
|
||||
*
|
||||
* On platforms where the library's internal allocator differs from the
|
||||
* consumer's C runtime (e.g. Windows, where Zig's libc and MSVC's CRT
|
||||
* maintain separate heaps), calling the standard C free() on memory
|
||||
* allocated by the library causes undefined behavior. This function
|
||||
* guarantees the correct allocator is used regardless of platform.
|
||||
*
|
||||
* It is safe to pass a NULL pointer; the call is a no-op in that case.
|
||||
*
|
||||
* @param allocator Pointer to the allocator that was used to allocate the
|
||||
* memory, or NULL if the default allocator was used
|
||||
* @param ptr Pointer to the memory to free (may be NULL)
|
||||
* @param len Length of the allocation in bytes (must match the original
|
||||
* allocation size)
|
||||
*
|
||||
* @ingroup allocator
|
||||
*/
|
||||
void ghostty_free(const GhosttyAllocator* allocator, uint8_t* ptr, size_t len);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* GHOSTTY_VT_ALLOCATOR_H */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* @file build_info.h
|
||||
*
|
||||
* Build info - query compile-time build configuration of libghostty-vt.
|
||||
*/
|
||||
|
||||
#ifndef GHOSTTY_VT_BUILD_INFO_H
|
||||
#define GHOSTTY_VT_BUILD_INFO_H
|
||||
|
||||
/** @defgroup build_info Build Info
|
||||
*
|
||||
* Query compile-time build configuration of libghostty-vt.
|
||||
*
|
||||
* These values reflect the options the library was built with and are
|
||||
* constant for the lifetime of the process.
|
||||
*
|
||||
* ## Basic Usage
|
||||
*
|
||||
* Use ghostty_build_info() to query individual build options:
|
||||
*
|
||||
* @snippet c-vt-build-info/src/main.c build-info-query
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <ghostty/vt/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Build optimization mode.
|
||||
*/
|
||||
typedef enum {
|
||||
GHOSTTY_OPTIMIZE_DEBUG = 0,
|
||||
GHOSTTY_OPTIMIZE_RELEASE_SAFE = 1,
|
||||
GHOSTTY_OPTIMIZE_RELEASE_SMALL = 2,
|
||||
GHOSTTY_OPTIMIZE_RELEASE_FAST = 3,
|
||||
} GhosttyOptimizeMode;
|
||||
|
||||
/**
|
||||
* Build info data types that can be queried.
|
||||
*
|
||||
* Each variant documents the expected output pointer type.
|
||||
*/
|
||||
typedef enum {
|
||||
/** Invalid data type. Never results in any data extraction. */
|
||||
GHOSTTY_BUILD_INFO_INVALID = 0,
|
||||
|
||||
/**
|
||||
* Whether SIMD-accelerated code paths are enabled.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_BUILD_INFO_SIMD = 1,
|
||||
|
||||
/**
|
||||
* Whether Kitty graphics protocol support is available.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_BUILD_INFO_KITTY_GRAPHICS = 2,
|
||||
|
||||
/**
|
||||
* Whether tmux control mode support is available.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_BUILD_INFO_TMUX_CONTROL_MODE = 3,
|
||||
|
||||
/**
|
||||
* The optimization mode the library was built with.
|
||||
*
|
||||
* Output type: GhosttyOptimizeMode *
|
||||
*/
|
||||
GHOSTTY_BUILD_INFO_OPTIMIZE = 4,
|
||||
} GhosttyBuildInfo;
|
||||
|
||||
/**
|
||||
* Query a compile-time build configuration value.
|
||||
*
|
||||
* The caller must pass a pointer to the correct output type for the
|
||||
* requested data (see GhosttyBuildInfo variants for types).
|
||||
*
|
||||
* @param data The build info field to query
|
||||
* @param out Pointer to store the result (type depends on data parameter)
|
||||
* @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the
|
||||
* data type is invalid
|
||||
*
|
||||
* @ingroup build_info
|
||||
*/
|
||||
GhosttyResult ghostty_build_info(GhosttyBuildInfo data, void *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* GHOSTTY_VT_BUILD_INFO_H */
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
* @file device.h
|
||||
*
|
||||
* Device types used by the terminal for device status and device attribute
|
||||
* queries.
|
||||
*/
|
||||
|
||||
#ifndef GHOSTTY_VT_DEVICE_H
|
||||
#define GHOSTTY_VT_DEVICE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* DA1 conformance levels (Pp parameter). */
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT100 1
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT101 1
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT102 6
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT125 12
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT131 7
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT132 4
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT220 62
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT240 62
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT320 63
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT340 63
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT420 64
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT510 65
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT520 65
|
||||
#define GHOSTTY_DA_CONFORMANCE_VT525 65
|
||||
#define GHOSTTY_DA_CONFORMANCE_LEVEL_2 62
|
||||
#define GHOSTTY_DA_CONFORMANCE_LEVEL_3 63
|
||||
#define GHOSTTY_DA_CONFORMANCE_LEVEL_4 64
|
||||
#define GHOSTTY_DA_CONFORMANCE_LEVEL_5 65
|
||||
|
||||
/* DA1 feature codes (Ps parameters). */
|
||||
#define GHOSTTY_DA_FEATURE_COLUMNS_132 1
|
||||
#define GHOSTTY_DA_FEATURE_PRINTER 2
|
||||
#define GHOSTTY_DA_FEATURE_REGIS 3
|
||||
#define GHOSTTY_DA_FEATURE_SIXEL 4
|
||||
#define GHOSTTY_DA_FEATURE_SELECTIVE_ERASE 6
|
||||
#define GHOSTTY_DA_FEATURE_USER_DEFINED_KEYS 8
|
||||
#define GHOSTTY_DA_FEATURE_NATIONAL_REPLACEMENT 9
|
||||
#define GHOSTTY_DA_FEATURE_TECHNICAL_CHARACTERS 15
|
||||
#define GHOSTTY_DA_FEATURE_LOCATOR 16
|
||||
#define GHOSTTY_DA_FEATURE_TERMINAL_STATE 17
|
||||
#define GHOSTTY_DA_FEATURE_WINDOWING 18
|
||||
#define GHOSTTY_DA_FEATURE_HORIZONTAL_SCROLLING 21
|
||||
#define GHOSTTY_DA_FEATURE_ANSI_COLOR 22
|
||||
#define GHOSTTY_DA_FEATURE_RECTANGULAR_EDITING 28
|
||||
#define GHOSTTY_DA_FEATURE_ANSI_TEXT_LOCATOR 29
|
||||
#define GHOSTTY_DA_FEATURE_CLIPBOARD 52
|
||||
|
||||
/* DA2 device type identifiers (Pp parameter). */
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT100 0
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT220 1
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT240 2
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT330 18
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT340 19
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT320 24
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT382 32
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT420 41
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT510 61
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT520 64
|
||||
#define GHOSTTY_DA_DEVICE_TYPE_VT525 65
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Color scheme reported in response to a CSI ? 996 n query.
|
||||
*
|
||||
* @ingroup terminal
|
||||
*/
|
||||
typedef enum {
|
||||
GHOSTTY_COLOR_SCHEME_LIGHT = 0,
|
||||
GHOSTTY_COLOR_SCHEME_DARK = 1,
|
||||
} GhosttyColorScheme;
|
||||
|
||||
/**
|
||||
* Primary device attributes (DA1) response data.
|
||||
*
|
||||
* Returned as part of GhosttyDeviceAttributes in response to a CSI c query.
|
||||
* The conformance_level is the Pp parameter and features contains the Ps
|
||||
* feature codes.
|
||||
*
|
||||
* @ingroup terminal
|
||||
*/
|
||||
typedef struct {
|
||||
/** Conformance level (Pp parameter). E.g. 62 for VT220. */
|
||||
uint16_t conformance_level;
|
||||
|
||||
/** DA1 feature codes. Only the first num_features entries are valid. */
|
||||
uint16_t features[64];
|
||||
|
||||
/** Number of valid entries in the features array. */
|
||||
size_t num_features;
|
||||
} GhosttyDeviceAttributesPrimary;
|
||||
|
||||
/**
|
||||
* Secondary device attributes (DA2) response data.
|
||||
*
|
||||
* Returned as part of GhosttyDeviceAttributes in response to a CSI > c query.
|
||||
* Response format: CSI > Pp ; Pv ; Pc c
|
||||
*
|
||||
* @ingroup terminal
|
||||
*/
|
||||
typedef struct {
|
||||
/** Terminal type identifier (Pp). E.g. 1 for VT220. */
|
||||
uint16_t device_type;
|
||||
|
||||
/** Firmware/patch version number (Pv). */
|
||||
uint16_t firmware_version;
|
||||
|
||||
/** ROM cartridge registration number (Pc). Always 0 for emulators. */
|
||||
uint16_t rom_cartridge;
|
||||
} GhosttyDeviceAttributesSecondary;
|
||||
|
||||
/**
|
||||
* Tertiary device attributes (DA3) response data.
|
||||
*
|
||||
* Returned as part of GhosttyDeviceAttributes in response to a CSI = c query.
|
||||
* Response format: DCS ! | D...D ST (DECRPTUI).
|
||||
*
|
||||
* @ingroup terminal
|
||||
*/
|
||||
typedef struct {
|
||||
/** Unit ID encoded as 8 uppercase hex digits in the response. */
|
||||
uint32_t unit_id;
|
||||
} GhosttyDeviceAttributesTertiary;
|
||||
|
||||
/**
|
||||
* Device attributes response data for all three DA levels.
|
||||
*
|
||||
* Filled by the device_attributes callback in response to CSI c,
|
||||
* CSI > c, or CSI = c queries. The terminal uses whichever sub-struct
|
||||
* matches the request type.
|
||||
*
|
||||
* @ingroup terminal
|
||||
*/
|
||||
typedef struct {
|
||||
GhosttyDeviceAttributesPrimary primary;
|
||||
GhosttyDeviceAttributesSecondary secondary;
|
||||
GhosttyDeviceAttributesTertiary tertiary;
|
||||
} GhosttyDeviceAttributes;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GHOSTTY_VT_DEVICE_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue