mirror of
https://github.com/wez/wezterm.git
synced 2024-08-16 17:50:28 +03:00
Merge branch 'wez:main' into title-argument
This commit is contained in:
commit
ffa4ae4878
87
.cirrus.yml
87
.cirrus.yml
@ -1,17 +1,18 @@
|
||||
compute_engine_instance:
|
||||
image_project: freebsd-org-cloud-dev
|
||||
image: family/freebsd-13-2
|
||||
platform: freebsd
|
||||
cpu: 4
|
||||
memory: 8G
|
||||
disk: 100 # Gb
|
||||
|
||||
env:
|
||||
CIRRUS_CLONE_SUBMODULES: true
|
||||
CIRRUS_CLONE_DEPTH: 1
|
||||
|
||||
task:
|
||||
name: freebsd-13
|
||||
|
||||
compute_engine_instance:
|
||||
image_project: freebsd-org-cloud-dev
|
||||
image: family/freebsd-13-2
|
||||
platform: freebsd
|
||||
cpu: 4
|
||||
memory: 8G
|
||||
disk: 100 # Gb
|
||||
|
||||
stateful: false
|
||||
only_if: "changesInclude('**.toml', '**.rs', '.gitmodules', '.cirrus.yml', 'get-deps', 'Cargo.lock')"
|
||||
install_rust_script:
|
||||
@ -35,3 +36,73 @@ task:
|
||||
- env PATH=$HOME/.cargo/bin:$PATH cargo build --all --release
|
||||
test_script:
|
||||
- env PATH=$HOME/.cargo/bin:$PATH cargo test --all --release
|
||||
|
||||
task:
|
||||
name: ubuntu-22.04-arm
|
||||
only_if: "$CIRRUS_REPO_OWNER == 'wez' && changesInclude('**.toml', '**.rs', '.gitmodules', '.cirrus.yml', 'get-deps', 'Cargo.lock')"
|
||||
arm_container:
|
||||
image: ubuntu:22.04
|
||||
cpu: 4
|
||||
memory: 12G
|
||||
environment:
|
||||
GITHUB_TOKEN: ENCRYPTED[23bd9513fa7174e74eaddce6a3099cabb22118423591553b23518e8c34bf155e07c559838b1d3422f561c73c1e31e6fc]
|
||||
|
||||
stateful: false
|
||||
install_rust_script:
|
||||
- echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
||||
- apt update
|
||||
- apt-get install -y git curl
|
||||
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
install_gh_cli_script:
|
||||
- curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg > /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
- chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list
|
||||
- apt update
|
||||
- apt install gh -y
|
||||
- gh --version
|
||||
getdeps_script:
|
||||
- env PATH=$HOME/.cargo/bin:$PATH bash get-deps
|
||||
build_script:
|
||||
- env PATH=$HOME/.cargo/bin:$PATH cargo build --release -p wezterm-gui -p wezterm -p wezterm-mux-server -p strip-ansi-escapes
|
||||
- export BUILD_REASON="Schedule"
|
||||
- export RELEASE="nightly"
|
||||
- "test -n \"$CIRRUS_TAG\" && BUILD_REASON=\"tag\""
|
||||
- "test -n \"$CIRRUS_TAG\" && RELEASE=$(ci/tag-name.sh)"
|
||||
- "./ci/deploy.sh"
|
||||
- "ls -l *.deb"
|
||||
- "bash ci/retry.sh gh release upload --clobber ${RELEASE} *.deb"
|
||||
|
||||
task:
|
||||
name: debian-12-arm
|
||||
only_if: "$CIRRUS_REPO_OWNER == 'wez' && changesInclude('**.toml', '**.rs', '.gitmodules', '.cirrus.yml', 'get-deps', 'Cargo.lock')"
|
||||
arm_container:
|
||||
image: debian:12
|
||||
cpu: 4
|
||||
memory: 12G
|
||||
environment:
|
||||
GITHUB_TOKEN: ENCRYPTED[23bd9513fa7174e74eaddce6a3099cabb22118423591553b23518e8c34bf155e07c559838b1d3422f561c73c1e31e6fc]
|
||||
|
||||
stateful: false
|
||||
install_rust_script:
|
||||
- echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
||||
- apt update
|
||||
- apt-get install -y git curl
|
||||
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
install_gh_cli_script:
|
||||
- curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg > /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
- chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list
|
||||
- apt update
|
||||
- apt install gh -y
|
||||
- gh --version
|
||||
getdeps_script:
|
||||
- env PATH=$HOME/.cargo/bin:$PATH bash get-deps
|
||||
build_script:
|
||||
- env PATH=$HOME/.cargo/bin:$PATH cargo build --release -p wezterm-gui -p wezterm -p wezterm-mux-server -p strip-ansi-escapes
|
||||
- export BUILD_REASON="Schedule"
|
||||
- export RELEASE="nightly"
|
||||
- "test -n \"$CIRRUS_TAG\" && BUILD_REASON=\"tag\""
|
||||
- "test -n \"$CIRRUS_TAG\" && RELEASE=$(ci/tag-name.sh)"
|
||||
- "./ci/deploy.sh"
|
||||
- "ls -l *.deb"
|
||||
- "bash ci/retry.sh gh release upload --clobber ${RELEASE} *.deb"
|
||||
|
2
.copr/Makefile
Normal file
2
.copr/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
srpm:
|
||||
COPR_SRPM=$(outdir) ./ci/copr-build.sh
|
55
.github/DISCUSSION_TEMPLATE/q-a.yml
vendored
Normal file
55
.github/DISCUSSION_TEMPLATE/q-a.yml
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
labels: []
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
When asking for help troubleshooting something, please remember
|
||||
to share as much context about what you're trying to do,
|
||||
specifically what configuration you tried, what happened and how it
|
||||
didn't match up to what you expected!
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: What Operating System(s) are you running on?
|
||||
multiple: true
|
||||
options:
|
||||
- Windows
|
||||
- Linux X11
|
||||
- Linux Wayland
|
||||
- macOS
|
||||
- FreeBSD X11
|
||||
- FreeBSD Wayland
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: window_manager
|
||||
attributes:
|
||||
label: Which Wayland compositor or X11 Window manager(s) are you using?
|
||||
description: |
|
||||
If running on a unix system, please include the name and version of the compositor/WM.
|
||||
Windows and macOS typically can leave this blank, but if you are using additional window
|
||||
management software on top of the standard for those systems, please indicate that here.
|
||||
placeholder: "ex: Sway, Mutter, wayfire, i3."
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: WezTerm version
|
||||
description: |
|
||||
Please run `wezterm -V` and include its output here.
|
||||
If you installed the flatpak version of wezterm, please consider trying
|
||||
the native package format for your system and comparing the behavior,
|
||||
as flatpak runs in an isolated sandbox that can prevent some functionality
|
||||
from working fully.
|
||||
placeholder: "ex: 20210816-085256-935c1f48"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Ask your question!
|
||||
description: |
|
||||
Please remember to share as much context as you can, as that makes it
|
||||
quicker and easier for others to understand and respond
|
||||
placeholder: Tell us what is on your mind!
|
||||
validations:
|
||||
required: true
|
@ -1,4 +1,4 @@
|
||||
name: fedora36
|
||||
name: fedora39
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@ -8,7 +8,7 @@ on:
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.lock"
|
||||
- "**/Cargo.toml"
|
||||
- ".github/workflows/gen_fedora36.yml"
|
||||
- ".github/workflows/gen_fedora39.yml"
|
||||
- "assets/fonts/**/*"
|
||||
- "assets/icon/*"
|
||||
- "assets/open-wezterm-here"
|
||||
@ -25,7 +25,7 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container: "fedora:36"
|
||||
container: "fedora:39"
|
||||
|
||||
steps:
|
||||
- name: "Install config manager"
|
||||
@ -55,7 +55,7 @@ jobs:
|
||||
- name: "Cache cargo"
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "fedora36-None-2-${{ runner.os }}-cargo"
|
||||
key: "fedora39-None-2-${{ runner.os }}-cargo"
|
||||
- name: "Install System Deps"
|
||||
shell: bash
|
||||
run: "env CI=yes PATH=$PATH ./get-deps"
|
||||
@ -66,7 +66,7 @@ jobs:
|
||||
uses: baptiste0928/cargo-install@v2
|
||||
with:
|
||||
crate: "cargo-nextest"
|
||||
cache-key: "fedora36"
|
||||
cache-key: "fedora39"
|
||||
- name: "Test (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo nextest run --all --release --no-fail-fast"
|
||||
@ -79,5 +79,5 @@ jobs:
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "fedora36"
|
||||
name: "fedora39"
|
||||
path: "wezterm-*.rpm"
|
@ -1,4 +1,4 @@
|
||||
name: fedora36_continuous
|
||||
name: fedora39_continuous
|
||||
|
||||
on:
|
||||
schedule:
|
||||
@ -10,7 +10,7 @@ on:
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.lock"
|
||||
- "**/Cargo.toml"
|
||||
- ".github/workflows/gen_fedora36_continuous.yml"
|
||||
- ".github/workflows/gen_fedora39_continuous.yml"
|
||||
- "assets/fonts/**/*"
|
||||
- "assets/icon/*"
|
||||
- "assets/open-wezterm-here"
|
||||
@ -27,7 +27,7 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container: "fedora:36"
|
||||
container: "fedora:39"
|
||||
env:
|
||||
BUILD_REASON: "Schedule"
|
||||
|
||||
@ -59,7 +59,7 @@ jobs:
|
||||
- name: "Cache cargo"
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "fedora36-None-2-${{ runner.os }}-cargo"
|
||||
key: "fedora39-None-2-${{ runner.os }}-cargo"
|
||||
- name: "Install System Deps"
|
||||
shell: bash
|
||||
run: "env CI=yes PATH=$PATH ./get-deps"
|
||||
@ -70,7 +70,7 @@ jobs:
|
||||
uses: baptiste0928/cargo-install@v2
|
||||
with:
|
||||
crate: "cargo-nextest"
|
||||
cache-key: "fedora36"
|
||||
cache-key: "fedora39"
|
||||
- name: "Test (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo nextest run --all --release --no-fail-fast"
|
||||
@ -79,11 +79,11 @@ jobs:
|
||||
run: "bash ci/deploy.sh"
|
||||
- name: "Move RPM"
|
||||
shell: bash
|
||||
run: "mv ~/rpmbuild/RPMS/*/*.rpm wezterm-nightly-fedora36.rpm"
|
||||
run: "mv ~/rpmbuild/RPMS/*/*.rpm wezterm-nightly-fedora39.rpm"
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "fedora36"
|
||||
name: "fedora39"
|
||||
path: "wezterm-*.rpm"
|
||||
retention-days: 5
|
||||
|
||||
@ -100,7 +100,7 @@ jobs:
|
||||
- name: "Download artifact"
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "fedora36"
|
||||
name: "fedora39"
|
||||
- name: "Checksum"
|
||||
shell: bash
|
||||
run: "for f in wezterm-*.rpm ; do sha256sum $f > $f.sha256 ; done"
|
@ -1,4 +1,4 @@
|
||||
name: fedora36_tag
|
||||
name: fedora39_tag
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container: "fedora:36"
|
||||
container: "fedora:39"
|
||||
|
||||
steps:
|
||||
- name: "Install config manager"
|
||||
@ -38,7 +38,7 @@ jobs:
|
||||
- name: "Cache cargo"
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "fedora36-None-2-${{ runner.os }}-cargo"
|
||||
key: "fedora39-None-2-${{ runner.os }}-cargo"
|
||||
- name: "Install System Deps"
|
||||
shell: bash
|
||||
run: "env CI=yes PATH=$PATH ./get-deps"
|
||||
@ -49,7 +49,7 @@ jobs:
|
||||
uses: baptiste0928/cargo-install@v2
|
||||
with:
|
||||
crate: "cargo-nextest"
|
||||
cache-key: "fedora36"
|
||||
cache-key: "fedora39"
|
||||
- name: "Test (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo nextest run --all --release --no-fail-fast"
|
||||
@ -62,7 +62,7 @@ jobs:
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "fedora36"
|
||||
name: "fedora39"
|
||||
path: "wezterm-*.rpm"
|
||||
|
||||
upload:
|
||||
@ -78,7 +78,7 @@ jobs:
|
||||
- name: "Download artifact"
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "fedora36"
|
||||
name: "fedora39"
|
||||
- name: "Checksum"
|
||||
shell: bash
|
||||
run: "for f in wezterm-*.rpm ; do sha256sum $f > $f.sha256 ; done"
|
86
.github/workflows/gen_opensuse_leap.yml
vendored
86
.github/workflows/gen_opensuse_leap.yml
vendored
@ -1,86 +0,0 @@
|
||||
name: opensuse_leap
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.lock"
|
||||
- "**/Cargo.toml"
|
||||
- ".github/workflows/gen_opensuse_leap.yml"
|
||||
- "assets/fonts/**/*"
|
||||
- "assets/icon/*"
|
||||
- "assets/open-wezterm-here"
|
||||
- "assets/shell-completion/**/*"
|
||||
- "assets/shell-integration/**/*"
|
||||
- "assets/wezterm-nautilus.py"
|
||||
- "assets/wezterm.appdata.xml"
|
||||
- "assets/wezterm.desktop"
|
||||
- "ci/deploy.sh"
|
||||
- "ci/tag-name.sh"
|
||||
- "get-deps"
|
||||
- "termwiz/data/wezterm.terminfo"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container: "registry.opensuse.org/opensuse/leap:15.4"
|
||||
|
||||
steps:
|
||||
- name: "Seed GITHUB_PATH to work around possible @action/core bug"
|
||||
shell: bash
|
||||
run: 'echo "$PATH:/bin:/usr/bin" >> $GITHUB_PATH'
|
||||
- name: "Install util-linux"
|
||||
shell: bash
|
||||
run: "zypper install -y util-linux"
|
||||
- name: "Install git"
|
||||
shell: bash
|
||||
run: "zypper install -y git"
|
||||
- name: "Install curl"
|
||||
shell: bash
|
||||
run: "zypper install -y curl"
|
||||
- name: "Ensure /run/sshd exists"
|
||||
shell: bash
|
||||
run: "mkdir -p /run/sshd"
|
||||
- name: "Install openssh-server"
|
||||
shell: bash
|
||||
run: "zypper install -y openssh-server"
|
||||
- name: "Workaround git permissions issue"
|
||||
shell: bash
|
||||
run: "git config --global --add safe.directory /__w/wezterm/wezterm"
|
||||
- name: "checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
- name: "Install Rust"
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: "Cache cargo"
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "opensuse_leap-None-2-${{ runner.os }}-cargo"
|
||||
- name: "Install System Deps"
|
||||
shell: bash
|
||||
run: "env CI=yes PATH=$PATH ./get-deps"
|
||||
- name: "Build (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo build --all --release"
|
||||
- name: "Install cargo-nextest from Cargo"
|
||||
uses: baptiste0928/cargo-install@v2
|
||||
with:
|
||||
crate: "cargo-nextest"
|
||||
cache-key: "opensuse_leap"
|
||||
- name: "Test (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo nextest run --all --release --no-fail-fast"
|
||||
- name: "Package"
|
||||
shell: bash
|
||||
run: "bash ci/deploy.sh"
|
||||
- name: "Move RPM"
|
||||
shell: bash
|
||||
run: "mv /usr/src/packages/RPMS/*/*.rpm ."
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "opensuse_leap"
|
||||
path: "wezterm-*.rpm"
|
114
.github/workflows/gen_opensuse_leap_continuous.yml
vendored
114
.github/workflows/gen_opensuse_leap_continuous.yml
vendored
@ -1,114 +0,0 @@
|
||||
name: opensuse_leap_continuous
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "10 3 * * *"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.lock"
|
||||
- "**/Cargo.toml"
|
||||
- ".github/workflows/gen_opensuse_leap_continuous.yml"
|
||||
- "assets/fonts/**/*"
|
||||
- "assets/icon/*"
|
||||
- "assets/open-wezterm-here"
|
||||
- "assets/shell-completion/**/*"
|
||||
- "assets/shell-integration/**/*"
|
||||
- "assets/wezterm-nautilus.py"
|
||||
- "assets/wezterm.appdata.xml"
|
||||
- "assets/wezterm.desktop"
|
||||
- "ci/deploy.sh"
|
||||
- "ci/tag-name.sh"
|
||||
- "get-deps"
|
||||
- "termwiz/data/wezterm.terminfo"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container: "registry.opensuse.org/opensuse/leap:15.4"
|
||||
env:
|
||||
BUILD_REASON: "Schedule"
|
||||
|
||||
steps:
|
||||
- name: "Seed GITHUB_PATH to work around possible @action/core bug"
|
||||
shell: bash
|
||||
run: 'echo "$PATH:/bin:/usr/bin" >> $GITHUB_PATH'
|
||||
- name: "Install util-linux"
|
||||
shell: bash
|
||||
run: "zypper install -y util-linux"
|
||||
- name: "Install git"
|
||||
shell: bash
|
||||
run: "zypper install -y git"
|
||||
- name: "Install curl"
|
||||
shell: bash
|
||||
run: "zypper install -y curl"
|
||||
- name: "Ensure /run/sshd exists"
|
||||
shell: bash
|
||||
run: "mkdir -p /run/sshd"
|
||||
- name: "Install openssh-server"
|
||||
shell: bash
|
||||
run: "zypper install -y openssh-server"
|
||||
- name: "Workaround git permissions issue"
|
||||
shell: bash
|
||||
run: "git config --global --add safe.directory /__w/wezterm/wezterm"
|
||||
- name: "checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
- name: "Install Rust"
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: "Cache cargo"
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "opensuse_leap-None-2-${{ runner.os }}-cargo"
|
||||
- name: "Install System Deps"
|
||||
shell: bash
|
||||
run: "env CI=yes PATH=$PATH ./get-deps"
|
||||
- name: "Build (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo build --all --release"
|
||||
- name: "Install cargo-nextest from Cargo"
|
||||
uses: baptiste0928/cargo-install@v2
|
||||
with:
|
||||
crate: "cargo-nextest"
|
||||
cache-key: "opensuse_leap"
|
||||
- name: "Test (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo nextest run --all --release --no-fail-fast"
|
||||
- name: "Package"
|
||||
shell: bash
|
||||
run: "bash ci/deploy.sh"
|
||||
- name: "Move RPM"
|
||||
shell: bash
|
||||
run: "mv /usr/src/packages/RPMS/*/*.rpm wezterm-nightly-opensuse_leap.rpm"
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "opensuse_leap"
|
||||
path: "wezterm-*.rpm"
|
||||
retention-days: 5
|
||||
|
||||
upload:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: "Workaround git permissions issue"
|
||||
shell: bash
|
||||
run: "git config --global --add safe.directory /__w/wezterm/wezterm"
|
||||
- name: "checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
- name: "Download artifact"
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "opensuse_leap"
|
||||
- name: "Checksum"
|
||||
shell: bash
|
||||
run: "for f in wezterm-*.rpm ; do sha256sum $f > $f.sha256 ; done"
|
||||
- name: "Upload to Nightly Release"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: "bash ci/retry.sh gh release upload --clobber nightly wezterm-*.rpm *.sha256"
|
97
.github/workflows/gen_opensuse_leap_tag.yml
vendored
97
.github/workflows/gen_opensuse_leap_tag.yml
vendored
@ -1,97 +0,0 @@
|
||||
name: opensuse_leap_tag
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "20*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container: "registry.opensuse.org/opensuse/leap:15.4"
|
||||
|
||||
steps:
|
||||
- name: "Seed GITHUB_PATH to work around possible @action/core bug"
|
||||
shell: bash
|
||||
run: 'echo "$PATH:/bin:/usr/bin" >> $GITHUB_PATH'
|
||||
- name: "Install util-linux"
|
||||
shell: bash
|
||||
run: "zypper install -y util-linux"
|
||||
- name: "Install git"
|
||||
shell: bash
|
||||
run: "zypper install -y git"
|
||||
- name: "Install curl"
|
||||
shell: bash
|
||||
run: "zypper install -y curl"
|
||||
- name: "Ensure /run/sshd exists"
|
||||
shell: bash
|
||||
run: "mkdir -p /run/sshd"
|
||||
- name: "Install openssh-server"
|
||||
shell: bash
|
||||
run: "zypper install -y openssh-server"
|
||||
- name: "Workaround git permissions issue"
|
||||
shell: bash
|
||||
run: "git config --global --add safe.directory /__w/wezterm/wezterm"
|
||||
- name: "checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
- name: "Install Rust"
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: "Cache cargo"
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "opensuse_leap-None-2-${{ runner.os }}-cargo"
|
||||
- name: "Install System Deps"
|
||||
shell: bash
|
||||
run: "env CI=yes PATH=$PATH ./get-deps"
|
||||
- name: "Build (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo build --all --release"
|
||||
- name: "Install cargo-nextest from Cargo"
|
||||
uses: baptiste0928/cargo-install@v2
|
||||
with:
|
||||
crate: "cargo-nextest"
|
||||
cache-key: "opensuse_leap"
|
||||
- name: "Test (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo nextest run --all --release --no-fail-fast"
|
||||
- name: "Package"
|
||||
shell: bash
|
||||
run: "bash ci/deploy.sh"
|
||||
- name: "Move RPM"
|
||||
shell: bash
|
||||
run: "mv /usr/src/packages/RPMS/*/*.rpm ."
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "opensuse_leap"
|
||||
path: "wezterm-*.rpm"
|
||||
|
||||
upload:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: "Workaround git permissions issue"
|
||||
shell: bash
|
||||
run: "git config --global --add safe.directory /__w/wezterm/wezterm"
|
||||
- name: "checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
- name: "Download artifact"
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "opensuse_leap"
|
||||
- name: "Checksum"
|
||||
shell: bash
|
||||
run: "for f in wezterm-*.rpm ; do sha256sum $f > $f.sha256 ; done"
|
||||
- name: "Create pre-release"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: "bash ci/retry.sh bash ci/create-release.sh $(ci/tag-name.sh)"
|
||||
- name: "Upload to Tagged Release"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: "bash ci/retry.sh gh release upload --clobber $(ci/tag-name.sh) wezterm-*.rpm *.sha256"
|
89
.github/workflows/gen_opensuse_tumbleweed.yml
vendored
89
.github/workflows/gen_opensuse_tumbleweed.yml
vendored
@ -1,89 +0,0 @@
|
||||
name: opensuse_tumbleweed
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.lock"
|
||||
- "**/Cargo.toml"
|
||||
- ".github/workflows/gen_opensuse_tumbleweed.yml"
|
||||
- "assets/fonts/**/*"
|
||||
- "assets/icon/*"
|
||||
- "assets/open-wezterm-here"
|
||||
- "assets/shell-completion/**/*"
|
||||
- "assets/shell-integration/**/*"
|
||||
- "assets/wezterm-nautilus.py"
|
||||
- "assets/wezterm.appdata.xml"
|
||||
- "assets/wezterm.desktop"
|
||||
- "ci/deploy.sh"
|
||||
- "ci/tag-name.sh"
|
||||
- "get-deps"
|
||||
- "termwiz/data/wezterm.terminfo"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container: "registry.opensuse.org/opensuse/tumbleweed"
|
||||
|
||||
steps:
|
||||
- name: "Seed GITHUB_PATH to work around possible @action/core bug"
|
||||
shell: bash
|
||||
run: 'echo "$PATH:/bin:/usr/bin" >> $GITHUB_PATH'
|
||||
- name: "Install util-linux"
|
||||
shell: bash
|
||||
run: "zypper install -y util-linux"
|
||||
- name: "Install which"
|
||||
shell: bash
|
||||
run: "zypper install -y which"
|
||||
- name: "Install git"
|
||||
shell: bash
|
||||
run: "zypper install -y git"
|
||||
- name: "Install curl"
|
||||
shell: bash
|
||||
run: "zypper install -y curl"
|
||||
- name: "Ensure /run/sshd exists"
|
||||
shell: bash
|
||||
run: "mkdir -p /run/sshd"
|
||||
- name: "Install openssh-server"
|
||||
shell: bash
|
||||
run: "zypper install -y openssh-server"
|
||||
- name: "Workaround git permissions issue"
|
||||
shell: bash
|
||||
run: "git config --global --add safe.directory /__w/wezterm/wezterm"
|
||||
- name: "checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
- name: "Install Rust"
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: "Cache cargo"
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "opensuse_tumbleweed-None-2-${{ runner.os }}-cargo"
|
||||
- name: "Install System Deps"
|
||||
shell: bash
|
||||
run: "env CI=yes PATH=$PATH ./get-deps"
|
||||
- name: "Build (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo build --all --release"
|
||||
- name: "Install cargo-nextest from Cargo"
|
||||
uses: baptiste0928/cargo-install@v2
|
||||
with:
|
||||
crate: "cargo-nextest"
|
||||
cache-key: "opensuse_tumbleweed"
|
||||
- name: "Test (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo nextest run --all --release --no-fail-fast"
|
||||
- name: "Package"
|
||||
shell: bash
|
||||
run: "bash ci/deploy.sh"
|
||||
- name: "Move RPM"
|
||||
shell: bash
|
||||
run: "mv /usr/src/packages/RPMS/*/*.rpm ."
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "opensuse_tumbleweed"
|
||||
path: "wezterm-*.rpm"
|
@ -1,117 +0,0 @@
|
||||
name: opensuse_tumbleweed_continuous
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "10 3 * * *"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.lock"
|
||||
- "**/Cargo.toml"
|
||||
- ".github/workflows/gen_opensuse_tumbleweed_continuous.yml"
|
||||
- "assets/fonts/**/*"
|
||||
- "assets/icon/*"
|
||||
- "assets/open-wezterm-here"
|
||||
- "assets/shell-completion/**/*"
|
||||
- "assets/shell-integration/**/*"
|
||||
- "assets/wezterm-nautilus.py"
|
||||
- "assets/wezterm.appdata.xml"
|
||||
- "assets/wezterm.desktop"
|
||||
- "ci/deploy.sh"
|
||||
- "ci/tag-name.sh"
|
||||
- "get-deps"
|
||||
- "termwiz/data/wezterm.terminfo"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container: "registry.opensuse.org/opensuse/tumbleweed"
|
||||
env:
|
||||
BUILD_REASON: "Schedule"
|
||||
|
||||
steps:
|
||||
- name: "Seed GITHUB_PATH to work around possible @action/core bug"
|
||||
shell: bash
|
||||
run: 'echo "$PATH:/bin:/usr/bin" >> $GITHUB_PATH'
|
||||
- name: "Install util-linux"
|
||||
shell: bash
|
||||
run: "zypper install -y util-linux"
|
||||
- name: "Install which"
|
||||
shell: bash
|
||||
run: "zypper install -y which"
|
||||
- name: "Install git"
|
||||
shell: bash
|
||||
run: "zypper install -y git"
|
||||
- name: "Install curl"
|
||||
shell: bash
|
||||
run: "zypper install -y curl"
|
||||
- name: "Ensure /run/sshd exists"
|
||||
shell: bash
|
||||
run: "mkdir -p /run/sshd"
|
||||
- name: "Install openssh-server"
|
||||
shell: bash
|
||||
run: "zypper install -y openssh-server"
|
||||
- name: "Workaround git permissions issue"
|
||||
shell: bash
|
||||
run: "git config --global --add safe.directory /__w/wezterm/wezterm"
|
||||
- name: "checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
- name: "Install Rust"
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: "Cache cargo"
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "opensuse_tumbleweed-None-2-${{ runner.os }}-cargo"
|
||||
- name: "Install System Deps"
|
||||
shell: bash
|
||||
run: "env CI=yes PATH=$PATH ./get-deps"
|
||||
- name: "Build (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo build --all --release"
|
||||
- name: "Install cargo-nextest from Cargo"
|
||||
uses: baptiste0928/cargo-install@v2
|
||||
with:
|
||||
crate: "cargo-nextest"
|
||||
cache-key: "opensuse_tumbleweed"
|
||||
- name: "Test (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo nextest run --all --release --no-fail-fast"
|
||||
- name: "Package"
|
||||
shell: bash
|
||||
run: "bash ci/deploy.sh"
|
||||
- name: "Move RPM"
|
||||
shell: bash
|
||||
run: "mv /usr/src/packages/RPMS/*/*.rpm wezterm-nightly-opensuse_tumbleweed.rpm"
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "opensuse_tumbleweed"
|
||||
path: "wezterm-*.rpm"
|
||||
retention-days: 5
|
||||
|
||||
upload:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: "Workaround git permissions issue"
|
||||
shell: bash
|
||||
run: "git config --global --add safe.directory /__w/wezterm/wezterm"
|
||||
- name: "checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
- name: "Download artifact"
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "opensuse_tumbleweed"
|
||||
- name: "Checksum"
|
||||
shell: bash
|
||||
run: "for f in wezterm-*.rpm ; do sha256sum $f > $f.sha256 ; done"
|
||||
- name: "Upload to Nightly Release"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: "bash ci/retry.sh gh release upload --clobber nightly wezterm-*.rpm *.sha256"
|
100
.github/workflows/gen_opensuse_tumbleweed_tag.yml
vendored
100
.github/workflows/gen_opensuse_tumbleweed_tag.yml
vendored
@ -1,100 +0,0 @@
|
||||
name: opensuse_tumbleweed_tag
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "20*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container: "registry.opensuse.org/opensuse/tumbleweed"
|
||||
|
||||
steps:
|
||||
- name: "Seed GITHUB_PATH to work around possible @action/core bug"
|
||||
shell: bash
|
||||
run: 'echo "$PATH:/bin:/usr/bin" >> $GITHUB_PATH'
|
||||
- name: "Install util-linux"
|
||||
shell: bash
|
||||
run: "zypper install -y util-linux"
|
||||
- name: "Install which"
|
||||
shell: bash
|
||||
run: "zypper install -y which"
|
||||
- name: "Install git"
|
||||
shell: bash
|
||||
run: "zypper install -y git"
|
||||
- name: "Install curl"
|
||||
shell: bash
|
||||
run: "zypper install -y curl"
|
||||
- name: "Ensure /run/sshd exists"
|
||||
shell: bash
|
||||
run: "mkdir -p /run/sshd"
|
||||
- name: "Install openssh-server"
|
||||
shell: bash
|
||||
run: "zypper install -y openssh-server"
|
||||
- name: "Workaround git permissions issue"
|
||||
shell: bash
|
||||
run: "git config --global --add safe.directory /__w/wezterm/wezterm"
|
||||
- name: "checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
- name: "Install Rust"
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: "Cache cargo"
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "opensuse_tumbleweed-None-2-${{ runner.os }}-cargo"
|
||||
- name: "Install System Deps"
|
||||
shell: bash
|
||||
run: "env CI=yes PATH=$PATH ./get-deps"
|
||||
- name: "Build (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo build --all --release"
|
||||
- name: "Install cargo-nextest from Cargo"
|
||||
uses: baptiste0928/cargo-install@v2
|
||||
with:
|
||||
crate: "cargo-nextest"
|
||||
cache-key: "opensuse_tumbleweed"
|
||||
- name: "Test (Release mode)"
|
||||
shell: bash
|
||||
run: "cargo nextest run --all --release --no-fail-fast"
|
||||
- name: "Package"
|
||||
shell: bash
|
||||
run: "bash ci/deploy.sh"
|
||||
- name: "Move RPM"
|
||||
shell: bash
|
||||
run: "mv /usr/src/packages/RPMS/*/*.rpm ."
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "opensuse_tumbleweed"
|
||||
path: "wezterm-*.rpm"
|
||||
|
||||
upload:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: "Workaround git permissions issue"
|
||||
shell: bash
|
||||
run: "git config --global --add safe.directory /__w/wezterm/wezterm"
|
||||
- name: "checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
- name: "Download artifact"
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "opensuse_tumbleweed"
|
||||
- name: "Checksum"
|
||||
shell: bash
|
||||
run: "for f in wezterm-*.rpm ; do sha256sum $f > $f.sha256 ; done"
|
||||
- name: "Create pre-release"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: "bash ci/retry.sh bash ci/create-release.sh $(ci/tag-name.sh)"
|
||||
- name: "Upload to Tagged Release"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: "bash ci/retry.sh gh release upload --clobber $(ci/tag-name.sh) wezterm-*.rpm *.sha256"
|
2
.github/workflows/lock.yml
vendored
2
.github/workflows/lock.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v4
|
||||
- uses: dessant/lock-threads@v5
|
||||
with:
|
||||
issue-inactive-days: '30'
|
||||
issue-comment: >
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,6 +15,7 @@ dhat-heap.json
|
||||
/termwiz/codegen/target
|
||||
/termwiz/codegen/Cargo.lock
|
||||
/gh_pages/
|
||||
/.cache/
|
||||
/docs/releases.json
|
||||
/docs/SUMMARY.md
|
||||
/docs/cli/cli/index.md
|
||||
|
@ -11,6 +11,20 @@ and smoother if you have the time and energy to read and follow these suggestion
|
||||
|
||||
There's never enough! Pretty much anything is fair game to improve here.
|
||||
|
||||
### Running the doc build yourself
|
||||
|
||||
To check your documentation additions, you can optionally build the docs yourself and see how the changes will look on the webpage.
|
||||
|
||||
To serve them up, and then automatically rebuild and refresh the docs in your browser, run:
|
||||
```console
|
||||
$ ci/build-docs.sh serve
|
||||
```
|
||||
And then click on the URL that it prints out after it has performed the first build.
|
||||
|
||||
Any arguments passed to `build-docs.sh` are passed down to the underlying `mkdocs` utility.
|
||||
|
||||
Look at [mkdocs serve](https://www.mkdocs.org/user-guide/cli/#mkdocs-serve) for more information on additional parameters.
|
||||
|
||||
### Operating system specific installation instructions?
|
||||
|
||||
There are a lot of targets out there. Today we have docs that are Ubuntu biased
|
||||
@ -44,14 +58,14 @@ I tend to iterate and sanity check as I develop using `cargo check`; it
|
||||
will type-check your code without generating code which is much faster
|
||||
than building everything in release mode:
|
||||
|
||||
```
|
||||
```console
|
||||
$ cargo check
|
||||
```
|
||||
|
||||
Likewise, if you want to quick check that something works, you can run it
|
||||
in debug mode using:
|
||||
|
||||
```
|
||||
```console
|
||||
$ cargo run
|
||||
```
|
||||
|
||||
@ -60,7 +74,7 @@ give you more detail in the backtrace produced if you run `RUST_BACKTRACE=1 carg
|
||||
|
||||
If you get a panic and want to examine local variables, you'll need to use gdb:
|
||||
|
||||
```
|
||||
```console
|
||||
$ cargo build
|
||||
$ gdb ./target/debug/wezterm
|
||||
$ break rust_panic # hit tab to complete the name of the panic symbol!
|
||||
@ -74,7 +88,7 @@ This will help ensure that your contributions keep working as things change.
|
||||
|
||||
You can run the existing tests using:
|
||||
|
||||
```
|
||||
```console
|
||||
$ cargo test --all
|
||||
```
|
||||
|
||||
@ -109,7 +123,7 @@ how that process works.
|
||||
Make sure that the tests are working and that the code is correctly
|
||||
formatted otherwise the continuous integration system will fail your build:
|
||||
|
||||
```
|
||||
```console
|
||||
$ rustup component add rustfmt-preview # you only need to do this once
|
||||
$ cargo test --all
|
||||
$ cargo fmt --all
|
||||
|
1503
Cargo.lock
generated
1503
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1574,12 +1574,16 @@ _wezterm() {
|
||||
return 0
|
||||
;;
|
||||
wezterm__record)
|
||||
opts="-h --help [PROG]..."
|
||||
opts="-h --cwd --help [PROG]..."
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
--cwd)
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
|
@ -168,10 +168,10 @@ complete -c wezterm -n "__fish_seen_subcommand_from cli; and __fish_seen_subcomm
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l width -d 'Specify the display width; defaults to "auto" which automatically selects an appropriate size. You may also use an integer value `N` to specify the number of cells, or `Npx` to specify the number of pixels, or `N%` to size relative to the terminal width' -r
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l height -d 'Specify the display height; defaults to "auto" which automatically selects an appropriate size. You may also use an integer value `N` to specify the number of cells, or `Npx` to specify the number of pixels, or `N%` to size relative to the terminal height' -r
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l position -d 'Set the cursor position prior to displaying the image. The default is to use the current cursor position. Coordinates are expressed in cells with 0,0 being the top left cell position' -r
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l tmux-passthru -d 'How to manage passing the escape through to tmux' -r -f -a "{disable ,enable ,detect }"
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l tmux-passthru -d 'How to manage passing the escape through to tmux' -r -f -a "{disable '',enable '',detect ''}"
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l max-pixels -d 'Set the maximum number of pixels per image frame. Images will be scaled down so that they do not exceed this size, unless `--no-resample` is also used. The default value matches the limit set by wezterm. Note that resampling the image here will reduce any animated images to a single frame' -r
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l resample-format -d 'Specify the image format to use to encode resampled/resized images. The default is to match the input format, but you can choose an alternative format' -r -f -a "{png ,jpeg ,input }"
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l resample-filter -d 'Specify the filtering technique used when resizing/resampling images. The default is a reasonable middle ground of speed and quality' -r -f -a "{nearest ,triangle ,catmull-rom ,gaussian ,lanczos3 }"
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l resample-format -d 'Specify the image format to use to encode resampled/resized images. The default is to match the input format, but you can choose an alternative format' -r -f -a "{png '',jpeg '',input ''}"
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l resample-filter -d 'Specify the filtering technique used when resizing/resampling images. The default is a reasonable middle ground of speed and quality' -r -f -a "{nearest '',triangle '',catmull-rom '',gaussian '',lanczos3 ''}"
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l resize -d 'Pre-process the image to resize it to the specified dimensions, expressed as eg: 800x600 (width x height). The resize is independent of other parameters that control the image placement and dimensions in the terminal; this is provided as a convenience preprocessing step' -r
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l no-preserve-aspect-ratio -d 'Do not respect the aspect ratio. The default is to respect the aspect ratio'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l no-move-cursor -d 'Do not move the cursor after displaying the image. Note that when used like this from the shell, there is a very high chance that shell prompt will overwrite the image; you may wish to also use `--hold` in that case'
|
||||
@ -179,14 +179,15 @@ complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l hold -d 'Wait for
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l no-resample -d 'Do not resample images whose frames are larger than the max-pixels value. Note that this will typically result in the image refusing to display in wezterm'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -l show-resample-timing -d 'When resampling or resizing, display some diagnostics around the timing/performance of that operation'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from imgcat" -s h -l help -d 'Print help (see more with \'--help\')'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from set-working-directory" -l tmux-passthru -d 'How to manage passing the escape through to tmux' -r -f -a "{disable ,enable ,detect }"
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from set-working-directory" -l tmux-passthru -d 'How to manage passing the escape through to tmux' -r -f -a "{disable '',enable '',detect ''}"
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from set-working-directory" -s h -l help -d 'Print help'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from record" -l cwd -d 'Start in the specified directory, instead of the default_cwd defined by your wezterm configuration' -r -F
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from record" -s h -l help -d 'Print help'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from replay" -l explain -d 'Explain what is being sent/received'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from replay" -l explain-only -d 'Don\'t replay, just show the explanation'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from replay" -l cat -d 'Just emit raw escape sequences all at once, with no timing information'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from replay" -s h -l help -d 'Print help'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from shell-completion" -l shell -d 'Which shell to generate for' -r -f -a "{bash ,elvish ,fish ,power-shell ,zsh ,fig }"
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from shell-completion" -l shell -d 'Which shell to generate for' -r -f -a "{bash '',elvish '',fish '',power-shell '',zsh '',fig ''}"
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from shell-completion" -s h -l help -d 'Print help'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from start; and not __fish_seen_subcommand_from ssh; and not __fish_seen_subcommand_from serial; and not __fish_seen_subcommand_from connect; and not __fish_seen_subcommand_from ls-fonts; and not __fish_seen_subcommand_from show-keys; and not __fish_seen_subcommand_from cli; and not __fish_seen_subcommand_from imgcat; and not __fish_seen_subcommand_from set-working-directory; and not __fish_seen_subcommand_from record; and not __fish_seen_subcommand_from replay; and not __fish_seen_subcommand_from shell-completion; and not __fish_seen_subcommand_from help" -f -a "start" -d 'Start the GUI, optionally running an alternative program'
|
||||
complete -c wezterm -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from start; and not __fish_seen_subcommand_from ssh; and not __fish_seen_subcommand_from serial; and not __fish_seen_subcommand_from connect; and not __fish_seen_subcommand_from ls-fonts; and not __fish_seen_subcommand_from show-keys; and not __fish_seen_subcommand_from cli; and not __fish_seen_subcommand_from imgcat; and not __fish_seen_subcommand_from set-working-directory; and not __fish_seen_subcommand_from record; and not __fish_seen_subcommand_from replay; and not __fish_seen_subcommand_from shell-completion; and not __fish_seen_subcommand_from help" -f -a "ssh" -d 'Establish an ssh session'
|
||||
|
@ -422,9 +422,10 @@ _arguments "${_arguments_options[@]}" \
|
||||
;;
|
||||
(record)
|
||||
_arguments "${_arguments_options[@]}" \
|
||||
'--cwd=[Start in the specified directory, instead of the default_cwd defined by your wezterm configuration]:CWD:_files' \
|
||||
'-h[Print help]' \
|
||||
'--help[Print help]' \
|
||||
'*::prog:' \
|
||||
'*::prog -- Start prog instead of the default_prog defined by your wezterm configuration:' \
|
||||
&& ret=0
|
||||
;;
|
||||
(replay)
|
||||
|
16
ci/copr-build.sh
Executable file
16
ci/copr-build.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
set -x
|
||||
set -e
|
||||
|
||||
|
||||
command -v git || dnf install -y git
|
||||
|
||||
git config --global --add safe.directory $PWD
|
||||
git config --global --add safe.directory $PWD/deps/freetype/freetype2
|
||||
git config --global --add safe.directory $PWD/deps/freetype/libpng
|
||||
git config --global --add safe.directory $PWD/deps/freetype/zlib
|
||||
git config --global --add safe.directory $PWD/deps/harfbuzz/harfbuzz
|
||||
|
||||
./ci/source-archive.sh
|
||||
./ci/deploy.sh
|
||||
|
75
ci/deploy.sh
75
ci/deploy.sh
@ -134,10 +134,16 @@ case $OSTYPE in
|
||||
WEZTERM_RPM_VERSION=$(echo ${TAG_NAME#nightly-} | tr - _)
|
||||
distroid=$(sh -c "source /etc/os-release && echo \$ID" | tr - _)
|
||||
distver=$(sh -c "source /etc/os-release && echo \$VERSION_ID" | tr - _)
|
||||
|
||||
SPEC_RELEASE="1.${distroid}${distver}"
|
||||
if test -n "${COPR_SRPM}" ; then
|
||||
SPEC_RELEASE=0
|
||||
fi
|
||||
|
||||
cat > wezterm.spec <<EOF
|
||||
Name: wezterm
|
||||
Version: ${WEZTERM_RPM_VERSION}
|
||||
Release: 1.${distroid}${distver}
|
||||
Release: ${SPEC_RELEASE}
|
||||
Packager: Wez Furlong <wez@wezfurlong.org>
|
||||
License: MIT
|
||||
URL: https://wezfurlong.org/wezterm/
|
||||
@ -147,14 +153,60 @@ Requires: dbus-1, fontconfig, openssl, libxcb1, libxkbcommon0, libxkbcommon-x11-
|
||||
%else
|
||||
Requires: dbus, fontconfig, openssl, libxcb, libxkbcommon, libxkbcommon-x11, libwayland-client, libwayland-egl, libwayland-cursor, mesa-libEGL, xcb-util-keysyms, xcb-util-wm
|
||||
%endif
|
||||
EOF
|
||||
|
||||
BUILD_COMMAND=<<EOF
|
||||
%build
|
||||
echo build
|
||||
EOF
|
||||
|
||||
if test -n "${COPR_SRPM}" ; then
|
||||
|
||||
TAR_NAME=$(git -c "core.abbrev=8" show -s "--format=%cd_%h" "--date=format:%Y%m%d_%H%M%S")
|
||||
|
||||
cat >> wezterm.spec <<EOF
|
||||
BuildRequires: gcc, gcc-c++, make, curl, fontconfig-devel, openssl-devel, libxcb-devel, libxkbcommon-devel, libxkbcommon-x11-devel, wayland-devel, xcb-util-devel, xcb-util-keysyms-devel, xcb-util-image-devel, xcb-util-wm-devel, git
|
||||
%if 0%{?suse_version}
|
||||
BuildRequires: Mesa-libEGL-devel
|
||||
%else
|
||||
BuildRequires: mesa-libEGL-devel
|
||||
%endif
|
||||
Source0: wezterm-${TAR_NAME}.tar.gz
|
||||
|
||||
%global debug_package %{nil}
|
||||
|
||||
%changelog
|
||||
* Mon Oct 2 2023 Wez Furlong
|
||||
- See git for full changelog
|
||||
|
||||
EOF
|
||||
HERE="."
|
||||
BUILD_COMMAND=$(cat <<EOF
|
||||
%prep
|
||||
%autosetup
|
||||
%build
|
||||
|
||||
echo Here I am
|
||||
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
source ~/.cargo/env
|
||||
|
||||
cargo build --release \
|
||||
-p wezterm-gui -p wezterm -p wezterm-mux-server \
|
||||
-p strip-ansi-escapes
|
||||
|
||||
EOF
|
||||
)
|
||||
|
||||
fi
|
||||
|
||||
cat >> wezterm.spec <<EOF
|
||||
%description
|
||||
wezterm is a terminal emulator with support for modern features
|
||||
such as fonts with ligatures, hyperlinks, tabs and multiple
|
||||
windows.
|
||||
|
||||
%build
|
||||
echo "Doing the build bit here"
|
||||
${BUILD_COMMAND}
|
||||
|
||||
%install
|
||||
set -x
|
||||
@ -188,7 +240,12 @@ install -Dm644 assets/wezterm-nautilus.py %{buildroot}/usr/share/nautilus-python
|
||||
/etc/profile.d/*
|
||||
EOF
|
||||
|
||||
/usr/bin/rpmbuild -bb --rmspec wezterm.spec --verbose
|
||||
if test -n "${COPR_SRPM}" ; then
|
||||
/usr/bin/rpmbuild -bs --rmspec wezterm.spec --verbose
|
||||
mv $(rpm --eval '%{_srcrpmdir}')/wezterm-${TAR_NAME}*.src.rpm "${COPR_SRPM}"/
|
||||
else
|
||||
/usr/bin/rpmbuild -bb --rmspec wezterm.spec --verbose
|
||||
fi
|
||||
|
||||
;;
|
||||
Ubuntu*|Debian*)
|
||||
@ -249,11 +306,21 @@ EOF
|
||||
install -Dm644 assets/shell-completion/bash pkg/debian/usr/share/bash-completion/completions/wezterm
|
||||
install -Dm644 assets/shell-completion/zsh pkg/debian/usr/share/zsh/functions/Completion/Unix/_wezterm
|
||||
install -Dm644 assets/shell-integration/* -t pkg/debian/etc/profile.d
|
||||
|
||||
if [[ "$BUILD_REASON" == "Schedule" ]] ; then
|
||||
debname=wezterm-nightly.$distro$distver
|
||||
else
|
||||
debname=wezterm-$TAG_NAME.$distro$distver
|
||||
fi
|
||||
arch=$(dpkg-architecture -q DEB_BUILD_ARCH_CPU)
|
||||
case $arch in
|
||||
amd64)
|
||||
;;
|
||||
*)
|
||||
debname="${debname}.${arch}"
|
||||
;;
|
||||
esac
|
||||
|
||||
fakeroot dpkg-deb --build pkg/debian $debname.deb
|
||||
|
||||
if [[ "$BUILD_REASON" != '' ]] ; then
|
||||
|
@ -946,15 +946,10 @@ TARGETS = [
|
||||
Target(name="centos9", container="quay.io/centos/centos:stream9"),
|
||||
Target(name="macos", os="macos-11"),
|
||||
# https://fedoraproject.org/wiki/End_of_life?rd=LifeCycle/EOL
|
||||
Target(container="fedora:36"),
|
||||
Target(container="fedora:37"),
|
||||
Target(container="fedora:38"),
|
||||
Target(container="fedora:39"),
|
||||
# Target(container="alpine:3.15"),
|
||||
Target(name="opensuse_leap", container="registry.opensuse.org/opensuse/leap:15.4"),
|
||||
Target(
|
||||
name="opensuse_tumbleweed",
|
||||
container="registry.opensuse.org/opensuse/tumbleweed",
|
||||
),
|
||||
Target(name="windows", os="windows-latest", rust_target="x86_64-pc-windows-msvc"),
|
||||
]
|
||||
|
||||
|
@ -11,6 +11,11 @@ else
|
||||
TAR_NAME=wezterm-${TAG_NAME}-src.tar
|
||||
fi
|
||||
|
||||
if test -n "${COPR_SRPM}" ; then
|
||||
TAG_NAME=$(git -c "core.abbrev=8" show -s "--format=%cd_%h" "--date=format:%Y%m%d_%H%M%S")
|
||||
TAR_NAME=wezterm-${TAG_NAME}.tar
|
||||
fi
|
||||
|
||||
rm -f ${TAR_NAME}*
|
||||
|
||||
NAME_PREFIX=wezterm-${TAG_NAME}
|
||||
@ -47,3 +52,6 @@ tar --delete \
|
||||
|
||||
gzip ${TAR_NAME}
|
||||
|
||||
if test -n "${COPR_SRPM}" ; then
|
||||
mv ${TAR_NAME}.gz $(rpm --eval '%{_sourcedir}')
|
||||
fi
|
||||
|
@ -13,6 +13,8 @@ CATEGORIZE = {
|
||||
r"Debian(\d+)(\.\d+)?\.deb$": "debian\\1_deb",
|
||||
r"Ubuntu(\d+)(\.\d+)?.AppImage$": "ubuntu\\1_AppImage",
|
||||
r"Ubuntu(\d+)(\.\d+)?.deb$": "ubuntu\\1_deb",
|
||||
r"Ubuntu(\d+)(\.\d+)?\.arm64\.deb$": "ubuntu\\1_arm64_deb",
|
||||
r"Debian(\d+)(\.\d+)?\.arm64\.deb$": "debian\\1_arm64_deb",
|
||||
r"Ubuntu20.04.tar.xz$": "linux_raw_bin",
|
||||
r"^wezterm-\d+-\d+-[a-f0-9]+.tar.xz$": "linux_raw_bin",
|
||||
r"src.tar.gz$": "src",
|
||||
|
@ -27,7 +27,7 @@ mlua = {version="0.9", features=["vendored", "lua54", "async", "send"]}
|
||||
# file change notification
|
||||
notify = "5.0.0"
|
||||
once_cell = "1.8"
|
||||
ordered-float = { version = "3.0", features = ["serde"] }
|
||||
ordered-float = { version = "4.1", features = ["serde"] }
|
||||
portable-pty = { path = "../pty", features = ["serde_support"]}
|
||||
promise = { path = "../promise" }
|
||||
serde = {version="1.0", features = ["rc", "derive"]}
|
||||
@ -35,7 +35,7 @@ serde_json = "1.0"
|
||||
shlex = "1.1"
|
||||
smol = "1.2"
|
||||
termwiz = { path = "../termwiz", features=["use_serde"] }
|
||||
toml = "0.7"
|
||||
toml = "0.8"
|
||||
umask = { path = "../umask" }
|
||||
wezterm-config-derive = { version="0.1", path="derive" }
|
||||
wezterm-dynamic = { path = "../wezterm-dynamic" }
|
||||
|
@ -148,6 +148,7 @@ pub struct Config {
|
||||
#[dynamic(default = "default_command_palette_font_size")]
|
||||
pub command_palette_font_size: f64,
|
||||
|
||||
pub command_palette_rows: Option<usize>,
|
||||
#[dynamic(default = "default_command_palette_fg_color")]
|
||||
pub command_palette_fg_color: RgbaColor,
|
||||
|
||||
@ -661,6 +662,9 @@ pub struct Config {
|
||||
#[dynamic(default)]
|
||||
pub ime_preedit_rendering: ImePreeditRendering,
|
||||
|
||||
#[dynamic(default)]
|
||||
pub notification_handling: NotificationHandling,
|
||||
|
||||
#[dynamic(default = "default_true")]
|
||||
pub use_dead_keys: bool,
|
||||
|
||||
@ -2008,6 +2012,16 @@ pub enum ImePreeditRendering {
|
||||
System,
|
||||
}
|
||||
|
||||
#[derive(Debug, FromDynamic, ToDynamic, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub enum NotificationHandling {
|
||||
#[default]
|
||||
AlwaysShow,
|
||||
NeverShow,
|
||||
SuppressFromFocusedPane,
|
||||
SuppressFromFocusedTab,
|
||||
SuppressFromFocusedWindow,
|
||||
}
|
||||
|
||||
fn validate_row_or_col(value: &u16) -> Result<(), String> {
|
||||
if *value < 1 {
|
||||
Err("initial_cols and initial_rows must be non-zero".to_string())
|
||||
|
@ -477,6 +477,27 @@ pub struct InputSelector {
|
||||
|
||||
#[dynamic(default)]
|
||||
pub fuzzy: bool,
|
||||
|
||||
#[dynamic(default = "default_num_alphabet")]
|
||||
pub alphabet: String,
|
||||
|
||||
#[dynamic(default = "default_description")]
|
||||
pub description: String,
|
||||
|
||||
#[dynamic(default = "default_fuzzy_description")]
|
||||
pub fuzzy_description: String,
|
||||
}
|
||||
|
||||
fn default_num_alphabet() -> String {
|
||||
"1234567890abcdefghilmnopqrstuvwxyz".to_string()
|
||||
}
|
||||
|
||||
fn default_description() -> String {
|
||||
"Select an item and press Enter = accept, Esc = cancel, / = filter".to_string()
|
||||
}
|
||||
|
||||
fn default_fuzzy_description() -> String {
|
||||
"Fuzzy matching: ".to_string()
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, FromDynamic, ToDynamic)]
|
||||
|
File diff suppressed because it is too large
Load Diff
2
deps/harfbuzz/harfbuzz
vendored
2
deps/harfbuzz/harfbuzz
vendored
@ -1 +1 @@
|
||||
Subproject commit 1d665c2b521512cdd56964138fc601debd1f1177
|
||||
Subproject commit 894a1f72ee93a1fd8dc1d9218cb3fd8f048be29a
|
27
deps/harfbuzz/src/lib.rs
vendored
27
deps/harfbuzz/src/lib.rs
vendored
@ -1,4 +1,4 @@
|
||||
/* automatically generated by rust-bindgen 0.65.1 */
|
||||
/* automatically generated by rust-bindgen 0.66.1 */
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_camel_case_types)]
|
||||
@ -1303,6 +1303,15 @@ pub type hb_paint_pop_transform_func_t = ::std::option::Option<
|
||||
user_data: *mut ::std::os::raw::c_void,
|
||||
),
|
||||
>;
|
||||
pub type hb_paint_color_glyph_func_t = ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
funcs: *mut hb_paint_funcs_t,
|
||||
paint_data: *mut ::std::os::raw::c_void,
|
||||
glyph: hb_codepoint_t,
|
||||
font: *mut hb_font_t,
|
||||
user_data: *mut ::std::os::raw::c_void,
|
||||
) -> hb_bool_t,
|
||||
>;
|
||||
pub type hb_paint_push_clip_glyph_func_t = ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
funcs: *mut hb_paint_funcs_t,
|
||||
@ -1523,6 +1532,14 @@ extern "C" {
|
||||
destroy: hb_destroy_func_t,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn hb_paint_funcs_set_color_glyph_func(
|
||||
funcs: *mut hb_paint_funcs_t,
|
||||
func: hb_paint_color_glyph_func_t,
|
||||
user_data: *mut ::std::os::raw::c_void,
|
||||
destroy: hb_destroy_func_t,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn hb_paint_funcs_set_push_clip_glyph_func(
|
||||
funcs: *mut hb_paint_funcs_t,
|
||||
@ -1629,6 +1646,14 @@ extern "C" {
|
||||
paint_data: *mut ::std::os::raw::c_void,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn hb_paint_color_glyph(
|
||||
funcs: *mut hb_paint_funcs_t,
|
||||
paint_data: *mut ::std::os::raw::c_void,
|
||||
glyph: hb_codepoint_t,
|
||||
font: *mut hb_font_t,
|
||||
) -> hb_bool_t;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn hb_paint_push_clip_glyph(
|
||||
funcs: *mut hb_paint_funcs_t,
|
||||
|
@ -61,7 +61,8 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
In addition, there are now a number of options for explicitly resizing
|
||||
as a preprocessing step, and controlling the filtering and format used
|
||||
by the resizing, along with showing diagnostics around the resize operation. #3264
|
||||
* Color schemes: [Ef-Cyprus](colorschemes/e/index.md#ef-cyprus),
|
||||
* Color schemes: [Campbell (Gogh)](colorschemes/c/index.md#campbell-gogh),
|
||||
[Ef-Cyprus](colorschemes/e/index.md#ef-cyprus),
|
||||
[Ef-Day](colorschemes/e/index.md#ef-day),
|
||||
[Ef-Deuteranopia-Dark](colorschemes/e/index.md#ef-deuteranopia-dark),
|
||||
[Ef-Deuteranopia-Light](colorschemes/e/index.md#ef-deuteranopia-light),
|
||||
@ -72,13 +73,36 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
[Ef-Frost](colorschemes/e/index.md#ef-frost),
|
||||
[Ef-Kassio](colorschemes/e/index.md#ef-kassio),
|
||||
[Ef-Light](colorschemes/e/index.md#ef-light),
|
||||
[Ef-Maris-Dark](colorschemes/e/index.md#ef-maris-dark),
|
||||
[Ef-Maris-Light](colorschemes/e/index.md#ef-maris-light),
|
||||
[Ef-Night](colorschemes/e/index.md#ef-night),
|
||||
[Ef-Symbiosis](colorschemes/e/index.md#ef-symbiosis),
|
||||
[iTerm2 Dark Background](colorschemes/i/index.md#iterm2-dark-background),
|
||||
[iTerm2 Default](colorschemes/i/index.md#iterm2-default),
|
||||
[iTerm2 Light Background](colorschemes/i/index.md#iterm2-light-background),
|
||||
[iTerm2 Pastel Dark Background](colorschemes/i/index.md#iterm2-pastel-dark-background),
|
||||
[iTerm2 Smoooooth](colorschemes/i/index.md#iterm2-smoooooth),
|
||||
[iTerm2 Tango Dark](colorschemes/i/index.md#iterm2-tango-dark),
|
||||
[iTerm2 Tango Light](colorschemes/i/index.md#iterm2-tango-light),
|
||||
[Modus-Operandi-Deuteranopia](colorschemes/m/index.md#modus-operandi-deuteranopia),
|
||||
[Modus-Operandi-Tinted](colorschemes/m/index.md#modus-operandi-tinted),
|
||||
[Modus-Vivendi-Deuteranopia](colorschemes/m/index.md#modus-vivendi-deuteranopia),
|
||||
[Modus-Vivendi-Tinted](colorschemes/m/index.md#modus-vivendi-tinted),
|
||||
[Modus-Vivendi-Tritanopia](colorschemes/m/index.md#modus-vivendi-tritanopia),
|
||||
[Oxocarbon Dark (Gogh)](colorschemes/o/index.md#oxocarbon-dark-gogh),
|
||||
[Rosé Pine Moon (base16)](colorschemes/r/index.md#rosé-pine-moon-base16)
|
||||
* Preliminary support for rasterizing fonts with COLR v1 glyphs, such as
|
||||
more recent versions of Noto Color Emoji. #4148
|
||||
* [wezterm cli zoom-pane](cli/cli/zoom-pane.md). Thanks to @quantonganh! #4160
|
||||
* [InputSelector](config/lua/keyassignment/InputSelector.md) has been
|
||||
enhanced to allow setting an alphabet for quickly launching items beyond
|
||||
the first 10 items, as well as customizing the description/label text.
|
||||
Thanks to @Danielkonge! #4226 #4227
|
||||
* [notification_handling](config/lua/config/notification_handling.md) to
|
||||
control whether notifications are suppressed based on focus. #3727
|
||||
* [command_palette_rows](config/lua/config/command_palette_rows.md) to
|
||||
control how many rows are displayed in the command palette. Thanks to
|
||||
@exastone! #4595
|
||||
|
||||
#### Fixed
|
||||
* Command Palette was using now-invalid Nerd Font 2.0 symbols for macOS
|
||||
@ -94,11 +118,30 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
than the native font dimensions and looked weird when either config option was
|
||||
not set to `1.0`. #2882
|
||||
* Using `CloseCurrentPane` could sometimes leave a stranded pane in a tab. #4030
|
||||
* Wayland: wezterm wouldn't start on Plasma 6 or newer versions of sway. Thanks
|
||||
to @hexchain! #3996 #4322.
|
||||
* font-config: when resolving a fallback font for a text cluster like `U+3065,U+2686`
|
||||
where no single font contains both glyphs, wezterm would fail to show a glyph
|
||||
for either codepoint. We now split the fallback query up and query for each
|
||||
individual codepoint separately. #4310
|
||||
* Gogh color schemes all had the incorrect cursor foreground color. #4257
|
||||
* Windows: crash on Windows 11 when using DX 12 with the WebGpu frontend. #4279
|
||||
* macOS: Leak of NSWindow and NSView objects. Thanks to @0f-0b! #4457
|
||||
* Initial G1 state is non-conformant. Thanks to @ninjalj! #4534 #3962
|
||||
* Make RIS also clear the alternate screen. Thanks to @ninjalj! #4563
|
||||
* DECRQCRA: treat uninitialized cells as spaces. Thanks to @ninjalj! #4565
|
||||
* Clamp cursor position reported by CPR. Thanks to @ninjalj! #4564
|
||||
* Correct `SUPER` modifier key handling in kitty protocol. Thanks to @gabyx! #4605
|
||||
* macOS: honor the `window_close_confirmation` config option when quitting the
|
||||
application. Thanks to @quantonganh! #4420 #4362
|
||||
* terminfo: added missing terminator to Sync capability. Thanks to @gpanders! #4578
|
||||
|
||||
#### Updated
|
||||
* Bundled harfbuzz to 8.1.1
|
||||
* Bundled harfbuzz to 8.3.0
|
||||
* Bundled freetype to 2.13.1
|
||||
* Bundled Noto Color Emoji font to 2.038
|
||||
* wgpu to 0.18, which [improves OpenGL compatibility with older GPUs when using
|
||||
WebGpu with its GL backend on Windows](https://github.com/gfx-rs/wgpu/releases/tag/v0.18.0)
|
||||
|
||||
### 20230712-072601-f4abf8fd
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -263,7 +263,7 @@ $ for scheme in *.sh ; do ; echo $scheme ; \
|
||||
### Tab Bar Appearance & Colors
|
||||
|
||||
The tab bar has two modes; the default is a native looking style, but
|
||||
is is also possible to enable a retro aesthetic. The configuration
|
||||
it is also possible to enable a retro aesthetic. The configuration
|
||||
for the two styles is broadly similar, but there are a few different
|
||||
details.
|
||||
|
||||
|
12
docs/config/lua/config/command_palette_rows.md
Normal file
12
docs/config/lua/config/command_palette_rows.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
tags:
|
||||
- appearance
|
||||
- command_palette
|
||||
---
|
||||
# `command_palette_rows = 14`
|
||||
|
||||
{{since('nightly')}}
|
||||
|
||||
Specifies the number of rows displayed by the command palette.
|
||||
[ActivateCommandPalette](../keyassignment/ActivateCommandPalette.md).
|
||||
If unset or `nil`, a default value based on the terminal display will be used.
|
@ -2,15 +2,12 @@
|
||||
tags:
|
||||
- font
|
||||
---
|
||||
# `font_size = 10.0`
|
||||
# `font_size = 12.0`
|
||||
|
||||
Specifies the size of the font, measured in points.
|
||||
|
||||
You may use fractional point sizes, such as `13.3`, to fine tune the size.
|
||||
|
||||
The default font size is `10.0` points.
|
||||
|
||||
{{since('20210314-114017-04b7cedd')}}
|
||||
|
||||
The default font size is now `12.0` points.
|
||||
The default font size is `12.0` points. In earlier versions prior to
|
||||
`20210314-114017-04b7cedd` it was `10.0`.
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
tags:
|
||||
- appearance
|
||||
---
|
||||
# `integrated_title_button_style = BUTTONS`
|
||||
# `integrated_title_buttons = BUTTONS`
|
||||
|
||||
{{since('20230408-112425-69ae8472')}}
|
||||
|
||||
|
@ -16,4 +16,4 @@ The value can be a number to specify the number of pixels, or a string with a un
|
||||
* `"1cell"` - the `cell` suffix indicates the height of the terminal cell, which in turn depends on the font size, font scaling and dpi.
|
||||
* `"1%"` - the `%` suffix indicates the size of the terminal portion of the display, which is computed based on the number of rows and the size of the cell.
|
||||
|
||||
You may use a fractional number such as `"0.5cell"` or numbers large than one such as `"72pt"`.
|
||||
You may use a fractional number such as `"0.5cell"` or numbers larger than one such as `"72pt"`.
|
||||
|
30
docs/config/lua/config/notification_handling.md
Normal file
30
docs/config/lua/config/notification_handling.md
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
tags:
|
||||
- notifications
|
||||
---
|
||||
|
||||
# `notification_handling = "AlwaysShow"`
|
||||
|
||||
{{since('nightly')}}
|
||||
|
||||
This option controls how wezterm behaves when a toast notification escape
|
||||
sequence is received.
|
||||
|
||||
The following escape sequences will generate a toast notification:
|
||||
|
||||
```console
|
||||
$ printf "\e]777;notify;%s;%s\e\\" "title" "body"
|
||||
```
|
||||
|
||||
```console
|
||||
$ printf "\e]9;%s\e\\" "hello there"
|
||||
```
|
||||
|
||||
This configuration option can have one of the following values,
|
||||
which have the following effects:
|
||||
|
||||
* `AlwaysShow` - Show the notification regardless of the current focus
|
||||
* `NeverShow` - Never show the notification
|
||||
* `SuppressFromFocusedPane` - Show the notification unless it was generated from the currently focused pane
|
||||
* `SuppressFromFocusedTab` - Show the notification unless it was generated from the currently focused tab
|
||||
* `SuppressFromFocusedWindow` - Show the notification unless it was generated from the currently focused window
|
@ -33,7 +33,7 @@ a string value with a unit suffix:
|
||||
* `"1cell"` - the `cell` suffix indicates the size of the terminal cell, which in turn depends on the font size, font scaling and dpi. When used for width, the width of the cell is used. When used for height, the height of the cell is used.
|
||||
* `"1%"` - the `%` suffix indicates the size of the terminal portion of the display, which is computed based on the number of rows/columns and the size of the cell. While it is possible to specify percentage, there are some resize scenarios where the percentage value may not be 100% stable/deterministic, as the size of the padding is used to compute the number of rows/columns.
|
||||
|
||||
You may use a fractional number such as `"0.5cell"` or numbers large than one such as `"72pt"`.
|
||||
You may use a fractional number such as `"0.5cell"` or numbers larger than one such as `"72pt"`.
|
||||
|
||||
The default padding is shown below. In earlier releases, the default padding was 0 for each of the possible edges.
|
||||
|
||||
|
@ -40,6 +40,7 @@ Activating the selected item will close the command palette and then invoke the
|
||||
action.
|
||||
|
||||
See also:
|
||||
* [command_palette_font_size](../config/command_palette_font_size.md)
|
||||
* [command_palette_fg_color](../config/command_palette_fg_color.md)
|
||||
* [command_palette_bg_color](../config/command_palette_bg_color.md)
|
||||
|
||||
* [command_palette_font_size](../config/command_palette_font_size.md)
|
||||
* [command_palette_fg_color](../config/command_palette_fg_color.md)
|
||||
* [command_palette_bg_color](../config/command_palette_bg_color.md)
|
||||
|
@ -8,7 +8,7 @@ to select from.
|
||||
When the user accepts a line, emits an event that allows you to act
|
||||
upon the input.
|
||||
|
||||
`InputSelector` accepts three fields:
|
||||
`InputSelector` accepts the following fields:
|
||||
|
||||
* `title` - the title that will be set for the overlay pane
|
||||
* `choices` - a lua table consisting of the potential choices. Each entry
|
||||
@ -22,6 +22,51 @@ upon the input.
|
||||
objects from the current pane and window, and `id` and `label` hold the
|
||||
corresponding fields from the selected choice. Both will be `nil` if
|
||||
the overlay is cancelled without selecting anything.
|
||||
* `fuzzy` - a boolean that defaults to `false`. If `true`, InputSelector will start
|
||||
in its fuzzy finding mode (this is equivalent to starting the InputSelector and
|
||||
pressing / in the default mode).
|
||||
|
||||
{{since('nightly')}}
|
||||
|
||||
These additional fields are also available:
|
||||
|
||||
* `alphabet` - a string of unique characters. The characters in the string are used
|
||||
to calculate one or two click shortcuts that can be used to quickly choose from
|
||||
the InputSelector when in the default mode. Defaults to:
|
||||
`"1234567890abcdefghilmnopqrstuvwxyz"`. (Without j/k so they can be used for movement
|
||||
up and down.)
|
||||
* `description` - a string to display when in the default mode. Defaults to:
|
||||
`"Select an item and press Enter = accept, Esc = cancel, / = filter"`.
|
||||
* `fuzzy_description` - a string to display when in fuzzy finding mode. Defaults to:
|
||||
`"Fuzzy matching: "`.
|
||||
|
||||
|
||||
### Key Assignments
|
||||
|
||||
The default key assignments in the InputSelector are as follows:
|
||||
|
||||
| Action | Key Assignment |
|
||||
|---------|-------------------|
|
||||
| Add to selection string until a match is found (if in the default mode) | Any key in `alphabet` {{since('nightly', inline=True)}} |
|
||||
| Select matching number (if in the default mode) | <kbd>1</kbd> to <kbd>9</kbd> {{since('20230408-112425-69ae8472', inline=True)}} |
|
||||
| Start fuzzy search (if in the default mode) | <kbd>/</kbd> |
|
||||
| Add to filtering string (if in fuzzy finding mode) | Any key not listed below |
|
||||
| Remove from selection or filtering string | <kbd>Backspace</kbd> |
|
||||
| Pick currently highlighted line | <kbd>Enter</kbd> |
|
||||
| | <kbd>LeftClick</kbd> (with mouse) |
|
||||
| Move Down | <kbd>DownArrow</kbd> |
|
||||
| | <kbd>Ctrl</kbd> + <kbd>N</kbd> |
|
||||
| | <kbd>Ctrl</kbd> + <kbd>J</kbd> {{since('nightly', inline=True)}} |
|
||||
| | <kbd>j</kbd> (if not in `alphabet`) |
|
||||
| Move Up | <kbd>UpArrow</kbd> |
|
||||
| | <kbd>Ctrl</kbd> + <kbd>P</kbd> |
|
||||
| | <kbd>Ctrl</kbd> + <kbd>K</kbd> {{since('nightly', inline=True)}} |
|
||||
| | <kbd>k</kbd> (if not in `alphabet`) |
|
||||
| Quit | <kbd>Ctrl</kbd> + <kbd>G</kbd> |
|
||||
| | <kbd>Ctrl</kbd> + <kbd>C</kbd> {{since('nightly', inline=True)}} |
|
||||
| | <kbd>Escape</kbd> |
|
||||
|
||||
Note: If the InputSelector is started with `fuzzy` set to `false`, then <kbd>Backspace</kbd> can go from fuzzy finding mode back to the default mode when pressed while the filtering string is empty.
|
||||
|
||||
## Example of choosing some canned text to enter into the terminal
|
||||
|
||||
@ -95,7 +140,7 @@ config.keys = {
|
||||
-- could read or compute data from other sources
|
||||
|
||||
local choices = {}
|
||||
for n = 1, 10 do
|
||||
for n = 1, 20 do
|
||||
table.insert(choices, { label = tostring(n) })
|
||||
end
|
||||
|
||||
@ -113,6 +158,8 @@ config.keys = {
|
||||
end),
|
||||
title = 'I am title',
|
||||
choices = choices,
|
||||
alphabet = '123456789',
|
||||
description = 'Write the number you want to choose or press / to search.',
|
||||
},
|
||||
pane
|
||||
)
|
||||
@ -123,5 +170,66 @@ config.keys = {
|
||||
return config
|
||||
```
|
||||
|
||||
## Example of switching between a list of workspaces with the InputSelector
|
||||
|
||||
```lua
|
||||
local wezterm = require 'wezterm'
|
||||
local act = wezterm.action
|
||||
local config = wezterm.config_builder()
|
||||
|
||||
config.keys = {
|
||||
{
|
||||
key = 'S',
|
||||
mods = 'CTRL|SHIFT',
|
||||
action = wezterm.action_callback(function(window, pane)
|
||||
-- Here you can dynamically construct a longer list if needed
|
||||
|
||||
local home = wezterm.home_dir
|
||||
local workspaces = {
|
||||
{ id = home, label = 'Home' },
|
||||
{ id = home .. '/work', label = 'Work' },
|
||||
{ id = home .. '/personal', label = 'Personal' },
|
||||
{ id = home .. '/.config', label = 'Config' },
|
||||
}
|
||||
|
||||
window:perform_action(
|
||||
act.InputSelector {
|
||||
action = wezterm.action_callback(
|
||||
function(inner_window, inner_pane, id, label)
|
||||
if not id and not label then
|
||||
wezterm.log_info 'cancelled'
|
||||
else
|
||||
wezterm.log_info('id = ' .. id)
|
||||
wezterm.log_info('label = ' .. label)
|
||||
inner_window:perform_action(
|
||||
act.SwitchToWorkspace {
|
||||
name = label,
|
||||
spawn = {
|
||||
label = 'Workspace: ' .. label,
|
||||
cwd = id,
|
||||
},
|
||||
},
|
||||
inner_pane
|
||||
)
|
||||
end
|
||||
end
|
||||
),
|
||||
title = 'Choose Workspace',
|
||||
choices = workspaces,
|
||||
fuzzy = true,
|
||||
fuzzy_description = 'Fuzzy find and/or make a workspace',
|
||||
},
|
||||
pane
|
||||
)
|
||||
end),
|
||||
},
|
||||
}
|
||||
|
||||
return config
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
See also [PromptInputLine](PromptInputLine.md).
|
||||
|
||||
|
32
docs/config/lua/wezterm/to_string.md
Normal file
32
docs/config/lua/wezterm/to_string.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
title: wezterm.to_string
|
||||
tags:
|
||||
- utility
|
||||
---
|
||||
# `wezterm.to_string(arg)`
|
||||
|
||||
{{since('nightly')}}
|
||||
|
||||
This function returns a string representation of any Lua value. In particular
|
||||
this can be used to get a string representation of a table or userdata.
|
||||
|
||||
The intended purpose is as a human readable way to inspect lua values. It is not machine
|
||||
readable; do not attempt to use it as a serialization format as the format is not guaranteed
|
||||
to remain the same across different versions of wezterm.
|
||||
|
||||
This same representation is used in the [debug overlay](../keyassignment/ShowDebugOverlay.md
|
||||
when printing the result of an expression from the Lua REPL and for the implicit string
|
||||
conversions of the parameters passed to [wezterm.log_info](log_info.md).
|
||||
|
||||
```lua
|
||||
local wezterm = require 'wezterm'
|
||||
assert(wezterm.to_string { 1, 2 } == [=[[
|
||||
1,
|
||||
2,
|
||||
]]=])
|
||||
assert(wezterm.to_string { a = 1, b = 2 } == [[{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}]])
|
||||
```
|
||||
|
@ -1,9 +1,12 @@
|
||||
Record a terminal session as an asciicast
|
||||
|
||||
Usage: wezterm record [PROG]...
|
||||
Usage: wezterm record [OPTIONS] [PROG]...
|
||||
|
||||
Arguments:
|
||||
[PROG]...
|
||||
[PROG]... Start prog instead of the default_prog defined by your wezterm
|
||||
configuration
|
||||
|
||||
Options:
|
||||
-h, --help Print help
|
||||
--cwd <CWD> Start in the specified directory, instead of the default_cwd
|
||||
defined by your wezterm configuration
|
||||
-h, --help Print help
|
||||
|
@ -87,13 +87,13 @@ that exactly matches your system you can try installing one from an older versio
|
||||
of your distribution, or use one of the Debian packages linked below. Failing that,
|
||||
you can try the AppImage download which should work on most Linux systems.
|
||||
|
||||
|Distro | Stable | Nightly |
|
||||
|------------|------------------|---------------------|
|
||||
|Ubuntu20 |[{{ ubuntu20_deb_stable_asset }}]({{ ubuntu20_deb_stable }}) |[{{ ubuntu20_deb_nightly_asset }}]({{ ubuntu20_deb_nightly }})|
|
||||
|Ubuntu22 |[{{ ubuntu22_deb_stable_asset }}]({{ ubuntu22_deb_stable }}) |[{{ ubuntu22_deb_nightly_asset }}]({{ ubuntu22_deb_nightly }})|
|
||||
|Debian10 |[{{ debian10_deb_stable_asset }}]({{ debian10_deb_stable }}) |[{{ debian10_deb_nightly_asset }}]({{ debian10_deb_nightly }})|
|
||||
|Debian11 |[{{ debian11_deb_stable_asset }}]({{ debian11_deb_stable }}) |[{{ debian11_deb_nightly_asset }}]({{ debian11_deb_nightly }})|
|
||||
|Debian12 |Nightly builds only|[{{ debian12_deb_nightly_asset }}]({{ debian12_deb_nightly }})|
|
||||
|Distro | Stable | Nightly| |
|
||||
|------------|------------------|--------|------------|
|
||||
|Ubuntu20 |[amd64]({{ ubuntu20_deb_stable }}) |[amd64]({{ ubuntu20_deb_nightly }})| |
|
||||
|Ubuntu22 |[amd64]({{ ubuntu22_deb_stable }}) |[amd64]({{ ubuntu22_deb_nightly }})|[arm64]({{ ubuntu22_arm64_deb_nightly}})|
|
||||
|Debian10 |[amd64]({{ debian10_deb_stable }}) |[amd64]({{ debian10_deb_nightly }})| |
|
||||
|Debian11 |[amd64]({{ debian11_deb_stable }}) |[amd64]({{ debian11_deb_nightly }})| |
|
||||
|Debian12 |Nightly builds only|[amd64]({{ debian12_deb_nightly }})|[arm64]({{ debian12_arm64_deb_nightly }}) |
|
||||
|
||||
To download and install from the CLI, you can use something like this, which
|
||||
shows how to install the Ubuntu 20 package:
|
||||
@ -106,6 +106,33 @@ $ sudo apt install -y ./{{ ubuntu20_deb_stable_asset }}
|
||||
* The package installs `/usr/bin/wezterm` and `/usr/share/applications/org.wezfurlong.wezterm.desktop`
|
||||
* Configuration instructions can be [found here](../config/files.md)
|
||||
|
||||
## Installing on Fedora and rpm-based Systems via Copr
|
||||
|
||||
Nightly builds of wezterm are now available via the [Copr](https://copr.fedorainfracloud.org/) build service.
|
||||
|
||||
You can see the current list of available distributions and architectures
|
||||
[on the wezterm-nightly project page](https://copr.fedorainfracloud.org/coprs/wezfurlong/wezterm-nightly/).
|
||||
At the time that this page was written, the following distributions are available in Copr for `x86_64` and `aarch64`:
|
||||
|
||||
* Centos Stream 8 and 9
|
||||
* Fedora 38, 39, rawhide
|
||||
* OpenSUSE Leap 15.5
|
||||
* OpenSUSE Tumbleweed
|
||||
* RHEL 8, 9
|
||||
|
||||
To perform initial installation:
|
||||
|
||||
```console
|
||||
$ sudo dnf copr enable wezfurlong/wezterm-nightly
|
||||
$ sudo dnf install wezterm
|
||||
```
|
||||
|
||||
To update:
|
||||
|
||||
```console
|
||||
$ sudo dnf update wezterm
|
||||
```
|
||||
|
||||
## Installing on Fedora and rpm-based Systems
|
||||
|
||||
The CI system builds `.rpm` files on CentOS, Fedora and openSUSE systems.
|
||||
@ -118,11 +145,12 @@ on most Linux systems.
|
||||
|CentOS7 |[{{ centos7_rpm_stable_asset }}]({{ centos7_rpm_stable }}) |[{{ centos7_rpm_nightly_asset }}]({{ centos7_rpm_nightly }})|
|
||||
|CentOS8 |[{{ centos8_rpm_stable_asset }}]({{ centos8_rpm_stable }}) |[{{ centos8_rpm_nightly_asset }}]({{ centos8_rpm_nightly }})|
|
||||
|CentOS9 |[{{ centos9_rpm_stable_asset }}]({{ centos9_rpm_stable }})|[{{ centos9_rpm_nightly_asset }}]({{ centos9_rpm_nightly }})|
|
||||
|Fedora36 |[{{ fedora36_rpm_stable_asset }}]({{ fedora36_rpm_stable }})|[{{ fedora36_rpm_nightly_asset }}]({{ fedora36_rpm_nightly }})|
|
||||
|Fedora36 |[{{ fedora36_rpm_stable_asset }}]({{ fedora36_rpm_stable }})|No longer supported|
|
||||
|Fedora37 |[{{ fedora37_rpm_stable_asset }}]({{ fedora37_rpm_stable }})|[{{ fedora37_rpm_nightly_asset }}]({{ fedora37_rpm_nightly }})|
|
||||
|Fedora38 |[{{ fedora38_rpm_stable_asset }}]({{ fedora38_rpm_stable }})|[{{ fedora38_rpm_nightly_asset }}]({{ fedora38_rpm_nightly }})|
|
||||
|openSUSE Leap |[{{ opensuse_leap_rpm_stable_asset }}]({{ opensuse_leap_rpm_stable }})|[{{ opensuse_leap_rpm_nightly_asset }}]({{ opensuse_leap_rpm_nightly }})|
|
||||
|openSUSE Tumbleweed |[{{ opensuse_tumbleweed_rpm_stable_asset }}]({{ opensuse_tumbleweed_rpm_stable }})|[{{ opensuse_tumbleweed_rpm_nightly_asset }}]({{ opensuse_tumbleweed_rpm_nightly }})|
|
||||
|Fedora39 |Nightly only|[{{ fedora39_rpm_nightly_asset }}]({{ fedora39_rpm_nightly }})|
|
||||
|openSUSE Leap |[{{ opensuse_leap_rpm_stable_asset }}]({{ opensuse_leap_rpm_stable }})|Use COPR instead|
|
||||
|openSUSE Tumbleweed |[{{ opensuse_tumbleweed_rpm_stable_asset }}]({{ opensuse_tumbleweed_rpm_stable }})|Use COPR instead|
|
||||
|
||||
To download and install from the CLI you can use something like this, which
|
||||
shows how to install the Fedora 37 package:
|
||||
@ -146,9 +174,9 @@ $ zypper install wezterm
|
||||
|
||||
## Arch Linux
|
||||
|
||||
WezTerm is available in the [Community repository](https://archlinux.org/packages/community/x86_64/wezterm/).
|
||||
WezTerm is available in the [Extra repository](https://archlinux.org/packages/extra/x86_64/wezterm/).
|
||||
|
||||
The version available in the community repository may lag behind the latest wezterm release, so you may
|
||||
The version available in the extra repository may lag behind the latest wezterm release, so you may
|
||||
wish to use one of these AUR options:
|
||||
|
||||
|What |Where|
|
||||
|
@ -115,8 +115,8 @@ markdown_extensions:
|
||||
base_path: "./docs"
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:materialx.emoji.twemoji
|
||||
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||
- pymdownx.tasklist:
|
||||
custom_checkbox: true
|
||||
- pymdownx.tabbed:
|
||||
|
40
get-deps
40
get-deps
@ -1,18 +1,23 @@
|
||||
#!/bin/sh
|
||||
|
||||
case $1 in
|
||||
--testing)
|
||||
TESTING=0
|
||||
;;
|
||||
'')
|
||||
TESTING=1
|
||||
;;
|
||||
*)
|
||||
echo 'get-deps:'
|
||||
echo ' --testing include dependencies required for tests'
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
TESTING=0
|
||||
DOCS=0
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--testing)
|
||||
TESTING=1
|
||||
;;
|
||||
--docs)
|
||||
DOCS=1
|
||||
;;
|
||||
*)
|
||||
echo 'get-deps:'
|
||||
echo ' --docs include dependencies required for testing docs'
|
||||
echo ' --testing include dependencies required for tests'
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
NOTFOUND=0
|
||||
|
||||
@ -21,7 +26,11 @@ test_cmd() {
|
||||
}
|
||||
|
||||
test_flag() {
|
||||
test $TESTING -eq 0
|
||||
test $TESTING -eq 1
|
||||
}
|
||||
|
||||
docs_flag() {
|
||||
test $DOCS -eq 1
|
||||
}
|
||||
|
||||
if test -z "$SUDO"; then
|
||||
@ -164,6 +173,9 @@ debian_deps() {
|
||||
if test_flag; then
|
||||
$APT install -y 'openssh-server'
|
||||
fi
|
||||
if docs_flag; then
|
||||
$APT install -y 'python3-pip mkdocs'
|
||||
fi
|
||||
}
|
||||
|
||||
arch_deps() {
|
||||
|
@ -55,12 +55,13 @@ impl GoghTheme {
|
||||
for s in data.themes {
|
||||
let cursor = RgbaColor::try_from(s.cursorColor)?;
|
||||
let name = s.name;
|
||||
let background = RgbaColor::try_from(s.background)?;
|
||||
|
||||
schemes.push(ColorSchemeFile {
|
||||
colors: Palette {
|
||||
foreground: Some(RgbaColor::try_from(s.foreground)?),
|
||||
background: Some(RgbaColor::try_from(s.background)?),
|
||||
cursor_fg: Some(cursor),
|
||||
background: Some(background),
|
||||
cursor_fg: Some(background),
|
||||
cursor_bg: Some(cursor),
|
||||
cursor_border: Some(cursor),
|
||||
ansi: Some([
|
||||
|
@ -30,6 +30,14 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> {
|
||||
})?,
|
||||
)?;
|
||||
|
||||
wezterm_mod.set(
|
||||
"to_string",
|
||||
lua.create_function(|_, arg: Value| {
|
||||
let res = ValuePrinter(arg);
|
||||
Ok(format!("{:#?}", res).to_string())
|
||||
})?,
|
||||
)?;
|
||||
|
||||
lua.globals().set(
|
||||
"print",
|
||||
lua.create_function(|_, args: Variadic<Value>| {
|
||||
|
@ -11,4 +11,4 @@ config = { path = "../../config" }
|
||||
wezterm-dynamic = { path = "../../wezterm-dynamic" }
|
||||
lazy_static = "1.4"
|
||||
luahelper = { path = "../../luahelper" }
|
||||
ordered-float = "3.0"
|
||||
ordered-float = "4.1"
|
||||
|
@ -3,7 +3,7 @@
|
||||
pub use mlua;
|
||||
use mlua::{IntoLua, Value as LuaValue};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashSet};
|
||||
use std::rc::Rc;
|
||||
use wezterm_dynamic::{FromDynamic, ToDynamic, Value as DynValue};
|
||||
|
||||
@ -262,6 +262,7 @@ impl<'lua> std::fmt::Debug for ValuePrinter<'lua> {
|
||||
ValuePrinterHelper {
|
||||
visited,
|
||||
value: self.0.clone(),
|
||||
is_cycle: false,
|
||||
}
|
||||
.fmt(fmt)
|
||||
}
|
||||
@ -270,6 +271,7 @@ impl<'lua> std::fmt::Debug for ValuePrinter<'lua> {
|
||||
struct ValuePrinterHelper<'lua> {
|
||||
visited: Rc<RefCell<HashSet<usize>>>,
|
||||
value: LuaValue<'lua>,
|
||||
is_cycle: bool,
|
||||
}
|
||||
|
||||
impl<'lua> PartialEq for ValuePrinterHelper<'lua> {
|
||||
@ -304,27 +306,55 @@ impl<'lua> ValuePrinterHelper<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_array_style_table(t: &mlua::Table) -> bool {
|
||||
let mut keys = BTreeSet::new();
|
||||
for pair in t.clone().pairs::<LuaValue, LuaValue>() {
|
||||
match pair {
|
||||
Ok((key, _)) => match key {
|
||||
LuaValue::Integer(i) if i >= 1 => {
|
||||
keys.insert(i);
|
||||
}
|
||||
_ => return false,
|
||||
},
|
||||
Err(_) => return false,
|
||||
}
|
||||
}
|
||||
|
||||
// Now see if we have contiguous keys.
|
||||
// The BTreeSet will iterate the keys in ascending order.
|
||||
let mut expect = 1;
|
||||
for key in keys {
|
||||
if key != expect {
|
||||
return false;
|
||||
}
|
||||
expect += 1;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
impl<'lua> std::fmt::Debug for ValuePrinterHelper<'lua> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
|
||||
match &self.value {
|
||||
LuaValue::Table(_) if self.is_cycle => {
|
||||
fmt.write_fmt(format_args!("table: {:?}", self.value.to_pointer()))
|
||||
}
|
||||
LuaValue::Table(t) => {
|
||||
self.visited
|
||||
.borrow_mut()
|
||||
.insert(self.value.to_pointer() as usize);
|
||||
if let Ok(true) = t.contains_key(1) {
|
||||
if is_array_style_table(&t) {
|
||||
// Treat as list
|
||||
let mut list = fmt.debug_list();
|
||||
for (idx, value) in t.clone().sequence_values().enumerate() {
|
||||
for value in t.clone().sequence_values() {
|
||||
match value {
|
||||
Ok(value) => {
|
||||
if !self.has_cycle(&value) {
|
||||
list.entry(&Self {
|
||||
visited: Rc::clone(&self.visited),
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
log::warn!("Ignoring value at ordinal position {} which has cyclical reference", idx);
|
||||
}
|
||||
let is_cycle = self.has_cycle(&value);
|
||||
list.entry(&Self {
|
||||
visited: Rc::clone(&self.visited),
|
||||
value,
|
||||
is_cycle,
|
||||
});
|
||||
}
|
||||
Err(err) => {
|
||||
list.entry(&err);
|
||||
@ -341,26 +371,19 @@ impl<'lua> std::fmt::Debug for ValuePrinterHelper<'lua> {
|
||||
for pair in t.clone().pairs::<LuaValue, LuaValue>() {
|
||||
match pair {
|
||||
Ok(pair) => {
|
||||
if !self.has_cycle(&pair.1) {
|
||||
map.insert(
|
||||
Self {
|
||||
visited: Rc::clone(&self.visited),
|
||||
value: pair.0,
|
||||
},
|
||||
Self {
|
||||
visited: Rc::clone(&self.visited),
|
||||
value: pair.1,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
log::warn!(
|
||||
"Ignoring field {:?} which has cyclical reference",
|
||||
Self {
|
||||
visited: Rc::clone(&self.visited),
|
||||
value: pair.0
|
||||
}
|
||||
);
|
||||
}
|
||||
let is_cycle = self.has_cycle(&pair.1);
|
||||
map.insert(
|
||||
Self {
|
||||
visited: Rc::clone(&self.visited),
|
||||
value: pair.0,
|
||||
is_cycle: false,
|
||||
},
|
||||
Self {
|
||||
visited: Rc::clone(&self.visited),
|
||||
value: pair.1,
|
||||
is_cycle,
|
||||
},
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("error while retrieving map entry: {}", err);
|
||||
@ -371,6 +394,9 @@ impl<'lua> std::fmt::Debug for ValuePrinterHelper<'lua> {
|
||||
fmt.debug_map().entries(&map).finish()
|
||||
}
|
||||
}
|
||||
LuaValue::UserData(_) if self.is_cycle => {
|
||||
fmt.write_fmt(format_args!("userdata: {:?}", self.value.to_pointer()))
|
||||
}
|
||||
LuaValue::UserData(ud) => {
|
||||
if let Ok(mt) = ud.get_metatable() {
|
||||
if let Ok(to_dynamic) = mt.get::<mlua::Function>("__wezterm_to_dynamic") {
|
||||
@ -378,6 +404,7 @@ impl<'lua> std::fmt::Debug for ValuePrinterHelper<'lua> {
|
||||
Ok(value) => Self {
|
||||
visited: Rc::clone(&self.visited),
|
||||
value,
|
||||
is_cycle: false,
|
||||
}
|
||||
.fmt(fmt),
|
||||
Err(err) => write!(fmt, "Error calling __wezterm_to_dynamic: {err}"),
|
||||
@ -390,6 +417,23 @@ impl<'lua> std::fmt::Debug for ValuePrinterHelper<'lua> {
|
||||
}
|
||||
}
|
||||
LuaValue::Error(e) => fmt.write_fmt(format_args!("error {}", e)),
|
||||
LuaValue::String(s) => match s.to_str() {
|
||||
Ok(s) => fmt.write_fmt(format_args!("\"{}\"", s.escape_default())),
|
||||
Err(_) => {
|
||||
let mut binary_string = "b\"".to_string();
|
||||
for &b in s.as_bytes() {
|
||||
if let Some(c) = char::from_u32(b as u32) {
|
||||
if c.is_ascii_alphanumeric() || c.is_ascii_punctuation() || c == ' ' {
|
||||
binary_string.push(c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
binary_string.push_str(&format!("\\x{b:02x}"));
|
||||
}
|
||||
binary_string.push('"');
|
||||
fmt.write_str(&binary_string)
|
||||
}
|
||||
},
|
||||
_ => match self.value.to_string() {
|
||||
Ok(s) => fmt.write_str(&s),
|
||||
Err(err) => write!(fmt, "({err:#})"),
|
||||
|
@ -485,6 +485,15 @@ impl Mux {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_focused_pane(
|
||||
&self,
|
||||
client_id: &ClientId,
|
||||
) -> Option<(DomainId, WindowId, TabId, PaneId)> {
|
||||
let pane_id = self.clients.read().get(client_id)?.focused_pane_id?;
|
||||
let (domain, window, tab) = self.resolve_pane_id(pane_id)?;
|
||||
Some((domain, window, tab, pane_id))
|
||||
}
|
||||
|
||||
pub fn record_focus_for_client(&self, client_id: &ClientId, pane_id: PaneId) {
|
||||
let mut prior = None;
|
||||
if let Some(info) = self.clients.write().get_mut(client_id) {
|
||||
|
@ -22,6 +22,6 @@ sqlite-cache = "0.1.3"
|
||||
tar = "0.4"
|
||||
tempfile = "3.3"
|
||||
tokio = { version = "1.19", features = ["rt-multi-thread", "sync", "macros"] }
|
||||
toml = "0.7"
|
||||
toml = "0.8"
|
||||
wezterm-dynamic = { path = "../wezterm-dynamic" }
|
||||
yaml-rust = "0.4.5"
|
||||
|
@ -3,7 +3,7 @@ use anyhow::Context;
|
||||
use config::{ColorSchemeFile, ColorSchemeMetaData};
|
||||
use serde::Deserialize;
|
||||
use sqlite_cache::Cache;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
use tar::Archive;
|
||||
@ -103,95 +103,13 @@ fn make_prefix(key: &str) -> (char, String) {
|
||||
panic!("no good prefix");
|
||||
}
|
||||
|
||||
fn bake_for_config(mut schemeses: Vec<Scheme>) -> anyhow::Result<()> {
|
||||
let json_file_name = "docs/colorschemes/data.json";
|
||||
|
||||
let mut version_by_color_scheme = BTreeMap::new();
|
||||
let mut names_by_color_scheme = BTreeMap::new();
|
||||
let mut version_by_name = BTreeMap::new();
|
||||
|
||||
if let Ok(data) = std::fs::read_to_string(&json_file_name) {
|
||||
#[derive(Deserialize)]
|
||||
struct Entry {
|
||||
colors: serde_json::Value,
|
||||
metadata: MetaData,
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct MetaData {
|
||||
name: String,
|
||||
aliases: Vec<String>,
|
||||
wezterm_version: Option<String>,
|
||||
}
|
||||
|
||||
let existing: Vec<Entry> = serde_json::from_str(&data)?;
|
||||
for item in existing {
|
||||
if let Some(version) = &item.metadata.wezterm_version {
|
||||
let ident = serde_json::to_string(&item.colors)?;
|
||||
version_by_color_scheme.insert(ident.to_string(), version.to_string());
|
||||
version_by_name.insert(item.metadata.name.to_string(), version.to_string());
|
||||
|
||||
let mut names = item.metadata.aliases;
|
||||
names.insert(0, item.metadata.name);
|
||||
|
||||
for name in names {
|
||||
names_by_color_scheme
|
||||
.entry(ident.to_string())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let existing: Vec<serde_json::Value> = serde_json::from_str(&data)?;
|
||||
for item in existing {
|
||||
let data = ColorSchemeFile::from_json_value(&item)?;
|
||||
push_or_alias(
|
||||
&mut schemeses,
|
||||
Scheme {
|
||||
name: data.metadata.name.as_ref().unwrap().to_string(),
|
||||
file_name: None,
|
||||
data,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for scheme in &mut schemeses {
|
||||
let json = scheme.to_json_value()?;
|
||||
let ident = serde_json::to_string(json.get("colors").unwrap())?;
|
||||
if let Some(version) = version_by_color_scheme
|
||||
.get(&ident)
|
||||
.or_else(|| version_by_name.get(&scheme.name))
|
||||
.or_else(|| {
|
||||
for a in &scheme.data.metadata.aliases {
|
||||
if let Some(v) = version_by_name.get(a) {
|
||||
return Some(v);
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
{
|
||||
scheme
|
||||
.data
|
||||
.metadata
|
||||
.wezterm_version
|
||||
.replace(version.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const DATA_FILE_NAME: &str = "docs/colorschemes/data.json";
|
||||
fn bake_for_config(schemeses: SchemeSet) -> anyhow::Result<()> {
|
||||
let mut all = vec![];
|
||||
for s in &schemeses {
|
||||
for s in schemeses.by_name.values() {
|
||||
// Only interested in aliases with different-enough names
|
||||
let mut aliases = s.data.metadata.aliases.clone();
|
||||
|
||||
let json = s.to_json_value()?;
|
||||
let ident = serde_json::to_string(json.get("colors").unwrap())?;
|
||||
if let Some(more_aliases) = names_by_color_scheme.get(&ident) {
|
||||
for a in more_aliases {
|
||||
aliases.push(a.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
aliases.sort();
|
||||
aliases.dedup();
|
||||
aliases.retain(|name| name != &s.name);
|
||||
@ -257,105 +175,200 @@ pub const SCHEMES: [(&'static str, &'static str); {count}] = [\n
|
||||
}
|
||||
|
||||
let json = serde_json::to_string_pretty(&doc_data)?;
|
||||
let update = match std::fs::read_to_string(json_file_name) {
|
||||
let update = match std::fs::read_to_string(&DATA_FILE_NAME) {
|
||||
Ok(existing) => existing != json,
|
||||
Err(_) => true,
|
||||
};
|
||||
|
||||
if update {
|
||||
println!("Updating {json_file_name}");
|
||||
std::fs::write(json_file_name, json)?;
|
||||
println!("Updating {DATA_FILE_NAME}");
|
||||
std::fs::write(&DATA_FILE_NAME, json)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn push_or_alias(schemeses: &mut Vec<Scheme>, candidate: Scheme) -> bool {
|
||||
let mut aliased = false;
|
||||
for existing in schemeses.iter_mut() {
|
||||
if candidate.data.colors == existing.data.colors {
|
||||
log::info!("Adding {} as alias of {}", candidate.name, existing.name);
|
||||
existing.data.metadata.aliases.push(candidate.name.clone());
|
||||
aliased = true;
|
||||
struct SchemeSet {
|
||||
by_name: HashMap<String, Scheme>,
|
||||
version_by_color_scheme: BTreeMap<String, String>,
|
||||
version_by_name: BTreeMap<String, String>,
|
||||
}
|
||||
|
||||
impl SchemeSet {
|
||||
pub fn accumulate(&mut self, to_add: Vec<Scheme>) {
|
||||
for candidate in to_add {
|
||||
self.add(candidate);
|
||||
}
|
||||
}
|
||||
if !aliased {
|
||||
log::info!("Adding {}", candidate.name);
|
||||
schemeses.push(candidate);
|
||||
}
|
||||
aliased
|
||||
}
|
||||
|
||||
fn accumulate(schemeses: &mut Vec<Scheme>, to_add: Vec<Scheme>) {
|
||||
// Only accumulate if the scheme looks different enough
|
||||
for candidate in to_add {
|
||||
push_or_alias(schemeses, candidate);
|
||||
}
|
||||
}
|
||||
pub fn load_existing() -> anyhow::Result<Self> {
|
||||
let mut by_name = HashMap::new();
|
||||
let mut version_by_color_scheme = BTreeMap::new();
|
||||
let mut names_by_color_scheme = BTreeMap::new();
|
||||
let mut version_by_name = BTreeMap::new();
|
||||
|
||||
async fn sync_toml(
|
||||
repo_url: &str,
|
||||
branch: &str,
|
||||
suffix: &str,
|
||||
schemeses: &mut Vec<Scheme>,
|
||||
) -> anyhow::Result<()> {
|
||||
let tarball_url = if repo_url.starts_with("https://codeberg.org/") {
|
||||
format!("{repo_url}/archive/{branch}.tar.gz")
|
||||
} else {
|
||||
format!("{repo_url}/tarball/{branch}")
|
||||
};
|
||||
let tar_data = fetch_url(&tarball_url).await?;
|
||||
let decoder = libflate::gzip::Decoder::new(tar_data.as_slice())?;
|
||||
let mut tar = Archive::new(decoder);
|
||||
for entry in tar.entries()? {
|
||||
let mut entry = entry?;
|
||||
if let Ok(data) = std::fs::read_to_string(&DATA_FILE_NAME) {
|
||||
#[derive(Deserialize)]
|
||||
struct Entry {
|
||||
colors: serde_json::Value,
|
||||
metadata: MetaData,
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct MetaData {
|
||||
name: String,
|
||||
aliases: Vec<String>,
|
||||
wezterm_version: Option<String>,
|
||||
}
|
||||
|
||||
if entry
|
||||
.path()?
|
||||
.extension()
|
||||
.and_then(|s| s.to_str())
|
||||
.map(|s| s == "toml")
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let dest_file = NamedTempFile::new()?;
|
||||
entry.unpack(dest_file.path())?;
|
||||
let existing: Vec<Entry> = serde_json::from_str(&data)?;
|
||||
for item in existing {
|
||||
if let Some(version) = &item.metadata.wezterm_version {
|
||||
let ident = serde_json::to_string(&item.colors)?;
|
||||
version_by_color_scheme.insert(ident.to_string(), version.to_string());
|
||||
version_by_name.insert(item.metadata.name.to_string(), version.to_string());
|
||||
|
||||
let data = std::fs::read_to_string(dest_file.path())?;
|
||||
let mut names = item.metadata.aliases;
|
||||
names.insert(0, item.metadata.name);
|
||||
|
||||
match ColorSchemeFile::from_toml_str(&data) {
|
||||
Ok(mut scheme) => {
|
||||
let name = match scheme.metadata.name {
|
||||
Some(name) => name,
|
||||
None => entry
|
||||
.path()?
|
||||
.file_stem()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
};
|
||||
let name = format!("{name}{suffix}");
|
||||
scheme.metadata.name = Some(name.clone());
|
||||
if scheme.metadata.origin_url.is_none() {
|
||||
scheme.metadata.origin_url = Some(repo_url.to_string());
|
||||
for name in names {
|
||||
names_by_color_scheme
|
||||
.entry(ident.to_string())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(name);
|
||||
}
|
||||
apply_nightly_version(&mut scheme.metadata);
|
||||
|
||||
let scheme = Scheme {
|
||||
name: name.clone(),
|
||||
file_name: None,
|
||||
data: scheme,
|
||||
};
|
||||
|
||||
push_or_alias(schemeses, scheme);
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("{tarball_url}/{}: {err:#}", entry.path().unwrap().display());
|
||||
}
|
||||
|
||||
let existing: Vec<serde_json::Value> = serde_json::from_str(&data)?;
|
||||
for item in existing {
|
||||
let data = ColorSchemeFile::from_json_value(&item)?;
|
||||
let name = data.metadata.name.as_ref().unwrap().to_string();
|
||||
by_name.insert(
|
||||
name.to_string(),
|
||||
Scheme {
|
||||
name,
|
||||
file_name: None,
|
||||
data,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
by_name,
|
||||
version_by_color_scheme,
|
||||
version_by_name,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add(&mut self, mut candidate: Scheme) {
|
||||
for existing in self.by_name.values_mut() {
|
||||
if candidate == *existing || candidate.data.colors == existing.data.colors {
|
||||
log::info!("Adding {} as alias of {}", candidate.name, existing.name);
|
||||
existing.data.metadata.aliases.push(candidate.name.clone());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve wezterm version information for this scheme
|
||||
let json = candidate.to_json_value().expect("scheme to be json compat");
|
||||
let ident =
|
||||
serde_json::to_string(json.get("colors").unwrap()).expect("colors to be json compat");
|
||||
if let Some(version) = self
|
||||
.version_by_color_scheme
|
||||
.get(&ident)
|
||||
.or_else(|| self.version_by_name.get(&candidate.name))
|
||||
.or_else(|| {
|
||||
for a in &candidate.data.metadata.aliases {
|
||||
if let Some(v) = self.version_by_name.get(a) {
|
||||
return Some(v);
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
{
|
||||
candidate
|
||||
.data
|
||||
.metadata
|
||||
.wezterm_version
|
||||
.replace(version.to_string());
|
||||
}
|
||||
|
||||
if let Some(existing) = self.by_name.remove(&candidate.name) {
|
||||
// Already exists but we didn't find it by exact color match
|
||||
// above.
|
||||
candidate.data.metadata.aliases = existing.data.metadata.aliases;
|
||||
println!("Updating {}", candidate.name);
|
||||
} else {
|
||||
println!("Adding {}", candidate.name);
|
||||
}
|
||||
self.by_name.insert(candidate.name.to_string(), candidate);
|
||||
}
|
||||
|
||||
async fn sync_toml(
|
||||
&mut self,
|
||||
repo_url: &str,
|
||||
branch: &str,
|
||||
suffix: &str,
|
||||
) -> anyhow::Result<()> {
|
||||
let tarball_url = if repo_url.starts_with("https://codeberg.org/") {
|
||||
format!("{repo_url}/archive/{branch}.tar.gz")
|
||||
} else {
|
||||
format!("{repo_url}/tarball/{branch}")
|
||||
};
|
||||
let tar_data = fetch_url(&tarball_url).await?;
|
||||
let decoder = libflate::gzip::Decoder::new(tar_data.as_slice())?;
|
||||
let mut tar = Archive::new(decoder);
|
||||
for entry in tar.entries()? {
|
||||
let mut entry = entry?;
|
||||
|
||||
if entry
|
||||
.path()?
|
||||
.extension()
|
||||
.and_then(|s| s.to_str())
|
||||
.map(|s| s == "toml")
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let dest_file = NamedTempFile::new()?;
|
||||
entry.unpack(dest_file.path())?;
|
||||
|
||||
let data = std::fs::read_to_string(dest_file.path())?;
|
||||
|
||||
match ColorSchemeFile::from_toml_str(&data) {
|
||||
Ok(mut scheme) => {
|
||||
let name = match scheme.metadata.name {
|
||||
Some(name) => name,
|
||||
None => entry
|
||||
.path()?
|
||||
.file_stem()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
};
|
||||
let name = format!("{name}{suffix}");
|
||||
scheme.metadata.name = Some(name.clone());
|
||||
if scheme.metadata.origin_url.is_none() {
|
||||
scheme.metadata.origin_url = Some(repo_url.to_string());
|
||||
}
|
||||
apply_nightly_version(&mut scheme.metadata);
|
||||
|
||||
let scheme = Scheme {
|
||||
name: name.clone(),
|
||||
file_name: None,
|
||||
data: scheme,
|
||||
};
|
||||
|
||||
self.add(scheme);
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("{tarball_url}/{}: {err:#}", entry.path().unwrap().display());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
@ -363,83 +376,51 @@ async fn main() -> anyhow::Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
// They color us! my precious!
|
||||
let mut schemeses = vec![];
|
||||
sync_toml(
|
||||
"https://github.com/catppuccin/wezterm",
|
||||
"main",
|
||||
"",
|
||||
&mut schemeses,
|
||||
)
|
||||
.await?;
|
||||
sync_toml(
|
||||
"https://github.com/EdenEast/nightfox.nvim",
|
||||
"main",
|
||||
"",
|
||||
&mut schemeses,
|
||||
)
|
||||
.await?;
|
||||
sync_toml(
|
||||
"https://github.com/Hiroya-W/wezterm-sequoia-theme",
|
||||
"main",
|
||||
"",
|
||||
&mut schemeses,
|
||||
)
|
||||
.await?;
|
||||
sync_toml(
|
||||
"https://github.com/dracula/wezterm",
|
||||
"main",
|
||||
"",
|
||||
&mut schemeses,
|
||||
)
|
||||
.await?;
|
||||
sync_toml(
|
||||
"https://github.com/olivercederborg/poimandres.nvim",
|
||||
"main",
|
||||
"",
|
||||
&mut schemeses,
|
||||
)
|
||||
.await?;
|
||||
sync_toml(
|
||||
"https://github.com/folke/tokyonight.nvim",
|
||||
"main",
|
||||
"",
|
||||
&mut schemeses,
|
||||
)
|
||||
.await?;
|
||||
sync_toml(
|
||||
"https://codeberg.org/anhsirk0/wezterm-themes",
|
||||
"main",
|
||||
"",
|
||||
&mut schemeses,
|
||||
)
|
||||
.await?;
|
||||
sync_toml(
|
||||
"https://github.com/hardhackerlabs/theme-wezterm",
|
||||
"master",
|
||||
"",
|
||||
&mut schemeses,
|
||||
)
|
||||
.await?;
|
||||
sync_toml(
|
||||
"https://github.com/ribru17/bamboo.nvim",
|
||||
"master",
|
||||
"",
|
||||
&mut schemeses,
|
||||
)
|
||||
.await?;
|
||||
accumulate(
|
||||
&mut schemeses,
|
||||
iterm2::sync_iterm2().await.context("sync iterm2")?,
|
||||
);
|
||||
accumulate(&mut schemeses, base16::sync().await.context("sync base16")?);
|
||||
accumulate(
|
||||
&mut schemeses,
|
||||
gogh::sync_gogh().await.context("sync gogh")?,
|
||||
);
|
||||
accumulate(
|
||||
&mut schemeses,
|
||||
sexy::sync_sexy().await.context("sync sexy")?,
|
||||
);
|
||||
let mut schemeses = SchemeSet::load_existing()?;
|
||||
|
||||
schemeses
|
||||
.sync_toml("https://github.com/catppuccin/wezterm", "main", "")
|
||||
.await?;
|
||||
schemeses
|
||||
.sync_toml("https://github.com/EdenEast/nightfox.nvim", "main", "")
|
||||
.await?;
|
||||
schemeses
|
||||
.sync_toml(
|
||||
"https://github.com/Hiroya-W/wezterm-sequoia-theme",
|
||||
"main",
|
||||
"",
|
||||
)
|
||||
.await?;
|
||||
schemeses
|
||||
.sync_toml("https://github.com/dracula/wezterm", "main", "")
|
||||
.await?;
|
||||
schemeses
|
||||
.sync_toml(
|
||||
"https://github.com/olivercederborg/poimandres.nvim",
|
||||
"main",
|
||||
"",
|
||||
)
|
||||
.await?;
|
||||
schemeses
|
||||
.sync_toml("https://github.com/folke/tokyonight.nvim", "main", "")
|
||||
.await?;
|
||||
schemeses
|
||||
.sync_toml("https://codeberg.org/anhsirk0/wezterm-themes", "main", "")
|
||||
.await?;
|
||||
schemeses
|
||||
.sync_toml(
|
||||
"https://github.com/hardhackerlabs/theme-wezterm",
|
||||
"master",
|
||||
"",
|
||||
)
|
||||
.await?;
|
||||
schemeses
|
||||
.sync_toml("https://github.com/ribru17/bamboo.nvim", "master", "")
|
||||
.await?;
|
||||
schemeses.accumulate(iterm2::sync_iterm2().await.context("sync iterm2")?);
|
||||
schemeses.accumulate(base16::sync().await.context("sync base16")?);
|
||||
schemeses.accumulate(gogh::sync_gogh().await.context("sync gogh")?);
|
||||
schemeses.accumulate(sexy::sync_sexy().await.context("sync sexy")?);
|
||||
bake_for_config(schemeses)?;
|
||||
|
||||
Ok(())
|
||||
|
@ -27,7 +27,7 @@ lazy_static = "1.4"
|
||||
log = "0.4"
|
||||
lru = "0.7"
|
||||
num-traits = "0.2"
|
||||
ordered-float = "3.0"
|
||||
ordered-float = "4.1"
|
||||
serde = {version="1.0", features = ["rc"]}
|
||||
terminfo = "0.8"
|
||||
unicode-normalization = "0.1.21"
|
||||
|
@ -546,7 +546,7 @@ impl TerminalState {
|
||||
last_mouse_move: None,
|
||||
cursor_visible: true,
|
||||
g0_charset: CharSet::Ascii,
|
||||
g1_charset: CharSet::DecLineDrawing,
|
||||
g1_charset: CharSet::Ascii,
|
||||
shift_out: false,
|
||||
newline_mode: false,
|
||||
current_mouse_buttons: vec![],
|
||||
@ -929,6 +929,11 @@ impl TerminalState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the current cell attributes of the screen
|
||||
pub fn pen(&self) -> CellAttributes {
|
||||
self.pen.clone()
|
||||
}
|
||||
|
||||
pub fn user_vars(&self) -> &HashMap<String, String> {
|
||||
&self.user_vars
|
||||
}
|
||||
@ -1248,6 +1253,9 @@ impl TerminalState {
|
||||
self.reverse_video_mode = false;
|
||||
self.bidi_enabled.take();
|
||||
self.bidi_hint.take();
|
||||
|
||||
self.g0_charset = CharSet::Ascii;
|
||||
self.g1_charset = CharSet::Ascii;
|
||||
}
|
||||
Device::RequestPrimaryDeviceAttributes => {
|
||||
let mut ident = "\x1b[?65".to_string(); // Vt500
|
||||
@ -1345,6 +1353,22 @@ impl TerminalState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates that mode is permanently enabled
|
||||
fn decqrm_response_permanent(&mut self, mode: Mode) {
|
||||
let (is_dec, number) = match &mode {
|
||||
Mode::QueryDecPrivateMode(DecPrivateMode::Code(code)) => (true, code.to_u16().unwrap()),
|
||||
Mode::QueryDecPrivateMode(DecPrivateMode::Unspecified(code)) => (true, *code),
|
||||
Mode::QueryMode(TerminalMode::Code(code)) => (false, code.to_u16().unwrap()),
|
||||
Mode::QueryMode(TerminalMode::Unspecified(code)) => (false, *code),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let prefix = if is_dec { "?" } else { "" };
|
||||
|
||||
write!(self.writer, "\x1b[{prefix}{number};3$y").ok();
|
||||
self.writer.flush().ok();
|
||||
}
|
||||
|
||||
fn decqrm_response(&mut self, mode: Mode, mut recognized: bool, enabled: bool) {
|
||||
let (is_dec, number) = match &mode {
|
||||
Mode::QueryDecPrivateMode(DecPrivateMode::Code(code)) => (true, code.to_u16().unwrap()),
|
||||
@ -1449,6 +1473,21 @@ impl TerminalState {
|
||||
self.decqrm_response(mode, true, self.left_and_right_margin_mode);
|
||||
}
|
||||
|
||||
Mode::SetDecPrivateMode(DecPrivateMode::Code(
|
||||
DecPrivateModeCode::GraphemeClustering,
|
||||
))
|
||||
| Mode::ResetDecPrivateMode(DecPrivateMode::Code(
|
||||
DecPrivateModeCode::GraphemeClustering,
|
||||
)) => {
|
||||
// Permanently enabled
|
||||
}
|
||||
|
||||
Mode::QueryDecPrivateMode(DecPrivateMode::Code(
|
||||
DecPrivateModeCode::GraphemeClustering,
|
||||
)) => {
|
||||
self.decqrm_response_permanent(mode);
|
||||
}
|
||||
|
||||
Mode::SetDecPrivateMode(DecPrivateMode::Code(DecPrivateModeCode::SaveCursor)) => {
|
||||
self.dec_save_cursor();
|
||||
}
|
||||
@ -1940,7 +1979,17 @@ impl TerminalState {
|
||||
checksum += u16::from(ch as u8);
|
||||
}
|
||||
}
|
||||
checksum
|
||||
|
||||
// Treat uninitialized cells as spaces.
|
||||
// The concept of uninitialized cells in wezterm is not the same as that on VT520 or that
|
||||
// on xterm, so, to prevent a lot of noise in esctest, treat them as spaces, at least when
|
||||
// asking for the checksum of a single cell (which is what esctest does).
|
||||
// See: https://github.com/wez/wezterm/pull/4565
|
||||
if checksum == 0 {
|
||||
32u16
|
||||
} else {
|
||||
checksum
|
||||
}
|
||||
}
|
||||
|
||||
fn perform_csi_window(&mut self, window: Window) {
|
||||
@ -2474,11 +2523,15 @@ impl TerminalState {
|
||||
})) as u32,
|
||||
);
|
||||
let col = OneBased::from_zero_based(
|
||||
(self.cursor.x.saturating_sub(if self.dec_origin_mode {
|
||||
self.left_and_right_margins.start
|
||||
} else {
|
||||
0
|
||||
})) as u32,
|
||||
(self
|
||||
.cursor
|
||||
.x
|
||||
.min(self.screen().physical_cols - 1)
|
||||
.saturating_sub(if self.dec_origin_mode {
|
||||
self.left_and_right_margins.start
|
||||
} else {
|
||||
0
|
||||
})) as u32,
|
||||
);
|
||||
let report = CSI::Cursor(Cursor::ActivePositionReport { line, col });
|
||||
write!(self.writer, "{}", report).ok();
|
||||
@ -2545,7 +2598,7 @@ impl TerminalState {
|
||||
pen: Default::default(),
|
||||
dec_origin_mode: false,
|
||||
g0_charset: CharSet::Ascii,
|
||||
g1_charset: CharSet::DecLineDrawing,
|
||||
g1_charset: CharSet::Ascii,
|
||||
});
|
||||
debug!(
|
||||
"restore cursor {:?} is_alt={}",
|
||||
|
@ -687,7 +687,7 @@ impl<'a> Performer<'a> {
|
||||
self.current_mouse_buttons.clear();
|
||||
self.cursor_visible = true;
|
||||
self.g0_charset = CharSet::Ascii;
|
||||
self.g1_charset = CharSet::DecLineDrawing;
|
||||
self.g1_charset = CharSet::Ascii;
|
||||
self.shift_out = false;
|
||||
self.newline_mode = false;
|
||||
self.tabs = TabStop::new(self.screen().physical_cols, 8);
|
||||
@ -700,6 +700,8 @@ impl<'a> Performer<'a> {
|
||||
self.accumulating_title.take();
|
||||
|
||||
self.screen.full_reset();
|
||||
self.screen.activate_alt_screen(seqno);
|
||||
self.erase_in_display(EraseInDisplay::EraseDisplay);
|
||||
self.screen.activate_primary_screen(seqno);
|
||||
self.erase_in_display(EraseInDisplay::EraseScrollback);
|
||||
self.erase_in_display(EraseInDisplay::EraseDisplay);
|
||||
|
@ -726,7 +726,7 @@ fn test_dec_special_graphics() {
|
||||
);
|
||||
|
||||
term = TestTerm::new(2, 50, 0);
|
||||
term.print("\u{0e}SO-ABCabcdefghijklmnopqrstuvwxyzDEF\r\n\u{0f}SI-hello");
|
||||
term.print("\u{1b})0\u{0e}SO-ABCabcdefghijklmnopqrstuvwxyzDEF\r\n\u{0f}SI-hello");
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
file!(),
|
||||
|
@ -28,7 +28,7 @@ libc = "0.2"
|
||||
log = "0.4"
|
||||
memmem = "0.1"
|
||||
num-traits = "0.2"
|
||||
ordered-float = "3.0"
|
||||
ordered-float = "4.1"
|
||||
pest = "2.1"
|
||||
pest_derive = "2.1"
|
||||
phf = "0.11"
|
||||
|
@ -29,7 +29,7 @@ wezterm|Wez's terminal emulator,
|
||||
Cr=\E]112\007, Cs=\E]12;%p1%s\007, Ms=\E]52;%p1%s;%p2%s\007, Se=\E[2\sq,
|
||||
Ss=\E[%p1%d\sq,
|
||||
Smulx=\E[4:%p1%dm,
|
||||
Sync=\E[?2026%?%p1%{1}%-%tl%eh,
|
||||
Sync=\E[?2026%?%p1%{1}%-%tl%eh%;,
|
||||
Setulc=\E[58:2::%p1%{65536}%/%d:%p1%{256}%/%{255}%&%d:%p1%{255}%&%d%;m,
|
||||
Smol=\E[53m,
|
||||
am, bce, ccc, km, mc5i, mir, msgr, npc, xenl,
|
||||
|
@ -219,7 +219,9 @@ impl Capabilities {
|
||||
if has_true_color {
|
||||
ColorLevel::TrueColor
|
||||
} else if let Some(cap::MaxColors(n)) = db.get::<cap::MaxColors>() {
|
||||
if n >= 256 {
|
||||
if n >= 16777216 {
|
||||
ColorLevel::TrueColor
|
||||
} else if n >= 256 {
|
||||
ColorLevel::TwoFiftySix
|
||||
} else {
|
||||
ColorLevel::Sixteen
|
||||
|
@ -669,9 +669,7 @@ impl TeenyString {
|
||||
let len = bytes.len();
|
||||
let width = width.unwrap_or_else(|| grapheme_column_width(s, unicode_version));
|
||||
|
||||
if len < std::mem::size_of::<u64>() {
|
||||
debug_assert!(width < 3);
|
||||
|
||||
if len < std::mem::size_of::<u64>() && width < 3 {
|
||||
let mut word = 0u64;
|
||||
unsafe {
|
||||
std::ptr::copy_nonoverlapping(
|
||||
|
@ -841,6 +841,11 @@ pub enum DecPrivateModeCode {
|
||||
EnableAlternateScreen = 47,
|
||||
OptEnableAlternateScreen = 1047,
|
||||
BracketedPaste = 2004,
|
||||
|
||||
/// <https://github.com/contour-terminal/terminal-unicode-core/>
|
||||
/// Grapheme clustering mode
|
||||
GraphemeClustering = 2027,
|
||||
|
||||
/// Applies to sixel and regis modes
|
||||
UsePrivateColorRegistersForEachGraphic = 1070,
|
||||
|
||||
|
@ -136,8 +136,16 @@ impl TerminfoRenderer {
|
||||
}
|
||||
|
||||
let has_true_color = self.caps.color_level() == ColorLevel::TrueColor;
|
||||
let terminfo_color: i32 = match self.get_capability::<cap::MaxColors>() {
|
||||
Some(cap::MaxColors(n)) => n,
|
||||
// Whether to use terminfo to render 256 colors. If this is too large (ex. 16777216 from xterm-direct),
|
||||
// then setaf expects the index to be true color, in which case we cannot use it to render 256 (or even 16) colors.
|
||||
let terminfo_256_color: i32 = match self.get_capability::<cap::MaxColors>() {
|
||||
Some(cap::MaxColors(n)) => {
|
||||
if n > 256 {
|
||||
0
|
||||
} else {
|
||||
n
|
||||
}
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
|
||||
@ -160,7 +168,7 @@ impl TerminfoRenderer {
|
||||
(false, ColorAttribute::TrueColorWithPaletteFallback(_, idx))
|
||||
| (_, ColorAttribute::PaletteIndex(idx)) => {
|
||||
match self.get_capability::<cap::SetAForeground>() {
|
||||
Some(set) if (idx as i32) < terminfo_color => {
|
||||
Some(set) if (idx as i32) < terminfo_256_color => {
|
||||
set.expand().color(idx).to(out.by_ref())?;
|
||||
}
|
||||
_ => {
|
||||
@ -194,7 +202,7 @@ impl TerminfoRenderer {
|
||||
(false, ColorAttribute::TrueColorWithPaletteFallback(_, idx))
|
||||
| (_, ColorAttribute::PaletteIndex(idx)) => {
|
||||
match self.get_capability::<cap::SetABackground>() {
|
||||
Some(set) if (idx as i32) < terminfo_color => {
|
||||
Some(set) if (idx as i32) < terminfo_256_color => {
|
||||
set.expand().color(idx).to(out.by_ref())?;
|
||||
}
|
||||
_ => {
|
||||
|
@ -8,7 +8,7 @@ license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
wezterm-dynamic-derive = { version="0.1", path="derive" }
|
||||
ordered-float = "3.0"
|
||||
ordered-float = "4.1"
|
||||
thiserror = "1.0"
|
||||
strsim = "0.10"
|
||||
log = "0.4"
|
||||
|
@ -136,7 +136,7 @@ impl Error {
|
||||
errors.push(Self::UnknownFieldForStruct {
|
||||
field_name: s.to_string(),
|
||||
type_name,
|
||||
possible: possible.clone(),
|
||||
possible,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ lfucache = { path = "../lfucache" }
|
||||
log = "0.4"
|
||||
memmap2 = "0.2"
|
||||
metrics = { version="0.17", features=["std"]}
|
||||
ordered-float = "3.0"
|
||||
ordered-float = "4.1"
|
||||
rangeset = { path = "../rangeset" }
|
||||
termwiz = { path = "../termwiz" }
|
||||
thiserror = "1.0"
|
||||
|
@ -165,73 +165,105 @@ impl FontLocator for FontConfigFontLocator {
|
||||
codepoints: &[char],
|
||||
) -> anyhow::Result<Vec<ParsedFont>> {
|
||||
log::trace!("locate_fallback_for_codepoints: {:?}", codepoints);
|
||||
let mut charset = CharSet::new()?;
|
||||
for &c in codepoints {
|
||||
charset.add(c)?;
|
||||
}
|
||||
let mut fonts: Vec<ParsedFont> = vec![];
|
||||
|
||||
let mut fonts = vec![];
|
||||
// In <https://github.com/wez/wezterm/issues/4310> we discover
|
||||
// that a font-config query for a charset containing both
|
||||
// 3065 and 2686 fails because no fonts contain both codepoints,
|
||||
// but querying separately does find the separate fonts.
|
||||
// We therefore need to break up our query so that we resolve
|
||||
// each codepoint individually.
|
||||
// However, if we need to resolve a block of characters that
|
||||
// are found in the same font (eg: someone is printing an
|
||||
// entire unicode block) we don't want to issue N queries
|
||||
// that return the same font.
|
||||
//
|
||||
// So we check the fonts that have been resolved in earlier
|
||||
// iterations to see if any of those cover a given codepoint
|
||||
// and allow that to satisfy the query if they do.
|
||||
|
||||
// Make two passes to locate a fallback: first try to find any
|
||||
// strictly monospace version, then, if we didn't find any matches,
|
||||
// look for a version with any spacing.
|
||||
for only_monospace in [true, false] {
|
||||
let mut pattern = FontPattern::new()?;
|
||||
pattern.add_charset(&charset)?;
|
||||
pattern.add_integer("weight", 80)?;
|
||||
pattern.add_integer("slant", 0)?;
|
||||
|
||||
let mut lists = vec![pattern
|
||||
.list()
|
||||
.context("pattern.list with no spacing constraint")?];
|
||||
|
||||
if only_monospace {
|
||||
for &spacing in &SPACING {
|
||||
pattern.delete_property("spacing")?;
|
||||
pattern.add_integer("spacing", spacing)?;
|
||||
lists.push(
|
||||
pattern
|
||||
.list()
|
||||
.with_context(|| format!("pattern.list with spacing={}", spacing))?,
|
||||
);
|
||||
'next_codepoint: for &c in codepoints {
|
||||
if !fonts.is_empty() {
|
||||
let mut wanted_range = rangeset::RangeSet::new();
|
||||
wanted_range.add(c as u32);
|
||||
for f in &fonts {
|
||||
match f.coverage_intersection(&wanted_range) {
|
||||
Ok(r) if !r.is_empty() => {
|
||||
// already found a font with this one!
|
||||
continue 'next_codepoint;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for list in lists {
|
||||
for pat in list.iter() {
|
||||
let num = pat.charset_intersect_count(&charset)?;
|
||||
if num == 0 {
|
||||
log::error!(
|
||||
"Skipping bogus font-config result {:?} because it doesn't overlap",
|
||||
pat
|
||||
);
|
||||
continue;
|
||||
}
|
||||
let mut pushed_this_pass = 0;
|
||||
|
||||
if let Ok(file) = pat.get_file().context("pat.get_file") {
|
||||
log::trace!("{file:?} has {num} codepoints from {codepoints:?}");
|
||||
let handle = FontDataHandle {
|
||||
source: FontDataSource::OnDisk(file.into()),
|
||||
index: pat.get_integer("index")?.try_into()?,
|
||||
variation: 0,
|
||||
origin: FontOrigin::FontConfig,
|
||||
coverage: pat.get_charset().ok().map(|c| c.to_range_set()),
|
||||
};
|
||||
if let Ok(parsed) = crate::parser::ParsedFont::from_locator(&handle) {
|
||||
fonts.push(parsed);
|
||||
let mut charset = CharSet::new()?;
|
||||
charset.add(c)?;
|
||||
|
||||
// Make two passes to locate a fallback: first try to find any
|
||||
// strictly monospace version, then, if we didn't find any matches,
|
||||
// look for a version with any spacing.
|
||||
for only_monospace in [true, false] {
|
||||
let mut pattern = FontPattern::new()?;
|
||||
pattern.add_charset(&charset)?;
|
||||
pattern.add_integer("weight", 80)?;
|
||||
pattern.add_integer("slant", 0)?;
|
||||
|
||||
let mut lists = vec![pattern
|
||||
.list()
|
||||
.context("pattern.list with no spacing constraint")?];
|
||||
|
||||
if only_monospace {
|
||||
for &spacing in &SPACING {
|
||||
pattern.delete_property("spacing")?;
|
||||
pattern.add_integer("spacing", spacing)?;
|
||||
lists.push(
|
||||
pattern.list().with_context(|| {
|
||||
format!("pattern.list with spacing={}", spacing)
|
||||
})?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for list in lists {
|
||||
for pat in list.iter() {
|
||||
let num = pat.charset_intersect_count(&charset)?;
|
||||
if num == 0 {
|
||||
log::error!(
|
||||
"Skipping bogus font-config result {:?} because it doesn't overlap",
|
||||
pat
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Ok(file) = pat.get_file().context("pat.get_file") {
|
||||
log::trace!("{file:?} has {num} codepoints from {codepoints:?}");
|
||||
let handle = FontDataHandle {
|
||||
source: FontDataSource::OnDisk(file.into()),
|
||||
index: pat.get_integer("index")?.try_into()?,
|
||||
variation: 0,
|
||||
origin: FontOrigin::FontConfig,
|
||||
coverage: pat.get_charset().ok().map(|c| c.to_range_set()),
|
||||
};
|
||||
if let Ok(parsed) = crate::parser::ParsedFont::from_locator(&handle) {
|
||||
fonts.push(parsed);
|
||||
pushed_this_pass += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if fonts.is_empty() {
|
||||
// If we get here on the first iteration, then we didn't
|
||||
// find a monospace version of fonts with those codepoints,
|
||||
// let's continue and try any matching font
|
||||
continue;
|
||||
}
|
||||
if pushed_this_pass == 0 {
|
||||
// If we get here on the first iteration, then we didn't
|
||||
// find a monospace version of fonts with those codepoints,
|
||||
// let's continue and try any matching font
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(fonts)
|
||||
|
@ -54,7 +54,7 @@ frecency = { path = "../frecency" }
|
||||
futures = "0.3"
|
||||
fuzzy-matcher = "0.3"
|
||||
hdrhistogram = "7.1"
|
||||
http_req = "0.9"
|
||||
http_req = "0.10"
|
||||
image = "0.24.6"
|
||||
lazy_static = "1.4"
|
||||
libc = "0.2"
|
||||
@ -66,7 +66,7 @@ mlua = {version="0.9", features=["send"]}
|
||||
mux = { path = "../mux" }
|
||||
mux-lua = { path = "../lua-api-crates/mux" }
|
||||
once_cell = "1.8"
|
||||
ordered-float = "3.0"
|
||||
ordered-float = "4.1"
|
||||
parking_lot = "0.12"
|
||||
portable-pty = { path = "../pty", features = ["serde_support"]}
|
||||
promise = { path = "../promise" }
|
||||
@ -105,7 +105,7 @@ wezterm-open-url = { path = "../wezterm-open-url" }
|
||||
wezterm-ssh = { path = "../wezterm-ssh" }
|
||||
wezterm-term = { path = "../term", features=["use_serde"] }
|
||||
wezterm-toast-notification = { path = "../wezterm-toast-notification" }
|
||||
wgpu = "0.17"
|
||||
wgpu = "0.18"
|
||||
window = { path = "../window" }
|
||||
window-funcs = { path = "../lua-api-crates/window-funcs" }
|
||||
|
||||
|
@ -236,7 +236,7 @@ impl CommandDef {
|
||||
for dom in &domains {
|
||||
let name = dom.domain_name();
|
||||
// FIXME: use domain_label here, but needs to be async
|
||||
let label = name.clone();
|
||||
let label = name;
|
||||
|
||||
if dom.spawnable() {
|
||||
if dom.state() == DomainState::Attached {
|
||||
@ -266,7 +266,7 @@ impl CommandDef {
|
||||
for dom in &domains {
|
||||
let name = dom.domain_name();
|
||||
// FIXME: use domain_label here, but needs to be async
|
||||
let label = name.clone();
|
||||
let label = name;
|
||||
|
||||
if dom.state() == DomainState::Attached {
|
||||
if name == "local" {
|
||||
|
@ -5,8 +5,8 @@ use crate::TermWindow;
|
||||
use ::window::*;
|
||||
use anyhow::{Context, Error};
|
||||
use config::keyassignment::{KeyAssignment, SpawnCommand};
|
||||
use config::ConfigSubscription;
|
||||
pub use config::FrontEndSelection;
|
||||
use config::{ConfigSubscription, NotificationHandling};
|
||||
use mux::client::ClientId;
|
||||
use mux::window::WindowId as MuxWindowId;
|
||||
use mux::{Mux, MuxNotification};
|
||||
@ -96,7 +96,7 @@ impl GuiFrontEnd {
|
||||
MuxNotification::PaneOutput(_) => {}
|
||||
MuxNotification::PaneAdded(_) => {}
|
||||
MuxNotification::Alert {
|
||||
pane_id: _,
|
||||
pane_id,
|
||||
alert:
|
||||
Alert::ToastNotification {
|
||||
title,
|
||||
@ -104,12 +104,34 @@ impl GuiFrontEnd {
|
||||
focus: _,
|
||||
},
|
||||
} => {
|
||||
let message = if title.is_none() { "" } else { &body };
|
||||
let title = title.as_ref().unwrap_or(&body);
|
||||
// FIXME: if notification.focus is true, we should do
|
||||
// something here to arrange to focus pane_id when the
|
||||
// notification is clicked
|
||||
persistent_toast_notification(title, message);
|
||||
let mux = Mux::get();
|
||||
|
||||
if let Some((_domain, window_id, tab_id)) = mux.resolve_pane_id(pane_id) {
|
||||
let config = config::configuration();
|
||||
|
||||
if let Some((_fdomain, f_window, f_tab, f_pane)) =
|
||||
mux.resolve_focused_pane(&client_id)
|
||||
{
|
||||
let show = match config.notification_handling {
|
||||
NotificationHandling::NeverShow => false,
|
||||
NotificationHandling::AlwaysShow => true,
|
||||
NotificationHandling::SuppressFromFocusedPane => f_pane != pane_id,
|
||||
NotificationHandling::SuppressFromFocusedTab => f_tab != tab_id,
|
||||
NotificationHandling::SuppressFromFocusedWindow => {
|
||||
f_window != window_id
|
||||
}
|
||||
};
|
||||
|
||||
if show {
|
||||
let message = if title.is_none() { "" } else { &body };
|
||||
let title = title.as_ref().unwrap_or(&body);
|
||||
// FIXME: if notification.focus is true, we should do
|
||||
// something here to arrange to focus pane_id when the
|
||||
// notification is clicked
|
||||
persistent_toast_notification(title, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MuxNotification::Alert {
|
||||
pane_id: _,
|
||||
|
@ -57,10 +57,32 @@ const PATTERNS: [&str; 14] = [
|
||||
/// It is derived from https://github.com/fcsonline/tmux-thumbs/blob/master/src/alphabets.rs
|
||||
/// which is Copyright (c) 2019 Ferran Basora and provided under the MIT license
|
||||
pub fn compute_labels_for_alphabet(alphabet: &str, num_matches: usize) -> Vec<String> {
|
||||
let alphabet = alphabet
|
||||
.chars()
|
||||
.map(|c| c.to_lowercase().to_string())
|
||||
.collect::<Vec<String>>();
|
||||
compute_labels_for_alphabet_impl(alphabet, num_matches, true)
|
||||
}
|
||||
|
||||
pub fn compute_labels_for_alphabet_with_preserved_case(
|
||||
alphabet: &str,
|
||||
num_matches: usize,
|
||||
) -> Vec<String> {
|
||||
compute_labels_for_alphabet_impl(alphabet, num_matches, false)
|
||||
}
|
||||
|
||||
fn compute_labels_for_alphabet_impl(
|
||||
alphabet: &str,
|
||||
num_matches: usize,
|
||||
make_lowercase: bool,
|
||||
) -> Vec<String> {
|
||||
let alphabet = if make_lowercase {
|
||||
alphabet
|
||||
.chars()
|
||||
.map(|c| c.to_lowercase().to_string())
|
||||
.collect::<Vec<String>>()
|
||||
} else {
|
||||
alphabet
|
||||
.chars()
|
||||
.map(|c| c.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
};
|
||||
// Prefer to use single character matches to represent everything
|
||||
let mut primary = alphabet.clone();
|
||||
let mut secondary = vec![];
|
||||
@ -144,6 +166,30 @@ mod alphabet_test {
|
||||
vec!["aa", "ab", "ba", "bb"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn composed_capital() {
|
||||
assert_eq!(
|
||||
compute_labels_for_alphabet_with_preserved_case("AB", 4),
|
||||
vec!["AA", "AB", "BA", "BB"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn composed_mixed() {
|
||||
assert_eq!(
|
||||
compute_labels_for_alphabet_with_preserved_case("aA", 4),
|
||||
vec!["aa", "aA", "Aa", "AA"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lowercase_alphabet_equal() {
|
||||
assert_eq!(
|
||||
compute_labels_for_alphabet_with_preserved_case("abc123", 12),
|
||||
compute_labels_for_alphabet("abc123", 12)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct QuickSelectOverlay {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use super::quickselect;
|
||||
use crate::scripting::guiwin::GuiWin;
|
||||
use config::keyassignment::{InputSelector, InputSelectorEntry, KeyAssignment};
|
||||
use fuzzy_matcher::skim::SkimMatcherV2;
|
||||
@ -26,6 +27,8 @@ struct SelectorState {
|
||||
always_fuzzy: bool,
|
||||
args: InputSelector,
|
||||
event_name: String,
|
||||
selection: String,
|
||||
labels: Vec<String>,
|
||||
}
|
||||
|
||||
impl SelectorState {
|
||||
@ -69,6 +72,14 @@ impl SelectorState {
|
||||
fn render(&mut self, term: &mut TermWizTerminal) -> termwiz::Result<()> {
|
||||
let size = term.get_screen_size()?;
|
||||
let max_width = size.cols.saturating_sub(6);
|
||||
let max_items = size.rows.saturating_sub(ROW_OVERHEAD);
|
||||
if max_items != self.max_items {
|
||||
self.labels = quickselect::compute_labels_for_alphabet_with_preserved_case(
|
||||
&self.args.alphabet,
|
||||
self.filtered_entries.len().min(max_items + 1),
|
||||
);
|
||||
self.max_items = max_items;
|
||||
}
|
||||
|
||||
let mut changes = vec![
|
||||
Change::ClearScreen(ColorAttribute::Default),
|
||||
@ -78,16 +89,14 @@ impl SelectorState {
|
||||
},
|
||||
Change::Text(format!(
|
||||
"{}\r\n",
|
||||
truncate_right(
|
||||
"Select an item and press Enter=accept \
|
||||
Esc=cancel /=filter",
|
||||
max_width
|
||||
)
|
||||
truncate_right(&self.args.description, max_width)
|
||||
)),
|
||||
Change::AllAttributes(CellAttributes::default()),
|
||||
];
|
||||
|
||||
let max_items = self.max_items;
|
||||
let labels = &self.labels;
|
||||
let max_label_len = labels.iter().map(|s| s.len()).max().unwrap_or(0);
|
||||
let mut labels_iter = labels.into_iter();
|
||||
|
||||
for (row_num, (entry_idx, entry)) in self
|
||||
.filtered_entries
|
||||
@ -107,8 +116,15 @@ impl SelectorState {
|
||||
attr.set_reverse(true);
|
||||
}
|
||||
|
||||
if row_num < 9 && !self.filtering {
|
||||
changes.push(Change::Text(format!(" {}. ", row_num + 1)));
|
||||
// from above we know that row_num <= max_items
|
||||
// show labels as long as we have more labels left
|
||||
// and we are not filtering
|
||||
if !self.filtering {
|
||||
if let Some(label) = labels_iter.next() {
|
||||
changes.push(Change::Text(format!(" {label:>max_label_len$}. ")));
|
||||
} else {
|
||||
changes.push(Change::Text(" ".repeat(max_label_len + 3)));
|
||||
}
|
||||
} else {
|
||||
changes.push(Change::Text(" ".to_string()));
|
||||
}
|
||||
@ -133,7 +149,7 @@ impl SelectorState {
|
||||
},
|
||||
Change::ClearToEndOfLine(ColorAttribute::Default),
|
||||
Change::Text(truncate_right(
|
||||
&format!("Fuzzy matching: {}", self.filter_term),
|
||||
&format!("{}{}", self.args.fuzzy_description, self.filter_term),
|
||||
max_width,
|
||||
)),
|
||||
]);
|
||||
@ -182,32 +198,39 @@ impl SelectorState {
|
||||
match event {
|
||||
InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Char(c),
|
||||
..
|
||||
}) if !self.filtering && c >= '1' && c <= '9' => {
|
||||
if self.launch(self.top_row + (c as u32 - '1' as u32) as usize) {
|
||||
break;
|
||||
modifiers: Modifiers::NONE,
|
||||
}) if !self.filtering && self.args.alphabet.contains(c) => {
|
||||
self.selection.push(c);
|
||||
if let Some(pos) = self.labels.iter().position(|x| *x == self.selection) {
|
||||
// since the number of labels is always <= self.max_items
|
||||
// by construction, we have pos as usize <= self.max_items
|
||||
// for free
|
||||
self.active_idx = self.top_row + pos as usize;
|
||||
if self.launch(self.active_idx) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Char('j'),
|
||||
..
|
||||
}) if !self.filtering => {
|
||||
}) if !self.filtering && !self.args.alphabet.contains("j") => {
|
||||
self.move_down();
|
||||
}
|
||||
InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Char('k'),
|
||||
..
|
||||
}) if !self.filtering => {
|
||||
}) if !self.filtering && !self.args.alphabet.contains("k") => {
|
||||
self.move_up();
|
||||
}
|
||||
InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Char('P'),
|
||||
key: KeyCode::Char('P' | 'K'),
|
||||
modifiers: Modifiers::CTRL,
|
||||
}) => {
|
||||
self.move_up();
|
||||
}
|
||||
InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Char('N'),
|
||||
key: KeyCode::Char('N' | 'J'),
|
||||
modifiers: Modifiers::CTRL,
|
||||
}) => {
|
||||
self.move_down();
|
||||
@ -222,13 +245,17 @@ impl SelectorState {
|
||||
key: KeyCode::Backspace,
|
||||
..
|
||||
}) => {
|
||||
if self.filter_term.pop().is_none() && !self.always_fuzzy {
|
||||
self.filtering = false;
|
||||
if !self.filtering {
|
||||
self.selection.pop();
|
||||
} else {
|
||||
if self.filter_term.pop().is_none() && !self.always_fuzzy {
|
||||
self.filtering = false;
|
||||
}
|
||||
self.update_filter();
|
||||
}
|
||||
self.update_filter();
|
||||
}
|
||||
InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Char('G'),
|
||||
key: KeyCode::Char('G' | 'C'),
|
||||
modifiers: Modifiers::CTRL,
|
||||
})
|
||||
| InputEvent::Key(KeyEvent {
|
||||
@ -301,9 +328,6 @@ impl SelectorState {
|
||||
break;
|
||||
}
|
||||
}
|
||||
InputEvent::Resized { rows, .. } => {
|
||||
self.max_items = rows.saturating_sub(ROW_OVERHEAD);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.render(term)?;
|
||||
@ -354,11 +378,9 @@ pub fn selector(
|
||||
anyhow::bail!("InputSelector requires action to be defined by wezterm.action_callback")
|
||||
}
|
||||
};
|
||||
let size = term.get_screen_size()?;
|
||||
let max_items = size.rows.saturating_sub(ROW_OVERHEAD);
|
||||
let mut state = SelectorState {
|
||||
active_idx: 0,
|
||||
max_items,
|
||||
max_items: 0,
|
||||
pane,
|
||||
top_row: 0,
|
||||
filter_term: String::new(),
|
||||
@ -368,6 +390,8 @@ pub fn selector(
|
||||
always_fuzzy: args.fuzzy,
|
||||
args,
|
||||
event_name,
|
||||
selection: String::new(),
|
||||
labels: vec![],
|
||||
};
|
||||
|
||||
term.set_raw_mode()?;
|
||||
|
@ -664,9 +664,12 @@ impl Modal for CommandPalette {
|
||||
.expect("to resolve char selection font");
|
||||
let metrics = RenderMetrics::with_font_metrics(&font.metrics());
|
||||
|
||||
let max_rows_on_screen = ((term_window.dimensions.pixel_height * 8 / 10)
|
||||
let mut max_rows_on_screen = ((term_window.dimensions.pixel_height * 8 / 10)
|
||||
/ metrics.cell_size.height as usize)
|
||||
- 2;
|
||||
if let Some(size) = term_window.config.command_palette_rows {
|
||||
max_rows_on_screen = max_rows_on_screen.min(size);
|
||||
}
|
||||
*self.max_rows_on_screen.borrow_mut() = max_rows_on_screen;
|
||||
|
||||
let rebuild_matches = results
|
||||
|
@ -111,10 +111,12 @@ impl crate::TermWindow {
|
||||
a: 0.,
|
||||
})
|
||||
},
|
||||
store: true,
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
occlusion_query_set: None,
|
||||
timestamp_writes: None,
|
||||
});
|
||||
cleared = true;
|
||||
|
||||
|
@ -1674,6 +1674,9 @@ impl KeyEvent {
|
||||
if raw_modifiers.contains(Modifiers::SUPER) {
|
||||
modifiers |= 8;
|
||||
}
|
||||
// TODO: Hyper and Meta are not handled yet.
|
||||
// We should somehow detect this?
|
||||
// See: https://github.com/wez/wezterm/pull/4605#issuecomment-1823604708
|
||||
if self.leds.contains(KeyboardLedStatus::CAPS_LOCK) {
|
||||
modifiers |= 64;
|
||||
}
|
||||
@ -1800,7 +1803,6 @@ impl KeyEvent {
|
||||
format!("\x1b[{c};{modifiers}{event_type}~")
|
||||
}
|
||||
Char(shifted_key) => {
|
||||
let mut use_legacy = false;
|
||||
let shifted_key = if *shifted_key == '\x08' {
|
||||
// Backspace is really VERASE -> ASCII DEL
|
||||
'\x7f'
|
||||
@ -1808,22 +1810,24 @@ impl KeyEvent {
|
||||
*shifted_key
|
||||
};
|
||||
|
||||
if !flags.contains(KittyKeyboardFlags::REPORT_ALTERNATE_KEYS)
|
||||
let use_legacy = !flags.contains(KittyKeyboardFlags::REPORT_ALTERNATE_KEYS)
|
||||
&& event_type.is_empty()
|
||||
&& is_legacy_key
|
||||
&& !(flags.contains(KittyKeyboardFlags::DISAMBIGUATE_ESCAPE_CODES)
|
||||
&& (self.modifiers.contains(Modifiers::CTRL)
|
||||
|| self.modifiers.contains(Modifiers::ALT)))
|
||||
{
|
||||
use_legacy = true;
|
||||
}
|
||||
&& !self.modifiers.intersects(
|
||||
Modifiers::SUPER, /* TODO: Hyper and Meta should be added here. */
|
||||
);
|
||||
|
||||
if use_legacy {
|
||||
// Legacy text key
|
||||
// https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-text-keys
|
||||
let mut output = String::new();
|
||||
if self.modifiers.contains(Modifiers::ALT) {
|
||||
output.push('\x1b');
|
||||
}
|
||||
|
||||
if self.modifiers.contains(Modifiers::CTRL) {
|
||||
csi_u_encode(
|
||||
&mut output,
|
||||
@ -1833,6 +1837,7 @@ impl KeyEvent {
|
||||
} else {
|
||||
output.push(shifted_key);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -3054,4 +3059,69 @@ mod test {
|
||||
"".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_issue_4436() {
|
||||
let flags = KittyKeyboardFlags::DISAMBIGUATE_ESCAPE_CODES;
|
||||
|
||||
assert_eq!(
|
||||
KeyEvent {
|
||||
key: KeyCode::Char('q'),
|
||||
modifiers: Modifiers::NONE,
|
||||
leds: KeyboardLedStatus::empty(),
|
||||
repeat_count: 1,
|
||||
key_is_down: true,
|
||||
raw: None,
|
||||
#[cfg(windows)]
|
||||
win32_uni_char: None,
|
||||
}
|
||||
.encode_kitty(flags),
|
||||
"q".to_string()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
KeyEvent {
|
||||
key: KeyCode::Char('f'),
|
||||
modifiers: Modifiers::SUPER,
|
||||
leds: KeyboardLedStatus::empty(),
|
||||
repeat_count: 1,
|
||||
key_is_down: true,
|
||||
raw: None,
|
||||
#[cfg(windows)]
|
||||
win32_uni_char: None,
|
||||
}
|
||||
.encode_kitty(flags),
|
||||
"\u{1b}[102;9u".to_string()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
KeyEvent {
|
||||
key: KeyCode::Char('f'),
|
||||
modifiers: Modifiers::SUPER | Modifiers::SHIFT,
|
||||
leds: KeyboardLedStatus::empty(),
|
||||
repeat_count: 1,
|
||||
key_is_down: true,
|
||||
raw: None,
|
||||
#[cfg(windows)]
|
||||
win32_uni_char: None,
|
||||
}
|
||||
.encode_kitty(flags),
|
||||
"\u{1b}[102;10u".to_string()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
KeyEvent {
|
||||
key: KeyCode::Char('f'),
|
||||
modifiers: Modifiers::SUPER | Modifiers::SHIFT | Modifiers::CTRL,
|
||||
leds: KeyboardLedStatus::empty(),
|
||||
repeat_count: 1,
|
||||
key_is_down: true,
|
||||
raw: None,
|
||||
#[cfg(windows)]
|
||||
win32_uni_char: None,
|
||||
}
|
||||
.encode_kitty(flags),
|
||||
"\u{1b}[102;14u".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -337,6 +337,13 @@ enum Message {
|
||||
|
||||
#[derive(Debug, Parser, Clone)]
|
||||
pub struct RecordCommand {
|
||||
/// Start in the specified directory, instead of
|
||||
/// the default_cwd defined by your wezterm configuration
|
||||
#[arg(long)]
|
||||
cwd: Option<std::path::PathBuf>,
|
||||
|
||||
/// Start prog instead of the default_prog defined by your
|
||||
/// wezterm configuration
|
||||
#[arg(value_parser)]
|
||||
prog: Vec<OsString>,
|
||||
}
|
||||
@ -369,7 +376,7 @@ impl RecordCommand {
|
||||
Some(prog)
|
||||
},
|
||||
config.default_prog.as_ref(),
|
||||
config.default_cwd.as_ref(),
|
||||
self.cwd.as_ref().or(config.default_cwd.as_ref()),
|
||||
)?;
|
||||
|
||||
let mut child = pair.slave.spawn_command(cmd)?;
|
||||
|
@ -75,7 +75,7 @@ xcb = {version="1.2", features=["render", "randr", "dri2", "xkb", "xlib_xcb", "p
|
||||
xkbcommon = { version = "0.5.0", features = ["x11", "wayland"] }
|
||||
mio = {version="0.8", features=["os-ext"]}
|
||||
libc = "0.2"
|
||||
smithay-client-toolkit = {version = "0.16", default-features=false, optional=true}
|
||||
smithay-client-toolkit = {version = "0.16.1", default-features=false, optional=true}
|
||||
wayland-protocols = {version="0.29", optional=true}
|
||||
wayland-client = {version="0.29", optional=true}
|
||||
wayland-egl = {version="0.29", optional=true}
|
||||
|
@ -7,6 +7,7 @@ use cocoa::appkit::NSApplicationTerminateReply;
|
||||
use cocoa::base::id;
|
||||
use cocoa::foundation::NSInteger;
|
||||
use config::keyassignment::KeyAssignment;
|
||||
use config::WindowCloseConfirmation;
|
||||
use objc::declare::ClassDecl;
|
||||
use objc::rc::StrongPtr;
|
||||
use objc::runtime::{Class, Object, Sel, BOOL, NO, YES};
|
||||
@ -21,35 +22,44 @@ extern "C" fn application_should_terminate(
|
||||
) -> u64 {
|
||||
log::debug!("application termination requested");
|
||||
unsafe {
|
||||
let alert: id = msg_send![class!(NSAlert), alloc];
|
||||
let alert: id = msg_send![alert, init];
|
||||
let message_text = nsstring("Terminate WezTerm?");
|
||||
let info_text = nsstring("Detach and close all panes and terminate wezterm?");
|
||||
let cancel = nsstring("Cancel");
|
||||
let ok = nsstring("Ok");
|
||||
match config::configuration().window_close_confirmation {
|
||||
WindowCloseConfirmation::NeverPrompt => terminate_now(),
|
||||
WindowCloseConfirmation::AlwaysPrompt => {
|
||||
let alert: id = msg_send![class!(NSAlert), alloc];
|
||||
let alert: id = msg_send![alert, init];
|
||||
let message_text = nsstring("Terminate WezTerm?");
|
||||
let info_text = nsstring("Detach and close all panes and terminate wezterm?");
|
||||
let cancel = nsstring("Cancel");
|
||||
let ok = nsstring("Ok");
|
||||
|
||||
let () = msg_send![alert, setMessageText: message_text];
|
||||
let () = msg_send![alert, setInformativeText: info_text];
|
||||
let () = msg_send![alert, addButtonWithTitle: cancel];
|
||||
let () = msg_send![alert, addButtonWithTitle: ok];
|
||||
#[allow(non_upper_case_globals)]
|
||||
const NSModalResponseCancel: NSInteger = 1000;
|
||||
#[allow(non_upper_case_globals, dead_code)]
|
||||
const NSModalResponseOK: NSInteger = 1001;
|
||||
let result: NSInteger = msg_send![alert, runModal];
|
||||
log::info!("alert result is {result}");
|
||||
let () = msg_send![alert, setMessageText: message_text];
|
||||
let () = msg_send![alert, setInformativeText: info_text];
|
||||
let () = msg_send![alert, addButtonWithTitle: cancel];
|
||||
let () = msg_send![alert, addButtonWithTitle: ok];
|
||||
#[allow(non_upper_case_globals)]
|
||||
const NSModalResponseCancel: NSInteger = 1000;
|
||||
#[allow(non_upper_case_globals, dead_code)]
|
||||
const NSModalResponseOK: NSInteger = 1001;
|
||||
let result: NSInteger = msg_send![alert, runModal];
|
||||
log::info!("alert result is {result}");
|
||||
|
||||
if result == NSModalResponseCancel {
|
||||
NSApplicationTerminateReply::NSTerminateCancel as u64
|
||||
} else {
|
||||
if let Some(conn) = Connection::get() {
|
||||
conn.terminate_message_loop();
|
||||
if result == NSModalResponseCancel {
|
||||
NSApplicationTerminateReply::NSTerminateCancel as u64
|
||||
} else {
|
||||
terminate_now()
|
||||
}
|
||||
}
|
||||
NSApplicationTerminateReply::NSTerminateNow as u64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn terminate_now() -> u64 {
|
||||
if let Some(conn) = Connection::get() {
|
||||
conn.terminate_message_loop();
|
||||
}
|
||||
NSApplicationTerminateReply::NSTerminateNow as u64
|
||||
}
|
||||
|
||||
extern "C" fn application_will_finish_launching(
|
||||
_self: &mut Object,
|
||||
_sel: Sel,
|
||||
|
@ -511,8 +511,7 @@ impl Window {
|
||||
let _: () = msg_send![*window, setRestorable: NO];
|
||||
|
||||
window.setReleasedWhenClosed_(NO);
|
||||
let ns_color: id = msg_send![Class::get("NSColor").unwrap(), alloc];
|
||||
window.setBackgroundColor_(cocoa::appkit::NSColor::clearColor(ns_color));
|
||||
window.setBackgroundColor_(cocoa::appkit::NSColor::clearColor(nil));
|
||||
|
||||
// We could set this, but it makes the entire window, including
|
||||
// its titlebar, opaque to this fixed degree.
|
||||
@ -1734,15 +1733,6 @@ impl WindowView {
|
||||
}
|
||||
}
|
||||
|
||||
/// `dealloc` is called when our NSView descendant is destroyed.
|
||||
/// In practice, I've not seen this trigger, which likely means
|
||||
/// that there is something afoot with reference counting.
|
||||
/// The cardinality of Window and View objects is low enough
|
||||
/// that I'm "OK" with this for now.
|
||||
/// What really matters is that the `Inner` object is dropped
|
||||
/// in a timely fashion once the window is closed, so we manage
|
||||
/// that by hooking into `windowWillClose` and routing both
|
||||
/// `dealloc` and `windowWillClose` to `drop_inner`.
|
||||
fn drop_inner(this: &mut Object) {
|
||||
unsafe {
|
||||
let myself: *mut c_void = *this.get_ivar(VIEW_CLS_NAME);
|
||||
@ -2124,10 +2114,10 @@ impl WindowView {
|
||||
.events
|
||||
.dispatch(WindowEvent::Destroyed);
|
||||
this.update_application_presentation(false);
|
||||
let conn = Connection::get().unwrap();
|
||||
let window_id = this.inner.borrow_mut().window_id;
|
||||
conn.windows.borrow_mut().remove(&window_id);
|
||||
}
|
||||
|
||||
// Release and zero out the inner member
|
||||
Self::drop_inner(this);
|
||||
}
|
||||
|
||||
fn mouse_common(this: &mut Object, nsevent: id, kind: MouseEventKind) {
|
||||
|
Loading…
Reference in New Issue
Block a user