mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-04 17:06:33 +00:00
Merge pull request #577 from mitchellh/patrickf/lint-markdown
Introduce Prettier and lint entire repo
This commit is contained in:
14
.github/workflows/clean-artifacts.yml
vendored
14
.github/workflows/clean-artifacts.yml
vendored
@@ -2,16 +2,16 @@ name: Clean Artifacts
|
|||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
# Once a day
|
# Once a day
|
||||||
- cron: '0 0 * * *'
|
- cron: "0 0 * * *"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
jobs:
|
jobs:
|
||||||
remove-old-artifacts:
|
remove-old-artifacts:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- name: Remove old artifacts
|
- name: Remove old artifacts
|
||||||
uses: c-hive/gha-remove-artifacts@v1
|
uses: c-hive/gha-remove-artifacts@v1
|
||||||
with:
|
with:
|
||||||
age: '1 week'
|
age: "1 week"
|
||||||
skip-tags: true
|
skip-tags: true
|
||||||
skip-recent: 5
|
skip-recent: 5
|
||||||
|
232
.github/workflows/release-tip.yml
vendored
232
.github/workflows/release-tip.yml
vendored
@@ -13,13 +13,13 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [build-macos]
|
needs: [build-macos]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Tip Tag
|
- name: Tip Tag
|
||||||
run: |
|
run: |
|
||||||
git config user.name "GitHub Actions Bot"
|
git config user.name "GitHub Actions Bot"
|
||||||
git config user.email "<>"
|
git config user.email "<>"
|
||||||
git tag -fa tip -m "Latest Continuous Release" ${GITHUB_SHA}
|
git tag -fa tip -m "Latest Continuous Release" ${GITHUB_SHA}
|
||||||
git push --force origin tip
|
git push --force origin tip
|
||||||
|
|
||||||
build-macos:
|
build-macos:
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
|
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
|
||||||
@@ -29,130 +29,130 @@ jobs:
|
|||||||
# Needed for macos SDK
|
# Needed for macos SDK
|
||||||
AGREE: "true"
|
AGREE: "true"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||||
- uses: cachix/install-nix-action@v23
|
- uses: cachix/install-nix-action@v23
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
|
|
||||||
# Setup our S3 client
|
# Setup our S3 client
|
||||||
- name: Setup s3cmd
|
- name: Setup s3cmd
|
||||||
uses: s3-actions/s3cmd@v1.5.0
|
uses: s3-actions/s3cmd@v1.5.0
|
||||||
with:
|
with:
|
||||||
provider: cloudflare
|
provider: cloudflare
|
||||||
account_id: ${{ secrets.CF_R2_TIP_ACCOUNT_ID }}
|
account_id: ${{ secrets.CF_R2_TIP_ACCOUNT_ID }}
|
||||||
access_key: ${{ secrets.CF_R2_TIP_AWS_KEY }}
|
access_key: ${{ secrets.CF_R2_TIP_AWS_KEY }}
|
||||||
secreT_key: ${{ secrets.CF_R2_TIP_SECRET_KEY }}
|
secreT_key: ${{ secrets.CF_R2_TIP_SECRET_KEY }}
|
||||||
|
|
||||||
# Load Build Number
|
# Load Build Number
|
||||||
- name: Build Number
|
- name: Build Number
|
||||||
run: |
|
run: |
|
||||||
echo "GHOSTTY_BUILD=$(git rev-list --count head)" >> $GITHUB_ENV
|
echo "GHOSTTY_BUILD=$(git rev-list --count head)" >> $GITHUB_ENV
|
||||||
|
|
||||||
# GhosttyKit is the framework that is built from Zig for our native
|
# GhosttyKit is the framework that is built from Zig for our native
|
||||||
# Mac app to access. Build this in release mode.
|
# Mac app to access. Build this in release mode.
|
||||||
- name: Build GhosttyKit
|
- name: Build GhosttyKit
|
||||||
run: nix develop -c zig build -Dstatic=true -Doptimize=ReleaseFast
|
run: nix develop -c zig build -Dstatic=true -Doptimize=ReleaseFast
|
||||||
|
|
||||||
# The native app is built with native XCode tooling. This also does
|
# The native app is built with native XCode tooling. This also does
|
||||||
# codesigning. IMPORTANT: this must NOT run in a Nix environment.
|
# codesigning. IMPORTANT: this must NOT run in a Nix environment.
|
||||||
# Nix breaks xcodebuild so this has to be run outside.
|
# Nix breaks xcodebuild so this has to be run outside.
|
||||||
- name: Build Ghostty.app
|
- name: Build Ghostty.app
|
||||||
run: cd macos && xcodebuild -configuration Release
|
run: cd macos && xcodebuild -configuration Release
|
||||||
|
|
||||||
# We inject the "build number" as simply the number of commits since HEAD.
|
# We inject the "build number" as simply the number of commits since HEAD.
|
||||||
# This will be a monotonically always increasing build number that we use.
|
# This will be a monotonically always increasing build number that we use.
|
||||||
- name: Inject Build Number
|
- name: Inject Build Number
|
||||||
run: |
|
run: |
|
||||||
echo "Setting build to $GHOSTTY_BUILD"
|
echo "Setting build to $GHOSTTY_BUILD"
|
||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $GHOSTTY_BUILD" "macos/build/Release/Ghostty.app/Contents/Info.plist"
|
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $GHOSTTY_BUILD" "macos/build/Release/Ghostty.app/Contents/Info.plist"
|
||||||
|
|
||||||
- name: Zip Unsigned App
|
- name: Zip Unsigned App
|
||||||
run: nix develop -c sh -c 'cd macos/build/Release && zip -9 -r --symlinks ../../../ghostty-macos-universal-unsigned.zip Ghostty.app'
|
run: nix develop -c sh -c 'cd macos/build/Release && zip -9 -r --symlinks ../../../ghostty-macos-universal-unsigned.zip Ghostty.app'
|
||||||
|
|
||||||
# Update Release
|
# Update Release
|
||||||
- name: Release Unsigned
|
- name: Release Unsigned
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
name: "Ghostty Tip (\"Nightly\")"
|
name: 'Ghostty Tip ("Nightly")'
|
||||||
prerelease: true
|
prerelease: true
|
||||||
tag_name: tip
|
tag_name: tip
|
||||||
target_commitish: ${{ github.sha }}
|
target_commitish: ${{ github.sha }}
|
||||||
files: ghostty-macos-universal-unsigned.zip
|
files: ghostty-macos-universal-unsigned.zip
|
||||||
token: ${{ secrets.GH_RELEASE_TOKEN }}
|
token: ${{ secrets.GH_RELEASE_TOKEN }}
|
||||||
|
|
||||||
- name: Codesign app bundle
|
- name: Codesign app bundle
|
||||||
env:
|
env:
|
||||||
MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }}
|
MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }}
|
||||||
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
|
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
|
||||||
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
|
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
|
||||||
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
|
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
|
||||||
run: |
|
run: |
|
||||||
# Turn our base64-encoded certificate back to a regular .p12 file
|
# Turn our base64-encoded certificate back to a regular .p12 file
|
||||||
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
|
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
|
||||||
|
|
||||||
# We need to create a new keychain, otherwise using the certificate will prompt
|
# We need to create a new keychain, otherwise using the certificate will prompt
|
||||||
# with a UI dialog asking for the certificate password, which we can't
|
# with a UI dialog asking for the certificate password, which we can't
|
||||||
# use in a headless CI environment
|
# use in a headless CI environment
|
||||||
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||||
security default-keychain -s build.keychain
|
security default-keychain -s build.keychain
|
||||||
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||||
security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
|
security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
|
||||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||||
|
|
||||||
# We finally codesign our app bundle, specifying the Hardened runtime option
|
# We finally codesign our app bundle, specifying the Hardened runtime option
|
||||||
/usr/bin/codesign --force -s "$MACOS_CERTIFICATE_NAME" --options runtime macos/build/Release/Ghostty.app -v
|
/usr/bin/codesign --force -s "$MACOS_CERTIFICATE_NAME" --options runtime macos/build/Release/Ghostty.app -v
|
||||||
|
|
||||||
- name: "Notarize app bundle"
|
- name: "Notarize app bundle"
|
||||||
env:
|
env:
|
||||||
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
||||||
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
||||||
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
|
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
|
||||||
run: |
|
run: |
|
||||||
# Store the notarization credentials so that we can prevent a UI password dialog
|
# Store the notarization credentials so that we can prevent a UI password dialog
|
||||||
# from blocking the CI
|
# from blocking the CI
|
||||||
echo "Create keychain profile"
|
echo "Create keychain profile"
|
||||||
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
|
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
|
||||||
|
|
||||||
# We can't notarize an app bundle directly, but we need to compress it as an archive.
|
# We can't notarize an app bundle directly, but we need to compress it as an archive.
|
||||||
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
|
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
|
||||||
# notarization service
|
# notarization service
|
||||||
echo "Creating temp notarization archive"
|
echo "Creating temp notarization archive"
|
||||||
ditto -c -k --keepParent "macos/build/Release/Ghostty.app" "notarization.zip"
|
ditto -c -k --keepParent "macos/build/Release/Ghostty.app" "notarization.zip"
|
||||||
|
|
||||||
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
|
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
|
||||||
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
|
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
|
||||||
# characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if
|
# characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if
|
||||||
# you're curious
|
# you're curious
|
||||||
echo "Notarize app"
|
echo "Notarize app"
|
||||||
xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait
|
xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait
|
||||||
|
|
||||||
# Finally, we need to "attach the staple" to our executable, which will allow our app to be
|
# Finally, we need to "attach the staple" to our executable, which will allow our app to be
|
||||||
# validated by macOS even when an internet connection is not available.
|
# validated by macOS even when an internet connection is not available.
|
||||||
echo "Attach staple"
|
echo "Attach staple"
|
||||||
xcrun stapler staple "macos/build/Release/Ghostty.app"
|
xcrun stapler staple "macos/build/Release/Ghostty.app"
|
||||||
|
|
||||||
# Zip up the app
|
# Zip up the app
|
||||||
- name: Zip App
|
- name: Zip App
|
||||||
run: cd macos/build/Release && zip -9 -r --symlinks ../../../ghostty-macos-universal.zip Ghostty.app
|
run: cd macos/build/Release && zip -9 -r --symlinks ../../../ghostty-macos-universal.zip Ghostty.app
|
||||||
|
|
||||||
# Update Release
|
# Update Release
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
name: "Ghostty Tip (\"Nightly\")"
|
name: 'Ghostty Tip ("Nightly")'
|
||||||
prerelease: true
|
prerelease: true
|
||||||
tag_name: tip
|
tag_name: tip
|
||||||
target_commitish: ${{ github.sha }}
|
target_commitish: ${{ github.sha }}
|
||||||
files: ghostty-macos-universal.zip
|
files: ghostty-macos-universal.zip
|
||||||
token: ${{ secrets.GH_RELEASE_TOKEN }}
|
token: ${{ secrets.GH_RELEASE_TOKEN }}
|
||||||
|
|
||||||
# Update Blob Storage
|
# Update Blob Storage
|
||||||
- name: Upload to Blob Storage
|
- name: Upload to Blob Storage
|
||||||
run: |
|
run: |
|
||||||
s3cmd put ghostty-macos-universal.zip s3://ghostty-tip/${GHOSTTY_BUILD}/ghostty-macos-universal.zip
|
s3cmd put ghostty-macos-universal.zip s3://ghostty-tip/${GHOSTTY_BUILD}/ghostty-macos-universal.zip
|
||||||
|
121
.github/workflows/test.yml
vendored
121
.github/workflows/test.yml
vendored
@@ -8,37 +8,36 @@ jobs:
|
|||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
|
|
||||||
target: [
|
target: [
|
||||||
aarch64-macos,
|
aarch64-macos,
|
||||||
x86_64-macos,
|
x86_64-macos,
|
||||||
|
|
||||||
aarch64-linux-gnu,
|
aarch64-linux-gnu,
|
||||||
x86_64-linux-gnu,
|
x86_64-linux-gnu,
|
||||||
|
# No windows support currently.
|
||||||
# No windows support currently.
|
# i386-windows,
|
||||||
# i386-windows,
|
# x86_64-windows-gnu,
|
||||||
# x86_64-windows-gnu,
|
]
|
||||||
]
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
needs: test
|
needs: test
|
||||||
env:
|
env:
|
||||||
# Needed for macos SDK
|
# Needed for macos SDK
|
||||||
AGREE: "true"
|
AGREE: "true"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||||
- uses: cachix/install-nix-action@v23
|
- uses: cachix/install-nix-action@v23
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
|
|
||||||
# Cross-compile the binary. We always use static building for this
|
# Cross-compile the binary. We always use static building for this
|
||||||
# because its the only way to access the headers.
|
# because its the only way to access the headers.
|
||||||
- name: Test Build
|
- name: Test Build
|
||||||
run: nix develop -c zig build -Dstatic=true -Dapp-runtime=glfw -Dtarget=${{ matrix.target }}
|
run: nix develop -c zig build -Dstatic=true -Dapp-runtime=glfw -Dtarget=${{ matrix.target }}
|
||||||
|
|
||||||
build-macos:
|
build-macos:
|
||||||
runs-on: macos-12
|
runs-on: macos-12
|
||||||
@@ -47,27 +46,27 @@ jobs:
|
|||||||
# Needed for macos SDK
|
# Needed for macos SDK
|
||||||
AGREE: "true"
|
AGREE: "true"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||||
- uses: cachix/install-nix-action@v23
|
- uses: cachix/install-nix-action@v23
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
|
|
||||||
# GhosttyKit is the framework that is built from Zig for our native
|
# GhosttyKit is the framework that is built from Zig for our native
|
||||||
# Mac app to access.
|
# Mac app to access.
|
||||||
- name: Build GhosttyKit
|
- name: Build GhosttyKit
|
||||||
run: nix develop -c zig build -Dstatic=true
|
run: nix develop -c zig build -Dstatic=true
|
||||||
|
|
||||||
# The native app is built with native XCode tooling. This also does
|
# The native app is built with native XCode tooling. This also does
|
||||||
# codesigning. IMPORTANT: this must NOT run in a Nix environment.
|
# codesigning. IMPORTANT: this must NOT run in a Nix environment.
|
||||||
# Nix breaks xcodebuild so this has to be run outside.
|
# Nix breaks xcodebuild so this has to be run outside.
|
||||||
- name: Build Ghostty.app
|
- name: Build Ghostty.app
|
||||||
run: cd macos && xcodebuild
|
run: cd macos && xcodebuild
|
||||||
|
|
||||||
test:
|
test:
|
||||||
strategy:
|
strategy:
|
||||||
@@ -75,25 +74,33 @@ jobs:
|
|||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||||
- uses: cachix/install-nix-action@v23
|
- uses: cachix/install-nix-action@v23
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
|
|
||||||
- name: test
|
- name: test
|
||||||
run: nix develop -c zig build -Dapp-runtime=none test
|
run: nix develop -c zig build -Dapp-runtime=none test
|
||||||
|
|
||||||
- name: Test GTK Build
|
- name: Test GTK Build
|
||||||
run: nix develop -c zig build -Dapp-runtime=gtk
|
run: nix develop -c zig build -Dapp-runtime=gtk
|
||||||
|
|
||||||
- name: Test GLFW Build
|
- name: Test GLFW Build
|
||||||
run: nix develop -c zig build -Dapp-runtime=glfw
|
run: nix develop -c zig build -Dapp-runtime=glfw
|
||||||
|
|
||||||
- name: Test Dynamic Build
|
- name: Test Dynamic Build
|
||||||
run: nix develop -c zig build -Dstatic=false
|
run: nix develop -c zig build -Dstatic=false
|
||||||
|
|
||||||
|
prettier:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4 # Check out repo so we can lint it
|
||||||
|
- uses: actionsx/prettier@v3
|
||||||
|
with:
|
||||||
|
args: --check .
|
||||||
|
7
.prettierignore
Normal file
7
.prettierignore
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Docs: https://prettier.io/docs/en/ignore.html
|
||||||
|
vendor/
|
||||||
|
# macos is managed by XCode GUI
|
||||||
|
macos/
|
||||||
|
**/*.html
|
||||||
|
flake.lock
|
||||||
|
|
67
README.md
67
README.md
@@ -44,11 +44,11 @@ things, but I've been using it full time since April 2022.
|
|||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
| Platform / Package | Links | Notes |
|
| Platform / Package | Links | Notes |
|
||||||
| ----------| ----- | ----- |
|
| ------------------ | ------------------------------------------------------------------------ | -------------------------- |
|
||||||
| macOS | [Tip ("Nightly")](https://github.com/mitchellh/ghostty/releases/tag/tip) | MacOS 12+ Universal Binary |
|
| macOS | [Tip ("Nightly")](https://github.com/mitchellh/ghostty/releases/tag/tip) | MacOS 12+ Universal Binary |
|
||||||
| Linux | [Build from Source](#developing-ghostty) | |
|
| Linux | [Build from Source](#developing-ghostty) | |
|
||||||
| Windows | n/a | Not supported yet |
|
| Windows | n/a | Not supported yet |
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
@@ -134,12 +134,12 @@ to support many of the features that
|
|||||||
|
|
||||||
The currently support shell integration features in Ghostty:
|
The currently support shell integration features in Ghostty:
|
||||||
|
|
||||||
* We do not confirm close for windows where the cursor is at a prompt.
|
- We do not confirm close for windows where the cursor is at a prompt.
|
||||||
* New terminals start in the working directory of the previously focused terminal.
|
- New terminals start in the working directory of the previously focused terminal.
|
||||||
* Complex prompts resize correctly by allowing the shell to redraw the prompt line.
|
- Complex prompts resize correctly by allowing the shell to redraw the prompt line.
|
||||||
* The cursor at the prompt is turned into a bar.
|
- The cursor at the prompt is turned into a bar.
|
||||||
* The `jump_to_prompt` keybinding can be used to scroll the terminal window
|
- The `jump_to_prompt` keybinding can be used to scroll the terminal window
|
||||||
forward and back through prompts.
|
forward and back through prompts.
|
||||||
|
|
||||||
#### Shell Integration Installation and Verification
|
#### Shell Integration Installation and Verification
|
||||||
|
|
||||||
@@ -208,15 +208,15 @@ goes for any other shell.
|
|||||||
|
|
||||||
The high-level ambitious plan for the project, in order:
|
The high-level ambitious plan for the project, in order:
|
||||||
|
|
||||||
| # | Step | Status |
|
| # | Step | Status |
|
||||||
|:---:|------|:------:|
|
| :-: | ----------------------------------------------------------- | :----: |
|
||||||
| 1 | [Standards-compliant terminal emulation](docs/sequences.md) | ⚠️ |
|
| 1 | [Standards-compliant terminal emulation](docs/sequences.md) | ⚠️ |
|
||||||
| 2 | Competitive performance | ✅ |
|
| 2 | Competitive performance | ✅ |
|
||||||
| 3 | Basic customizability -- fonts, bg colors, etc. | ✅ |
|
| 3 | Basic customizability -- fonts, bg colors, etc. | ✅ |
|
||||||
| 4 | Richer windowing features -- multi-window, tabbing, panes | ✅ |
|
| 4 | Richer windowing features -- multi-window, tabbing, panes | ✅ |
|
||||||
| 5 | Native Platform Experiences (i.e. Mac Preference Panel) | ⚠️ |
|
| 5 | Native Platform Experiences (i.e. Mac Preference Panel) | ⚠️ |
|
||||||
| 6 | Windows Terminals (including PowerShell, Cmd, WSL) | ❌ |
|
| 6 | Windows Terminals (including PowerShell, Cmd, WSL) | ❌ |
|
||||||
| N | Fancy features (to be expanded upon later) | ❌ |
|
| N | Fancy features (to be expanded upon later) | ❌ |
|
||||||
|
|
||||||
Additional details for each step in the big roadmap below:
|
Additional details for each step in the big roadmap below:
|
||||||
|
|
||||||
@@ -261,10 +261,10 @@ Ghostty is a cross-platform terminal emulator but we don't aim for a
|
|||||||
least-common-denominator experience. There is a large, shared core written
|
least-common-denominator experience. There is a large, shared core written
|
||||||
in Zig but we do a lot of platform-native things:
|
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
|
- 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.
|
would expect such as real windowing, menu bars, a settings GUI, etc.
|
||||||
* macOS uses a true Metal renderer with CoreText for font discovery.
|
- macOS uses a true Metal renderer with CoreText for font discovery.
|
||||||
* The Linux app is built with GTK.
|
- The Linux app is built with GTK.
|
||||||
|
|
||||||
There are more improvements to be made. The macOS settings window is still
|
There are more improvements to be made. The macOS settings window is still
|
||||||
a work-in-progress. Similar improvements will follow with Linux.
|
a work-in-progress. Similar improvements will follow with Linux.
|
||||||
@@ -310,11 +310,11 @@ tasks.
|
|||||||
|
|
||||||
Other useful commands:
|
Other useful commands:
|
||||||
|
|
||||||
* `zig build test` for running unit tests.
|
- `zig build test` for running unit tests.
|
||||||
* `zig build run -Dconformance=<name>` runs a conformance test case from
|
- `zig build run -Dconformance=<name>` runs a conformance test case from
|
||||||
the `conformance` directory. The `name` is the name of the file. This runs
|
the `conformance` directory. The `name` is the name of the file. This runs
|
||||||
in the current running terminal emulator so if you want to check the
|
in the current running terminal emulator so if you want to check the
|
||||||
behavior of this project, you must run this command in ghostty.
|
behavior of this project, you must run this command in ghostty.
|
||||||
|
|
||||||
### Compiling a Release Build
|
### Compiling a Release Build
|
||||||
|
|
||||||
@@ -392,3 +392,14 @@ as `Console.app`. The easiest way I've found to view these is to just use the CL
|
|||||||
$ sudo log stream --level debug --predicate 'subsystem=="com.mitchellh.ghostty"'
|
$ sudo log stream --level debug --predicate 'subsystem=="com.mitchellh.ghostty"'
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Linting
|
||||||
|
|
||||||
|
Ghostty's docs and resources (not including Zig code) are linted using [Prettier](https://prettier.io) with out-of-the-box settings. A Prettier CI check will fail builds with improper formatting. Therefore, if you are modifying anything Prettier will lint, you may want to install it locally and run this from the repo root before you commit:
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install -g prettier
|
||||||
|
prettier --write .
|
||||||
|
```
|
||||||
|
|
||||||
|
Or simply install one of the many Prettier extensions out there for your editor of choice.
|
||||||
|
@@ -42,14 +42,14 @@ or even pair (time permitting) if you're interested.
|
|||||||
|
|
||||||
This is the priority of bugs:
|
This is the priority of bugs:
|
||||||
|
|
||||||
1. Crashes. 💥 These are just unacceptable and I'll drop everything to
|
1. Crashes. 💥 These are just unacceptable and I'll drop everything to
|
||||||
fix a crash.
|
fix a crash.
|
||||||
|
|
||||||
2. Escape sequence logic or rendering issues. These are almost as bad as
|
2. Escape sequence logic or rendering issues. These are almost as bad as
|
||||||
crashes because they usually make your workflow unusable. This includes
|
crashes because they usually make your workflow unusable. This includes
|
||||||
unsupported escape sequences that impact your workflow.
|
unsupported escape sequences that impact your workflow.
|
||||||
|
|
||||||
3. Anything else...
|
3. Anything else...
|
||||||
|
|
||||||
## Let's Talk!
|
## Let's Talk!
|
||||||
|
|
||||||
|
18
TODO.md
18
TODO.md
@@ -1,15 +1,15 @@
|
|||||||
Performance:
|
Performance:
|
||||||
|
|
||||||
* for scrollback, investigate using segmented list for sufficiently large
|
- for scrollback, investigate using segmented list for sufficiently large
|
||||||
scrollback scenarios.
|
scrollback scenarios.
|
||||||
* Loading fonts on startups should probably happen in multiple threads
|
- Loading fonts on startups should probably happen in multiple threads
|
||||||
* `deleteLines` is very, very slow which makes scroll region benchmarks terrible
|
- `deleteLines` is very, very slow which makes scroll region benchmarks terrible
|
||||||
|
|
||||||
Correctness:
|
Correctness:
|
||||||
|
|
||||||
* test wrap against wraptest: https://github.com/mattiase/wraptest
|
- test wrap against wraptest: https://github.com/mattiase/wraptest
|
||||||
- automate this in some way
|
- automate this in some way
|
||||||
* Charsets: UTF-8 vs. ASCII mode
|
- Charsets: UTF-8 vs. ASCII mode
|
||||||
- we only support UTF-8 input right now
|
- we only support UTF-8 input right now
|
||||||
- need fallback glyphs if they're not supported
|
- need fallback glyphs if they're not supported
|
||||||
- can effect a crash using `vttest` menu `3 10` since it tries to parse
|
- can effect a crash using `vttest` menu `3 10` since it tries to parse
|
||||||
@@ -17,13 +17,13 @@ Correctness:
|
|||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
|
|
||||||
* scrollback: configurable
|
- scrollback: configurable
|
||||||
|
|
||||||
Mac:
|
Mac:
|
||||||
|
|
||||||
* Preferences window
|
- Preferences window
|
||||||
|
|
||||||
Major Features:
|
Major Features:
|
||||||
|
|
||||||
* Bell
|
- Bell
|
||||||
* Sixels: https://saitoha.github.io/libsixel/
|
- Sixels: https://saitoha.github.io/libsixel/
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
# we want to keep _trying_ but its something with known issues.
|
# we want to keep _trying_ but its something with known issues.
|
||||||
app-id: com.mitchellh.ghostty
|
app-id: com.mitchellh.ghostty
|
||||||
runtime: org.gnome.Platform
|
runtime: org.gnome.Platform
|
||||||
runtime-version: '43'
|
runtime-version: "43"
|
||||||
sdk: org.gnome.Sdk
|
sdk: org.gnome.Sdk
|
||||||
default-branch: tip
|
default-branch: tip
|
||||||
command: ghostty
|
command: ghostty
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
# Control and Escape Sequences
|
# Control and Escape Sequences
|
||||||
|
|
||||||
⚠️ **This is super out of date. Ghostty's support is much better
|
⚠️ **This is super out of date. Ghostty's support is much better
|
||||||
than this document seems. TODO to update this.** ⚠️
|
than this document seems. TODO to update this.** ⚠️
|
||||||
|
|
||||||
|
|
||||||
This is the list of control and escape sequences known in the ecosystem
|
This is the list of control and escape sequences known in the ecosystem
|
||||||
of terminal emulators and their implementation status in ghostty. Note that
|
of terminal emulators and their implementation status in ghostty. Note that
|
||||||
some control sequences may never be implemented in ghostty. In these scenarios,
|
some control sequences may never be implemented in ghostty. In these scenarios,
|
||||||
@@ -11,35 +10,35 @@ it is noted why.
|
|||||||
|
|
||||||
Status meanings:
|
Status meanings:
|
||||||
|
|
||||||
* ✅ - Implementation is complete and considered 100% accurate.
|
- ✅ - Implementation is complete and considered 100% accurate.
|
||||||
* ⚠️ - Implementation works, but may be missing some functionality. The
|
- ⚠️ - Implementation works, but may be missing some functionality. The
|
||||||
details of how well it works or doesn't are in the linked page. In many
|
details of how well it works or doesn't are in the linked page. In many
|
||||||
cases, the missing functionality is very specific or esoteric. Regardless,
|
cases, the missing functionality is very specific or esoteric. Regardless,
|
||||||
we don't consider a sequence a green checkmark until all known feature
|
we don't consider a sequence a green checkmark until all known feature
|
||||||
interactions are complete.
|
interactions are complete.
|
||||||
* ❌ - Implementation is effectively non-functional, but ghostty continues
|
- ❌ - Implementation is effectively non-functional, but ghostty continues
|
||||||
in the face of it (probably in some broken state).
|
in the face of it (probably in some broken state).
|
||||||
* 💥 - Ghostty crashes if this control sequence is sent.
|
- 💥 - Ghostty crashes if this control sequence is sent.
|
||||||
|
|
||||||
| ID | ASCII | Name | Status |
|
| ID | ASCII | Name | Status |
|
||||||
|:---:|:-----:|:-----|:------:|
|
| :---: | :-----: | :----------------------------------------- | :----: |
|
||||||
| `ENQ` | `0x05` | [Enquiry](sequences/enq.md) | ✅ |
|
| `ENQ` | `0x05` | [Enquiry](sequences/enq.md) | ✅ |
|
||||||
| `BEL` | `0x07` | [Bell](sequences/bel.md) | ❌ |
|
| `BEL` | `0x07` | [Bell](sequences/bel.md) | ❌ |
|
||||||
| `BS` | `0x08` | [Backspace](sequences/bs.md) | ⚠️ |
|
| `BS` | `0x08` | [Backspace](sequences/bs.md) | ⚠️ |
|
||||||
| `TAB` | `0x09` | [Tab](sequences/tab.md) | ⚠️ |
|
| `TAB` | `0x09` | [Tab](sequences/tab.md) | ⚠️ |
|
||||||
| `LF` | `0x0A` | [Linefeed](sequences/lf.md) | ⚠️ |
|
| `LF` | `0x0A` | [Linefeed](sequences/lf.md) | ⚠️ |
|
||||||
| `VT` | `0x0B` | [Vertical Tab](sequences/vt.md) | ✅ |
|
| `VT` | `0x0B` | [Vertical Tab](sequences/vt.md) | ✅ |
|
||||||
| `FF` | `0x0C` | [Form Feed](sequences/ff.md) | ✅ |
|
| `FF` | `0x0C` | [Form Feed](sequences/ff.md) | ✅ |
|
||||||
| `CR` | `0x0D` | [Carriage Return](sequences/cr.md) | ⚠️ |
|
| `CR` | `0x0D` | [Carriage Return](sequences/cr.md) | ⚠️ |
|
||||||
| `SO` | `0x0E` | [Shift Out](#) | ❌ |
|
| `SO` | `0x0E` | [Shift Out](#) | ❌ |
|
||||||
| `SI` | `0x0F` | [Shift In](#) | ❌ |
|
| `SI` | `0x0F` | [Shift In](#) | ❌ |
|
||||||
| `CAN` | `0x18` | [Cancel Parsing](sequences/can.md) | ✅ |
|
| `CAN` | `0x18` | [Cancel Parsing](sequences/can.md) | ✅ |
|
||||||
| `SUB` | `0x1A` | [Cancel Parsing (Alias)](sequences/can.md) | ✅ |
|
| `SUB` | `0x1A` | [Cancel Parsing (Alias)](sequences/can.md) | ✅ |
|
||||||
| `IND` | `ESC D` | [Index](sequences/ind.md) | ✅ |
|
| `IND` | `ESC D` | [Index](sequences/ind.md) | ✅ |
|
||||||
| `NEL` | `ESC E` | [Next Line](sequences/nel.md) | ✅ |
|
| `NEL` | `ESC E` | [Next Line](sequences/nel.md) | ✅ |
|
||||||
| `HTS` | `ESC H` | [Horizontal Tab Set](sequences/hts.md) | ✅ |
|
| `HTS` | `ESC H` | [Horizontal Tab Set](sequences/hts.md) | ✅ |
|
||||||
| `RI` | `ESC M` | [Reverse Index](sequences/ri.md) | ⚠️ |
|
| `RI` | `ESC M` | [Reverse Index](sequences/ri.md) | ⚠️ |
|
||||||
| `SS2` | `ESC N` | [Single Shift 2](#) | ❌ |
|
| `SS2` | `ESC N` | [Single Shift 2](#) | ❌ |
|
||||||
| `SS3` | `ESC O` | [Single Shift 3](#) | ❌ |
|
| `SS3` | `ESC O` | [Single Shift 3](#) | ❌ |
|
||||||
| `SPA` | `ESC V` | [Start Protected Area](#) | ❌ |
|
| `SPA` | `ESC V` | [Start Protected Area](#) | ❌ |
|
||||||
| `EPA` | `ESC W` | [End Protected Area](#) | ❌ |
|
| `EPA` | `ESC W` | [End Protected Area](#) | ❌ |
|
||||||
|
@@ -1,24 +1,24 @@
|
|||||||
# Bell
|
# Bell
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ------ |
|
||||||
| Text | |
|
| Text | |
|
||||||
| Hex | `0x07` |
|
| Hex | `0x07` |
|
||||||
|
|
||||||
Rings a "bell" to alert the operator to some condition.
|
Rings a "bell" to alert the operator to some condition.
|
||||||
|
|
||||||
## Implementation Details
|
## Implementation Details
|
||||||
|
|
||||||
* ghostty logs "BELL"
|
- ghostty logs "BELL"
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* Add a configurable visual bell -- common in most terminal emulators --
|
- Add a configurable visual bell -- common in most terminal emulators --
|
||||||
to flash the border.
|
to flash the border.
|
||||||
* Mark the window as requesting attention, most operating systems support
|
- Mark the window as requesting attention, most operating systems support
|
||||||
this. For example, Windows windows will flash in the toolbar.
|
this. For example, Windows windows will flash in the toolbar.
|
||||||
* Support an audible bell.
|
- Support an audible bell.
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
* https://vt100.net/docs/vt100-ug/chapter3.html
|
- https://vt100.net/docs/vt100-ug/chapter3.html
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
# Backspace
|
# Backspace
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ------ |
|
||||||
| Text | |
|
| Text | |
|
||||||
| Hex | `0x08` |
|
| Hex | `0x08` |
|
||||||
|
|
||||||
Move the cursor left one cell.
|
Move the cursor left one cell.
|
||||||
|
|
||||||
@@ -11,9 +11,9 @@ TODO: Details about how this interacts with soft wrapping.
|
|||||||
|
|
||||||
## Implementation Details
|
## Implementation Details
|
||||||
|
|
||||||
* ghostty implements this naively as `cursor.x -|= 1` (`-|=` being a
|
- ghostty implements this naively as `cursor.x -|= 1` (`-|=` being a
|
||||||
saturating subtraction).
|
saturating subtraction).
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* Soft wrap integration
|
- Soft wrap integration
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
# Cancel Parsing
|
# Cancel Parsing
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ---------------- |
|
||||||
| Text | |
|
| Text | |
|
||||||
| Hex | `0x18` or `0x1A` |
|
| Hex | `0x18` or `0x1A` |
|
||||||
|
|
||||||
Cancels sequence parsing. Any partially completed sequence such as `ESC`
|
Cancels sequence parsing. Any partially completed sequence such as `ESC`
|
||||||
can send `0x18` and revert back to an unparsed state. The sequence characters
|
can send `0x18` and revert back to an unparsed state. The sequence characters
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
# Carriage Return
|
# Carriage Return
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ------ |
|
||||||
| Text | |
|
| Text | |
|
||||||
| Hex | `0x0D` |
|
| Hex | `0x0D` |
|
||||||
|
|
||||||
Moves the cursor to the left-most column and resets any pending wrap flags.
|
Moves the cursor to the left-most column and resets any pending wrap flags.
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* Integration with left/right scrolling margins
|
- Integration with left/right scrolling margins
|
||||||
* Integration with origin mode
|
- Integration with origin mode
|
||||||
|
@@ -1,21 +1,21 @@
|
|||||||
# Enquiry (Answerback)
|
# Enquiry (Answerback)
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ------ |
|
||||||
| Text | |
|
| Text | |
|
||||||
| Hex | `0x05` |
|
| Hex | `0x05` |
|
||||||
|
|
||||||
Sends an answerback string. In the VT100, this was configurable by the
|
Sends an answerback string. In the VT100, this was configurable by the
|
||||||
operator.
|
operator.
|
||||||
|
|
||||||
## Implementation Details
|
## Implementation Details
|
||||||
|
|
||||||
* ghostty always sends `""`
|
- ghostty always sends `""`
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* Make the answerback configurable
|
- Make the answerback configurable
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
* https://vt100.net/docs/vt100-ug/chapter3.html
|
- https://vt100.net/docs/vt100-ug/chapter3.html
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
# Form Feed
|
# Form Feed
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ------ |
|
||||||
| Text | |
|
| Text | |
|
||||||
| Hex | `0x0C` |
|
| Hex | `0x0C` |
|
||||||
|
|
||||||
Equivalent to [linefeed](lf.md).
|
Equivalent to [linefeed](lf.md).
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
# Horizontal Tab Set
|
# Horizontal Tab Set
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ----------- |
|
||||||
| Text | `ESC H` |
|
| Text | `ESC H` |
|
||||||
| Hex | `0x18 0x48` |
|
| Hex | `0x18 0x48` |
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
# Index
|
# Index
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ----------- |
|
||||||
| Text | `ESC D` |
|
| Text | `ESC D` |
|
||||||
| Hex | `0x18 0x44` |
|
| Hex | `0x18 0x44` |
|
||||||
|
|
||||||
@@ -10,10 +10,10 @@ if necessary. This always unsets the pending wrap state.
|
|||||||
|
|
||||||
If the cursor is currently outside the scrolling region:
|
If the cursor is currently outside the scrolling region:
|
||||||
|
|
||||||
* move the cursor down one line if it is not on bottom line of the screen.
|
- move the cursor down one line if it is not on bottom line of the screen.
|
||||||
|
|
||||||
If the cursor is inside the scrolling region:
|
If the cursor is inside the scrolling region:
|
||||||
|
|
||||||
* If the cursor is on the bottom-most line of the screen: invoke
|
- If the cursor is on the bottom-most line of the screen: invoke
|
||||||
[scroll up](su.md) with the value `1`.
|
[scroll up](su.md) with the value `1`.
|
||||||
* Else: move the cursor one line down.
|
- Else: move the cursor one line down.
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
# Linefeed
|
# Linefeed
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ------ |
|
||||||
| Text | |
|
| Text | |
|
||||||
| Hex | `0x0A` |
|
| Hex | `0x0A` |
|
||||||
|
|
||||||
Invoke [Index](ind.md).
|
Invoke [Index](ind.md).
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* Linefeed mode (mode 20)
|
- Linefeed mode (mode 20)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
# Index
|
# Index
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ----------- |
|
||||||
| Text | `ESC E` |
|
| Text | `ESC E` |
|
||||||
| Hex | `0x18 0x45` |
|
| Hex | `0x18 0x45` |
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
# Reverse Index
|
# Reverse Index
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ----------- |
|
||||||
| Text | `ESC M` |
|
| Text | `ESC M` |
|
||||||
| Hex | `0x18 0x4D` |
|
| Hex | `0x18 0x4D` |
|
||||||
|
|
||||||
@@ -9,13 +9,13 @@ Reverse [index](ind.md). This unsets the pending wrap state.
|
|||||||
|
|
||||||
If the cursor is outside of the scrolling region:
|
If the cursor is outside of the scrolling region:
|
||||||
|
|
||||||
* move the cursor one line up unless it is the top-most line of the screen.
|
- move the cursor one line up unless it is the top-most line of the screen.
|
||||||
|
|
||||||
If the cursor is inside the scrolling region:
|
If the cursor is inside the scrolling region:
|
||||||
|
|
||||||
* If the cursor is on the top-most line: invoke [scroll down](#) with value `1`
|
- If the cursor is on the top-most line: invoke [scroll down](#) with value `1`
|
||||||
* Else: move the cursor one line up.
|
- Else: move the cursor one line up.
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* Scroll region edge cases
|
- Scroll region edge cases
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
# Tab
|
# Tab
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ------ |
|
||||||
| Text | |
|
| Text | |
|
||||||
| Hex | `0x09` |
|
| Hex | `0x09` |
|
||||||
|
|
||||||
Move the cursor right to the next tab stop.
|
Move the cursor right to the next tab stop.
|
||||||
|
|
||||||
@@ -17,5 +17,5 @@ Initially, tab stops are set on every 8th column.
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* Integration with left/right margins of the scrolling region.
|
- Integration with left/right margins of the scrolling region.
|
||||||
* How does horizontal tab interact with the pending wrap state?
|
- How does horizontal tab interact with the pending wrap state?
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
# Vertical Tab
|
# Vertical Tab
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| ---- | ------ |
|
||||||
| Text | |
|
| Text | |
|
||||||
| Hex | `0x0B` |
|
| Hex | `0x0B` |
|
||||||
|
|
||||||
Equivalent to [linefeed](lf.md).
|
Equivalent to [linefeed](lf.md).
|
||||||
|
292
example/app.ts
292
example/app.ts
@@ -1,14 +1,18 @@
|
|||||||
import { ZigJS } from 'zig-js';
|
import { ZigJS } from "zig-js";
|
||||||
|
|
||||||
const zjs = new ZigJS();
|
const zjs = new ZigJS();
|
||||||
const importObject = {
|
const importObject = {
|
||||||
module: {},
|
module: {},
|
||||||
env: {
|
env: {
|
||||||
memory: new WebAssembly.Memory({ initial: 25, maximum: 65536, shared: true }),
|
memory: new WebAssembly.Memory({
|
||||||
|
initial: 25,
|
||||||
|
maximum: 65536,
|
||||||
|
shared: true,
|
||||||
|
}),
|
||||||
log: (ptr: number, len: number) => {
|
log: (ptr: number, len: number) => {
|
||||||
const arr = new Uint8ClampedArray(zjs.memory.buffer, ptr, len);
|
const arr = new Uint8ClampedArray(zjs.memory.buffer, ptr, len);
|
||||||
const data = arr.slice();
|
const data = arr.slice();
|
||||||
const str = new TextDecoder('utf-8').decode(data);
|
const str = new TextDecoder("utf-8").decode(data);
|
||||||
console.log(str);
|
console.log(str);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -16,158 +20,170 @@ const importObject = {
|
|||||||
...zjs.importObject(),
|
...zjs.importObject(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const url = new URL('ghostty-wasm.wasm', import.meta.url);
|
const url = new URL("ghostty-wasm.wasm", import.meta.url);
|
||||||
fetch(url.href).then(response =>
|
fetch(url.href)
|
||||||
response.arrayBuffer()
|
.then((response) => response.arrayBuffer())
|
||||||
).then(bytes =>
|
.then((bytes) => WebAssembly.instantiate(bytes, importObject))
|
||||||
WebAssembly.instantiate(bytes, importObject)
|
.then((results) => {
|
||||||
).then(results => {
|
const memory = importObject.env.memory;
|
||||||
const memory = importObject.env.memory;
|
const {
|
||||||
const {
|
malloc,
|
||||||
malloc,
|
free,
|
||||||
free,
|
config_new,
|
||||||
config_new,
|
config_free,
|
||||||
config_free,
|
config_load_string,
|
||||||
config_load_string,
|
config_finalize,
|
||||||
config_finalize,
|
face_new,
|
||||||
face_new,
|
face_free,
|
||||||
face_free,
|
face_render_glyph,
|
||||||
face_render_glyph,
|
face_debug_canvas,
|
||||||
face_debug_canvas,
|
deferred_face_new,
|
||||||
deferred_face_new,
|
deferred_face_free,
|
||||||
deferred_face_free,
|
deferred_face_load,
|
||||||
deferred_face_load,
|
deferred_face_face,
|
||||||
deferred_face_face,
|
group_new,
|
||||||
group_new,
|
group_free,
|
||||||
group_free,
|
group_add_face,
|
||||||
group_add_face,
|
group_init_sprite_face,
|
||||||
group_init_sprite_face,
|
group_index_for_codepoint,
|
||||||
group_index_for_codepoint,
|
group_render_glyph,
|
||||||
group_render_glyph,
|
group_cache_new,
|
||||||
group_cache_new,
|
group_cache_free,
|
||||||
group_cache_free,
|
group_cache_index_for_codepoint,
|
||||||
group_cache_index_for_codepoint,
|
group_cache_render_glyph,
|
||||||
group_cache_render_glyph,
|
group_cache_atlas_greyscale,
|
||||||
group_cache_atlas_greyscale,
|
group_cache_atlas_color,
|
||||||
group_cache_atlas_color,
|
atlas_new,
|
||||||
atlas_new,
|
atlas_free,
|
||||||
atlas_free,
|
atlas_debug_canvas,
|
||||||
atlas_debug_canvas,
|
shaper_new,
|
||||||
shaper_new,
|
shaper_free,
|
||||||
shaper_free,
|
shaper_test,
|
||||||
shaper_test,
|
} = results.instance.exports;
|
||||||
} = results.instance.exports;
|
// Give us access to the zjs value for debugging.
|
||||||
// Give us access to the zjs value for debugging.
|
globalThis.zjs = zjs;
|
||||||
globalThis.zjs = zjs;
|
console.log(zjs);
|
||||||
console.log(zjs);
|
|
||||||
|
|
||||||
// Initialize our zig-js memory
|
// Initialize our zig-js memory
|
||||||
zjs.memory = memory;
|
zjs.memory = memory;
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
const makeStr = (str) => {
|
const makeStr = (str) => {
|
||||||
const utf8 = new TextEncoder().encode(str);
|
const utf8 = new TextEncoder().encode(str);
|
||||||
const ptr = malloc(utf8.byteLength);
|
const ptr = malloc(utf8.byteLength);
|
||||||
new Uint8Array(memory.buffer, ptr).set(utf8);
|
new Uint8Array(memory.buffer, ptr).set(utf8);
|
||||||
return { ptr: ptr, len: utf8.byteLength };
|
return { ptr: ptr, len: utf8.byteLength };
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create our config
|
// Create our config
|
||||||
const config = config_new();
|
const config = config_new();
|
||||||
const config_str = makeStr("font-family = monospace");
|
const config_str = makeStr("font-family = monospace");
|
||||||
config_load_string(config, config_str.ptr, config_str.len);
|
config_load_string(config, config_str.ptr, config_str.len);
|
||||||
config_finalize(config);
|
config_finalize(config);
|
||||||
free(config_str.ptr);
|
free(config_str.ptr);
|
||||||
|
|
||||||
// Create our atlas
|
// Create our atlas
|
||||||
// const atlas = atlas_new(512, 0 /* greyscale */);
|
// const atlas = atlas_new(512, 0 /* greyscale */);
|
||||||
|
|
||||||
// Create some memory for our string
|
// Create some memory for our string
|
||||||
const font_name = makeStr("monospace");
|
const font_name = makeStr("monospace");
|
||||||
|
|
||||||
// Initialize our deferred face
|
// Initialize our deferred face
|
||||||
// const df = deferred_face_new(font_ptr, font.byteLength, 0 /* text */);
|
// const df = deferred_face_new(font_ptr, font.byteLength, 0 /* text */);
|
||||||
//deferred_face_load(df, 72 /* size */);
|
//deferred_face_load(df, 72 /* size */);
|
||||||
//const face = deferred_face_face(df);
|
//const face = deferred_face_face(df);
|
||||||
|
|
||||||
// Initialize our font face
|
// Initialize our font face
|
||||||
//const face = face_new(font_ptr, font.byteLength, 72 /* size in px */);
|
//const face = face_new(font_ptr, font.byteLength, 72 /* size in px */);
|
||||||
//free(font_ptr);
|
//free(font_ptr);
|
||||||
|
|
||||||
// Create our group
|
// Create our group
|
||||||
const group = group_new(32 /* size */);
|
const group = group_new(32 /* size */);
|
||||||
group_add_face(group, 0 /* regular */, deferred_face_new(font_name.ptr, font_name.len, 0 /* text */));
|
group_add_face(
|
||||||
group_add_face(group, 0 /* regular */, deferred_face_new(font_name.ptr, font_name.len, 1 /* emoji */));
|
group,
|
||||||
|
0 /* regular */,
|
||||||
|
deferred_face_new(font_name.ptr, font_name.len, 0 /* text */),
|
||||||
|
);
|
||||||
|
group_add_face(
|
||||||
|
group,
|
||||||
|
0 /* regular */,
|
||||||
|
deferred_face_new(font_name.ptr, font_name.len, 1 /* emoji */),
|
||||||
|
);
|
||||||
|
|
||||||
// Initialize our sprite font, without this we just use the browser.
|
// Initialize our sprite font, without this we just use the browser.
|
||||||
group_init_sprite_face(group);
|
group_init_sprite_face(group);
|
||||||
|
|
||||||
// Create our group cache
|
// Create our group cache
|
||||||
const group_cache = group_cache_new(group);
|
const group_cache = group_cache_new(group);
|
||||||
|
|
||||||
// Render a glyph
|
// Render a glyph
|
||||||
// for (let i = 33; i <= 126; i++) {
|
// for (let i = 33; i <= 126; i++) {
|
||||||
// const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
// const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
||||||
// group_cache_render_glyph(group_cache, font_idx, i, 0);
|
// group_cache_render_glyph(group_cache, font_idx, i, 0);
|
||||||
// //face_render_glyph(face, atlas, i);
|
// //face_render_glyph(face, atlas, i);
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// const emoji = ["🐏","🌞","🌚","🍱","💿","🐈","📃","📀","🕡","🙃"];
|
// const emoji = ["🐏","🌞","🌚","🍱","💿","🐈","📃","📀","🕡","🙃"];
|
||||||
// for (let i = 0; i < emoji.length; i++) {
|
// for (let i = 0; i < emoji.length; i++) {
|
||||||
// const cp = emoji[i].codePointAt(0);
|
// const cp = emoji[i].codePointAt(0);
|
||||||
// const font_idx = group_cache_index_for_codepoint(group_cache, cp, 0, -1 /* best choice */);
|
// const font_idx = group_cache_index_for_codepoint(group_cache, cp, 0, -1 /* best choice */);
|
||||||
// group_cache_render_glyph(group_cache, font_idx, cp, 0);
|
// group_cache_render_glyph(group_cache, font_idx, cp, 0);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
for (let i = 0x2500; i <= 0x257F; i++) {
|
for (let i = 0x2500; i <= 0x257f; i++) {
|
||||||
const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
||||||
group_cache_render_glyph(group_cache, font_idx, i, 0);
|
group_cache_render_glyph(group_cache, font_idx, i, 0);
|
||||||
}
|
}
|
||||||
for (let i = 0x2580; i <= 0x259f; i++) {
|
for (let i = 0x2580; i <= 0x259f; i++) {
|
||||||
const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
||||||
group_cache_render_glyph(group_cache, font_idx, i, 0);
|
group_cache_render_glyph(group_cache, font_idx, i, 0);
|
||||||
}
|
}
|
||||||
for (let i = 0x2800; i <= 0x28FF; i++) {
|
for (let i = 0x2800; i <= 0x28ff; i++) {
|
||||||
const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
||||||
group_cache_render_glyph(group_cache, font_idx, i, 0);
|
group_cache_render_glyph(group_cache, font_idx, i, 0);
|
||||||
}
|
}
|
||||||
for (let i = 0x1FB00; i <= 0x1FB3B; i++) {
|
for (let i = 0x1fb00; i <= 0x1fb3b; i++) {
|
||||||
const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
||||||
group_cache_render_glyph(group_cache, font_idx, i, 0);
|
group_cache_render_glyph(group_cache, font_idx, i, 0);
|
||||||
}
|
}
|
||||||
for (let i = 0x1FB3C; i <= 0x1FB6B; i++) {
|
for (let i = 0x1fb3c; i <= 0x1fb6b; i++) {
|
||||||
const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1);
|
||||||
group_cache_render_glyph(group_cache, font_idx, i, 0);
|
group_cache_render_glyph(group_cache, font_idx, i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//face_render_glyph(face, atlas, "橋".codePointAt(0));
|
//face_render_glyph(face, atlas, "橋".codePointAt(0));
|
||||||
//face_render_glyph(face, atlas, "p".codePointAt(0));
|
//face_render_glyph(face, atlas, "p".codePointAt(0));
|
||||||
|
|
||||||
// Debug our canvas
|
// Debug our canvas
|
||||||
//face_debug_canvas(face);
|
//face_debug_canvas(face);
|
||||||
|
|
||||||
// Let's try shaping
|
// Let's try shaping
|
||||||
const shaper = shaper_new(120);
|
const shaper = shaper_new(120);
|
||||||
//const input = makeStr("hello🐏");
|
//const input = makeStr("hello🐏");
|
||||||
const input = makeStr("hello🐏👍🏽");
|
const input = makeStr("hello🐏👍🏽");
|
||||||
shaper_test(shaper, group_cache, input.ptr, input.len);
|
shaper_test(shaper, group_cache, input.ptr, input.len);
|
||||||
|
|
||||||
const cp = 1114112;
|
const cp = 1114112;
|
||||||
const font_idx = group_cache_index_for_codepoint(group_cache, cp, 0, -1 /* best choice */);
|
const font_idx = group_cache_index_for_codepoint(
|
||||||
group_cache_render_glyph(group_cache, font_idx, cp, -1);
|
group_cache,
|
||||||
|
cp,
|
||||||
|
0,
|
||||||
|
-1 /* best choice */,
|
||||||
|
);
|
||||||
|
group_cache_render_glyph(group_cache, font_idx, cp, -1);
|
||||||
|
|
||||||
// Debug our atlas canvas
|
// Debug our atlas canvas
|
||||||
{
|
{
|
||||||
const atlas = group_cache_atlas_greyscale(group_cache);
|
const atlas = group_cache_atlas_greyscale(group_cache);
|
||||||
const id = atlas_debug_canvas(atlas);
|
const id = atlas_debug_canvas(atlas);
|
||||||
document.getElementById("atlas-canvas").append(zjs.deleteValue(id));
|
document.getElementById("atlas-canvas").append(zjs.deleteValue(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const atlas = group_cache_atlas_color(group_cache);
|
const atlas = group_cache_atlas_color(group_cache);
|
||||||
const id = atlas_debug_canvas(atlas);
|
const id = atlas_debug_canvas(atlas);
|
||||||
document.getElementById("atlas-color-canvas").append(zjs.deleteValue(id));
|
document.getElementById("atlas-color-canvas").append(zjs.deleteValue(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
//face_free(face);
|
//face_free(face);
|
||||||
});
|
});
|
||||||
|
@@ -38,4 +38,3 @@ the full test suite against only a single terminal emulator.
|
|||||||
This test suite expects the `ghostty` binary to be in _this directory_.
|
This test suite expects the `ghostty` binary to be in _this directory_.
|
||||||
You can manually copy it into place. Each time you modify the binary, you
|
You can manually copy it into place. Each time you modify the binary, you
|
||||||
must rebuild the Docker image.
|
must rebuild the Docker image.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user