xleak-0.2.6/.cargo_vcs_info.json 0000644 00000000136 00000000001 0012145 0 ustar {
"git": {
"sha1": "f6a62fd83e4fed7b1c69e9908a868813868c0a8c"
},
"path_in_vcs": ""
} xleak-0.2.6/.github/ISSUE_TEMPLATE/bug_report.md 0000644 0000000 0000000 00000001674 10461020230 0017162 0 ustar 0000000 0000000 ---
name: Bug Report
about: Report a bug or issue with xleak
title: '[BUG] '
labels: bug
assignees: ''
---
## Description
## Steps to Reproduce
1.
2.
3.
## Expected Behavior
## Actual Behavior
## Environment
- **xleak version**:
- **OS**:
- **Installation method**:
## Excel File Details (if applicable)
- **File format**:
- **File size**:
- **Number of sheets**:
- **Can you share the file?**:
## Error Message
```
Paste error message here
```
## Additional Context
xleak-0.2.6/.github/ISSUE_TEMPLATE/feature_request.md 0000644 0000000 0000000 00000001274 10461020230 0020211 0 ustar 0000000 0000000 ---
name: Feature Request
about: Suggest a new feature or enhancement
title: '[FEATURE] '
labels: enhancement
assignees: ''
---
## Feature Description
## Problem or Use Case
## Proposed Solution
## Alternatives Considered
## Additional Context
## Implementation Notes
xleak-0.2.6/.github/ISSUE_TEMPLATE/release.md 0000644 0000000 0000000 00000006566 10461020230 0016437 0 ustar 0000000 0000000 ---
name: Release
about: Track a new version release
title: 'Release vX.Y.Z'
labels: release
assignees: ''
---
## Release Version
**Version:** vX.Y.Z
## Pre-Release Checklist
- [ ] All tests passing: `cargo test`
- [ ] No clippy warnings: `cargo clippy`
- [ ] Code is formatted: `cargo fmt --check`
- [ ] CHANGELOG.md updated with new version changes
- [ ] Version bumped in `Cargo.toml`
- [ ] Test binary works: `cargo run --release -- test_data.xlsx`
## Create Release
- [ ] Commit version bump: `git commit -m "chore: release X.Y.Z"`
- [ ] Push to main: `git push`
- [ ] Create version tag: `git tag vX.Y.Z`
- [ ] Push tag: `git push origin vX.Y.Z`
- [ ] Wait for GitHub Actions workflows to complete (~10-15 minutes)
## Automated Release Verification
All publishing is automated. Verify these workflows complete successfully:
### Core Release (`.github/workflows/release.yml`)
- [ ] GitHub Release created at https://github.com/bgreenwell/xleak/releases/tag/vX.Y.Z
- [ ] All artifacts present (binaries, tarballs, installers, checksums)
- [ ] Homebrew formula published to [homebrew-tap](https://github.com/bgreenwell/homebrew-tap)
- [ ] Published to [crates.io](https://crates.io/crates/xleak)
### Scoop Publishing (`.github/workflows/publish-scoop.yml`)
- [ ] Manifest updated in [scoop-bucket](https://github.com/bgreenwell/scoop-bucket)
- [ ] Manifest uses correct ZIP file and SHA256
### AUR Publishing (`.github/workflows/publish-aur.yml`)
- [ ] PKGBUILD updated in [AUR package](https://aur.archlinux.org/packages/xleak-bin)
- [ ] .SRCINFO generated correctly
- [ ] Version, URL, and SHA256 correct
### WinGet Publishing (`.github/workflows/publish-winget.yml`)
- [ ] PR created to [microsoft/winget-pkgs](https://github.com/microsoft/winget-pkgs)
- [ ] PR validation checks passing
- [ ] PR merged (may take 1-2 days, requires Microsoft approval)
## Test Installations
Test at least one platform from each category:
- [ ] Homebrew (macOS/Linux): `brew upgrade xleak && xleak --version`
- [ ] Scoop (Windows): `scoop update xleak && xleak --version`
- [ ] AUR (Arch Linux): `yay -Syu xleak-bin && xleak --version`
- [ ] WinGet (Windows): `winget upgrade bgreenwell.xleak` (after PR merge)
- [ ] Shell installer: Test install script from releases
- [ ] MSI installer: Download and test from GitHub Releases
## Troubleshooting
If any automated workflow fails:
1. Check GitHub Actions logs for specific errors
2. Verify secrets are configured:
- `HOMEBREW_TAP_TOKEN`
- `SCOOP_BUCKET_TOKEN`
- `CARGO_REGISTRY_TOKEN`
- `AUR_SSH_PRIVATE_KEY`
- `WINGET_TOKEN`
3. See RELEASE_CHECKLIST.md for detailed troubleshooting
4. Fall back to manual publishing if needed (instructions in RELEASE_CHECKLIST.md)
### Known Issues
- **WinGet PR merge delay**: First-time submissions may take longer for review
- **AUR SSH timeout**: Retry workflow if AUR connection times out
## Post-Release
- [ ] All workflows completed successfully
- [ ] Installation tests passed on multiple platforms
- [ ] Announcement drafted (if applicable)
- [ ] Documentation updated if needed
- [ ] Monitor for installation issues on GitHub Discussions/Issues
- [ ] Close this issue
## Notes
---
**Automation Status:**
- Fully automated: GitHub Releases, Homebrew, Scoop, crates.io, AUR
- Semi-automated: WinGet (PR created automatically, merge requires approval)
xleak-0.2.6/.github/dependabot.yml.disabled 0000644 0000000 0000000 00000002411 10461020230 0016671 0 ustar 0000000 0000000 # GitHub Dependabot configuration for doxx - DISABLED
# See: https://docs.github.com/en/code-security/dependabot
#
# This is disabled during early development to avoid PR spam.
# Rename to dependabot.yml when project is stable and ready for automated dependency updates.
version: 2
updates:
# Rust dependencies
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "UTC"
open-pull-requests-limit: 3
reviewers:
- "bgreenwell"
assignees:
- "bgreenwell"
commit-message:
prefix: "deps"
include: "scope"
labels:
- "dependencies"
- "rust"
# Group ALL updates to reduce PR noise
groups:
rust-dependencies:
patterns:
- "*"
update-types:
- "minor"
- "patch"
- "major"
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "UTC"
open-pull-requests-limit: 2
reviewers:
- "bgreenwell"
assignees:
- "bgreenwell"
commit-message:
prefix: "ci"
include: "scope"
labels:
- "dependencies"
- "github-actions" xleak-0.2.6/.github/workflows/ci.yml 0000644 0000000 0000000 00000002534 10461020230 0015454 0 ustar 0000000 0000000 name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
jobs:
test:
name: Build and Test
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Install system dependencies (Linux)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y libxcb-shape0-dev libxcb-xfixes0-dev
- name: Cache dependencies
uses: Swatinem/rust-cache@v2
- name: Check formatting (Unix only)
if: matrix.os != 'windows-latest'
run: cargo fmt --all -- --check
- name: Lint with Clippy
run: cargo clippy --all-targets -- -D warnings
- name: Check build
run: cargo build --release
- name: Run tests
run: cargo test --verbose
# Nix build
- name: Install Nix
if: matrix.os != 'windows-latest'
uses: cachix/install-nix-action@v31
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: Build with Nix
if: matrix.os != 'windows-latest'
run: nix build
xleak-0.2.6/.github/workflows/docs.yml 0000644 0000000 0000000 00000003320 10461020230 0016003 0 ustar 0000000 0000000 name: Deploy Documentation
on:
push:
branches: ["main"]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
if: ${{ github.actor == 'bgreenwell' }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache dependencies
uses: Swatinem/rust-cache@v2
- name: Build documentation
run: cargo doc --no-deps
- name: Create redirect page
run: echo '' > target/doc/index.html
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
continue-on-error: true
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: "./target/doc"
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
if: success()
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
continue-on-error: true
- name: Pages deployment status
run: |
if [ "${{ steps.deployment.outcome }}" == "failure" ]; then
echo "::warning::GitHub Pages deployment failed. Please enable Pages in repository settings:"
echo "::warning::1. Go to Settings > Pages"
echo "::warning::2. Set Source to 'GitHub Actions'"
echo "::warning::3. Re-run this workflow"
else
echo "Documentation deployed successfully!"
fi
xleak-0.2.6/.github/workflows/publish-aur.yml 0000644 0000000 0000000 00000010061 10461020230 0017306 0 ustar 0000000 0000000 name: Publish to AUR
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Release tag to publish (e.g., v0.2.5)'
required: true
type: string
permissions:
contents: read
jobs:
publish-aur:
runs-on: ubuntu-22.04
if: ${{ !github.event.release.prerelease }}
steps:
- name: Determine release version
id: get-version
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
TAG="${{ inputs.tag }}"
else
TAG="${{ github.event.release.tag_name }}"
fi
VERSION="${TAG#v}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: Checkout xleak repository
uses: actions/checkout@v4
with:
path: xleak
- name: Download release tarball and SHA256
run: |
VERSION="${{ steps.get-version.outputs.version }}"
TARBALL="xleak-x86_64-unknown-linux-gnu.tar.xz"
SHA_FILE="${TARBALL}.sha256"
cd xleak
gh release download "v${VERSION}" \
--pattern "$SHA_FILE"
SHA256=$(cat "$SHA_FILE" | cut -d ' ' -f 1)
echo "sha256=$SHA256" >> $GITHUB_OUTPUT
echo "tarball=$TARBALL" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
id: download
- name: Generate PKGBUILD
run: |
VERSION="${{ steps.get-version.outputs.version }}"
SHA256="${{ steps.download.outputs.sha256 }}"
TARBALL="${{ steps.download.outputs.tarball }}"
cat > PKGBUILD << 'EOF'
# Maintainer: Brandon Greenwell
pkgname=xleak-bin
pkgver=VERSION_PLACEHOLDER
pkgrel=1
pkgdesc="A fast terminal Excel viewer with interactive TUI, search, formulas, and export capabilities"
url="https://github.com/bgreenwell/xleak"
license=("MIT")
arch=("x86_64")
provides=("xleak")
conflicts=("xleak")
source=("https://github.com/bgreenwell/xleak/releases/download/v$pkgver/TARBALL_PLACEHOLDER")
sha256sums=("SHA256_PLACEHOLDER")
package() {
cd "$srcdir/xleak-x86_64-unknown-linux-gnu"
install -Dm755 xleak -t "$pkgdir/usr/bin"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}
EOF
sed -i "s/VERSION_PLACEHOLDER/$VERSION/" PKGBUILD
sed -i "s/TARBALL_PLACEHOLDER/$TARBALL/" PKGBUILD
sed -i "s/SHA256_PLACEHOLDER/$SHA256/" PKGBUILD
- name: Generate .SRCINFO
uses: addnab/docker-run-action@v3
with:
image: archlinux:latest
options: -v ${{ github.workspace }}:/workspace
run: |
cd /workspace
useradd -m builder
chown -R builder:builder .
su builder -c 'makepkg --printsrcinfo' > .SRCINFO
- name: Fix permissions after Docker
run: |
sudo chown -R $USER:$USER ${{ github.workspace }}
- name: Setup SSH for AUR
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
- name: Configure SSH for AUR
run: |
mkdir -p ~/.ssh
ssh-keyscan -t rsa,ecdsa,ed25519 aur.archlinux.org >> ~/.ssh/known_hosts
- name: Clone AUR repository
run: |
git clone ssh://aur@aur.archlinux.org/xleak-bin.git aur-repo
- name: Update AUR repository
run: |
VERSION="${{ steps.get-version.outputs.version }}"
cp PKGBUILD aur-repo/
cp .SRCINFO aur-repo/
cd aur-repo
git config user.name "Brandon Greenwell"
git config user.email "greenwell.brandon@gmail.com"
git add PKGBUILD .SRCINFO
if git diff --staged --quiet; then
echo "No changes to commit"
else
git commit -m "Update to v${VERSION}"
git push origin master
fi
xleak-0.2.6/.github/workflows/publish-scoop.yml 0000644 0000000 0000000 00000006255 10461020230 0017654 0 ustar 0000000 0000000 name: Publish Scoop Manifest
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Release tag to publish (e.g., v0.2.5)'
required: true
type: string
permissions:
contents: read
jobs:
publish-scoop:
runs-on: ubuntu-22.04
if: ${{ !github.event.release.prerelease || github.event.repository.allow_prerelease }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_USER: "axo bot"
GITHUB_EMAIL: "admin+bot@axo.dev"
steps:
- name: Determine release tag
id: get-tag
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT"
else
echo "tag=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT"
fi
- name: Checkout Scoop bucket
uses: actions/checkout@v4
with:
repository: bgreenwell/scoop-bucket
token: ${{ secrets.SCOOP_BUCKET_TOKEN }}
path: scoop-bucket
- name: Download release artifacts
run: |
TAG="${{ steps.get-tag.outputs.tag }}"
VERSION="${TAG#v}"
ZIP_FILE="xleak-x86_64-pc-windows-msvc.zip"
SHA_FILE="${ZIP_FILE}.sha256"
gh release download "$TAG" \
--repo bgreenwell/xleak \
--pattern "$ZIP_FILE" \
--pattern "$SHA_FILE"
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "ZIP_FILE=$ZIP_FILE" >> $GITHUB_ENV
echo "SHA_FILE=$SHA_FILE" >> $GITHUB_ENV
- name: Generate Scoop manifest
run: |
SHA256=$(cat "$SHA_FILE" | cut -d ' ' -f 1)
DOWNLOAD_URL="https://github.com/bgreenwell/xleak/releases/download/v${VERSION}/${ZIP_FILE}"
mkdir -p scoop-bucket/bucket
jq -n \
--arg version "${VERSION}" \
--arg url "${DOWNLOAD_URL}" \
--arg hash "${SHA256}" \
'{
version: $version,
description: "A fast terminal Excel viewer with interactive TUI, search, formulas, and export capabilities",
homepage: "https://github.com/bgreenwell/xleak",
license: "MIT",
architecture: {
"64bit": {
url: $url,
hash: $hash
}
},
bin: "xleak.exe",
checkver: {
github: "https://github.com/bgreenwell/xleak"
},
autoupdate: {
architecture: {
"64bit": {
url: "https://github.com/bgreenwell/xleak/releases/download/v$version/xleak-x86_64-pc-windows-msvc.zip"
}
}
}
}' > scoop-bucket/bucket/xleak.json
- name: Commit and push manifest
working-directory: scoop-bucket
run: |
git config user.name "${GITHUB_USER}"
git config user.email "${GITHUB_EMAIL}"
git add bucket/xleak.json
if git diff --staged --quiet; then
echo "No changes to commit"
else
git commit -m "xleak ${VERSION}"
git push
fi
xleak-0.2.6/.github/workflows/publish-winget.yml 0000644 0000000 0000000 00000002171 10461020230 0020017 0 ustar 0000000 0000000 name: Publish to WinGet
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Release tag to publish (e.g., v0.2.5)'
required: true
type: string
permissions:
contents: read
jobs:
publish-winget:
runs-on: ubuntu-latest
if: ${{ !github.event.release.prerelease }}
steps:
- name: Determine release version
id: get-version
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
TAG="${{ inputs.tag }}"
else
TAG="${{ github.event.release.tag_name }}"
fi
VERSION="${TAG#v}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: Publish to WinGet with Komac
uses: michidk/run-komac@v2
with:
args: 'new --version ${{ steps.get-version.outputs.version }} --urls "https://github.com/bgreenwell/xleak/releases/download/${{ steps.get-version.outputs.tag }}/xleak-x86_64-pc-windows-msvc.msi" --submit bgreenwell.xleak'
env:
GITHUB_TOKEN: ${{ secrets.WINGET_TOKEN }}
xleak-0.2.6/.github/workflows/release.yml 0000644 0000000 0000000 00000034235 10461020230 0016504 0 ustar 0000000 0000000 # This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist
#
# Copyright 2022-2024, axodotdev
# SPDX-License-Identifier: MIT or Apache-2.0
#
# CI that:
#
# * checks for a Git Tag that looks like a release
# * builds artifacts with dist (archives, installers, hashes)
# * uploads those artifacts to temporary workflow zip
# * on success, uploads the artifacts to a GitHub Release
#
# Note that the GitHub Release will be created with a generated
# title/body based on your changelogs.
name: Release
permissions:
"contents": "write"
# This task will run whenever you push a git tag that looks like a version
# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc.
# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where
# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION
# must be a Cargo-style SemVer Version (must have at least major.minor.patch).
#
# If PACKAGE_NAME is specified, then the announcement will be for that
# package (erroring out if it doesn't have the given version or isn't dist-able).
#
# If PACKAGE_NAME isn't specified, then the announcement will be for all
# (dist-able) packages in the workspace with that version (this mode is
# intended for workspaces with only one dist-able package, or with all dist-able
# packages versioned/released in lockstep).
#
# If you push multiple tags at once, separate instances of this workflow will
# spin up, creating an independent announcement for each one. However, GitHub
# will hard limit this to 3 tags per commit, as it will assume more tags is a
# mistake.
#
# If there's a prerelease-style suffix to the version, then the release(s)
# will be marked as a prerelease.
on:
pull_request:
push:
tags:
- '**[0-9]+.[0-9]+.[0-9]+*'
jobs:
# Run 'dist plan' (or host) to determine what tasks we need to do
plan:
runs-on: "ubuntu-22.04"
outputs:
val: ${{ steps.plan.outputs.manifest }}
tag: ${{ !github.event.pull_request && github.ref_name || '' }}
tag-flag: ${{ !github.event.pull_request && format('--tag={0}', github.ref_name) || '' }}
publishing: ${{ !github.event.pull_request }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
submodules: recursive
- name: Install dist
# we specify bash to get pipefail; it guards against the `curl` command
# failing. otherwise `sh` won't catch that `curl` returned non-0
shell: bash
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.30.2/cargo-dist-installer.sh | sh"
- name: Cache dist
uses: actions/upload-artifact@v4
with:
name: cargo-dist-cache
path: ~/.cargo/bin/dist
# sure would be cool if github gave us proper conditionals...
# so here's a doubly-nested ternary-via-truthiness to try to provide the best possible
# functionality based on whether this is a pull_request, and whether it's from a fork.
# (PRs run on the *source* but secrets are usually on the *target* -- that's *good*
# but also really annoying to build CI around when it needs secrets to work right.)
- id: plan
run: |
dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json
echo "dist ran successfully"
cat plan-dist-manifest.json
echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT"
- name: "Upload dist-manifest.json"
uses: actions/upload-artifact@v4
with:
name: artifacts-plan-dist-manifest
path: plan-dist-manifest.json
# Build and packages all the platform-specific things
build-local-artifacts:
name: build-local-artifacts (${{ join(matrix.targets, ', ') }})
# Let the initial task tell us to not run (currently very blunt)
needs:
- plan
if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }}
strategy:
fail-fast: false
# Target platforms/runners are computed by dist in create-release.
# Each member of the matrix has the following arguments:
#
# - runner: the github runner
# - dist-args: cli flags to pass to dist
# - install-dist: expression to run to install dist on the runner
#
# Typically there will be:
# - 1 "global" task that builds universal installers
# - N "local" tasks that build each platform's binaries and platform-specific installers
matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }}
runs-on: ${{ matrix.runner }}
container: ${{ matrix.container && matrix.container.image || null }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json
steps:
- name: enable windows longpaths
run: |
git config --global core.longpaths true
- uses: actions/checkout@v4
with:
persist-credentials: false
submodules: recursive
- name: Install Rust non-interactively if not already installed
if: ${{ matrix.container }}
run: |
if ! command -v cargo > /dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
fi
- name: Install dist
run: ${{ matrix.install_dist.run }}
# Get the dist-manifest
- name: Fetch local artifacts
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: target/distrib/
merge-multiple: true
- name: Install dependencies
run: |
${{ matrix.packages_install }}
- name: Build artifacts
run: |
# Actually do builds and make zips and whatnot
dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json
echo "dist ran successfully"
- id: cargo-dist
name: Post-build
# We force bash here just because github makes it really hard to get values up
# to "real" actions without writing to env-vars, and writing to env-vars has
# inconsistent syntax between shell and powershell.
shell: bash
run: |
# Parse out what we just built and upload it to scratch storage
echo "paths<> "$GITHUB_OUTPUT"
dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
cp dist-manifest.json "$BUILD_MANIFEST_NAME"
- name: "Upload artifacts"
uses: actions/upload-artifact@v4
with:
name: artifacts-build-local-${{ join(matrix.targets, '_') }}
path: |
${{ steps.cargo-dist.outputs.paths }}
${{ env.BUILD_MANIFEST_NAME }}
# Build and package all the platform-agnostic(ish) things
build-global-artifacts:
needs:
- plan
- build-local-artifacts
runs-on: "ubuntu-22.04"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
submodules: recursive
- name: Install cached dist
uses: actions/download-artifact@v4
with:
name: cargo-dist-cache
path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/dist
# Get all the local artifacts for the global tasks to use (for e.g. checksums)
- name: Fetch local artifacts
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: target/distrib/
merge-multiple: true
- id: cargo-dist
shell: bash
run: |
dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json
echo "dist ran successfully"
# Parse out what we just built and upload it to scratch storage
echo "paths<> "$GITHUB_OUTPUT"
jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
cp dist-manifest.json "$BUILD_MANIFEST_NAME"
- name: "Upload artifacts"
uses: actions/upload-artifact@v4
with:
name: artifacts-build-global
path: |
${{ steps.cargo-dist.outputs.paths }}
${{ env.BUILD_MANIFEST_NAME }}
# Determines if we should publish/announce
host:
needs:
- plan
- build-local-artifacts
- build-global-artifacts
# Only run if we're "publishing", and only if plan, local and global didn't fail (skipped is fine)
if: ${{ always() && needs.plan.result == 'success' && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
runs-on: "ubuntu-22.04"
outputs:
val: ${{ steps.host.outputs.manifest }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
submodules: recursive
- name: Install cached dist
uses: actions/download-artifact@v4
with:
name: cargo-dist-cache
path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/dist
# Fetch artifacts from scratch-storage
- name: Fetch artifacts
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: target/distrib/
merge-multiple: true
- id: host
shell: bash
run: |
dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json
echo "artifacts uploaded and released successfully"
cat dist-manifest.json
echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT"
- name: "Upload dist-manifest.json"
uses: actions/upload-artifact@v4
with:
# Overwrite the previous copy
name: artifacts-dist-manifest
path: dist-manifest.json
# Create a GitHub Release while uploading all files to it
- name: "Download GitHub Artifacts"
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: artifacts
merge-multiple: true
- name: Cleanup
run: |
# Remove the granular manifests
rm -f artifacts/*-dist-manifest.json
- name: Create GitHub Release
env:
PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}"
ANNOUNCEMENT_TITLE: "${{ fromJson(steps.host.outputs.manifest).announcement_title }}"
ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}"
RELEASE_COMMIT: "${{ github.sha }}"
run: |
# Write and read notes from a file to avoid quoting breaking things
echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt
gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/*
publish-homebrew-formula:
needs:
- plan
- host
runs-on: "ubuntu-22.04"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PLAN: ${{ needs.plan.outputs.val }}
GITHUB_USER: "axo bot"
GITHUB_EMAIL: "admin+bot@axo.dev"
if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: true
repository: "bgreenwell/homebrew-tap"
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
# So we have access to the formula
- name: Fetch homebrew formulae
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: Formula/
merge-multiple: true
# This is extra complex because you can make your Formula name not match your app name
# so we need to find releases with a *.rb file, and publish with that filename.
- name: Commit formula files
run: |
git config --global user.name "${GITHUB_USER}"
git config --global user.email "${GITHUB_EMAIL}"
for release in $(echo "$PLAN" | jq --compact-output '.releases[] | select([.artifacts[] | endswith(".rb")] | any)'); do
filename=$(echo "$release" | jq '.artifacts[] | select(endswith(".rb"))' --raw-output)
name=$(echo "$filename" | sed "s/\.rb$//")
version=$(echo "$release" | jq .app_version --raw-output)
export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"
brew update
# We avoid reformatting user-provided data such as the app description and homepage.
brew style --except-cops FormulaAudit/Homepage,FormulaAudit/Desc,FormulaAuditStrict --fix "Formula/${filename}" || true
git add "Formula/${filename}"
git commit -m "${name} ${version}"
done
git push
announce:
needs:
- plan
- host
- publish-homebrew-formula
# use "always() && ..." to allow us to wait for all publish jobs while
# still allowing individual publish jobs to skip themselves (for prereleases).
# "host" however must run to completion, no skipping allowed!
if: ${{ always() && needs.host.result == 'success' && (needs.publish-homebrew-formula.result == 'skipped' || needs.publish-homebrew-formula.result == 'success') }}
runs-on: "ubuntu-22.04"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
submodules: recursive
xleak-0.2.6/.gitignore 0000644 0000000 0000000 00000000407 10461020230 0012726 0 ustar 0000000 0000000 # Rust
/target
**/*.rs.bk
*.pdb
# Test/generated files
*.xlsx
*.xls
*.xlsm
*.xlsb
*.ods
*.csv
tests/fixtures/deprecated/
# macOS
.DS_Store
# Windows
Thumbs.db
# IDEs
.vscode/
.idea/
*.swp
*.swo
*~
# Local
CLAUDE.md
.planning/
scoop-bucket/
.winget-manifest/
xleak-0.2.6/AGENTS.md 0000644 0000000 0000000 00000005366 10461020230 0012252 0 ustar 0000000 0000000 # xleak
Excel terminal viewer written in Rust with TUI, search, formulas, and export capabilities.
**Stack:** Rust 2024, calamine, clap, ratatui + crossterm, anyhow, comfy-table, arboard, chrono
**Formats:** `.xlsx`, `.xls`, `.xlsm`, `.xlsb`, `.ods`
**Key files:** `main.rs`, `workbook.rs`, `tui.rs`, `display.rs` in `src/`
## Commands
```bash
cargo fmt && cargo clippy && cargo build --release
cargo run -- tests/fixtures/test_comprehensive.xlsx -i
cargo run -- tests/fixtures/test_comprehensive.xlsx --sheet Formulas --export csv
cd tests/fixtures && uv run python generate_all_tests.py # regenerate fixtures
cargo install --path . # install globally
```
## Architecture
- `main.rs` — CLI parsing, orchestration
- `workbook.rs` — Excel I/O, data extraction (calamine)
- `tui.rs` — Interactive TUI state and rendering (ratatui)
- `display.rs` — Non-interactive output (terminal, CSV, JSON, text) via comfy-table
## Code Style
- Fix all `cargo clippy` warnings; run `cargo fmt` before committing
- Error handling: `anyhow::Result` with `.context()` for messages
- Comments: only when "why" is non-obvious; doc comments for public APIs
- `CellValue` enum: exhaustive pattern matching required
- Use `--release` for performance testing; use `-n` to limit rows on large files
## Common Patterns
- **New CLI option:** field on `Cli` in `main.rs`, clap macros, handle in `main()`
- **New export format:** `export_()` in `display.rs`, match arm in `main()`
- **Fix display:** `display_table()` in `display.rs`, test with DataTypes sheet
- **New cell type:** `CellValue` enum in `workbook.rs`, impl `Display`, update `datatype_to_cellvalue()`
## Development
Conventional commits: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`.
Feature branches → PR to `main`. Direct commits: releases, hotfixes, minor docs only.
**PR checklist:**
- [ ] Compiles, no clippy warnings, `cargo fmt` clean
- [ ] Tested with fixtures (multiple formats: .xlsx, .xls, .ods)
- [ ] README.md updated (user-facing) or AGENTS.md (architecture changes)
- [ ] Concise entry added to CHANGELOG.md under `[Unreleased]`
**Changelog style:** One line per item, no filler words. Bad: `"Formula cells are now detected and a warning is shown to inform users that..."`. Good: `"Warn when formula cells are blank due to uncached xlsx values"`.
## Release
All distribution channels automated via cargo-dist. See [RELEASE_CHECKLIST.md](./RELEASE_CHECKLIST.md).
- `.github/workflows/release.yml` — GitHub Releases, Homebrew, crates.io
- `.github/workflows/publish-scoop.yml` — Scoop
- `.github/workflows/publish-aur.yml` — AUR
- `.github/workflows/publish-winget.yml` — WinGet
Check `.planning/` (untracked) for planning docs before starting large features.
xleak-0.2.6/CHANGELOG.md 0000644 0000000 0000000 00000013417 10461020230 0012554 0 ustar 0000000 0000000 # Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.2.6] - 2026-05-24
### Added
- NetBSD installation via `pkgin install xleak` (thanks [@0323pin](https://github.com/0323pin)! [#40](https://github.com/bgreenwell/xleak/pull/40))
- Automated AUR, WinGet, and Scoop publishing via GitHub Actions
- Warn when formula cells are blank due to uncached xlsx values (`NOTE:` before table, suggests `--formulas` or re-saving in Excel/LibreOffice)
### Changed
- Upgrade `calamine` 0.26 → 0.34 and `dirs` 5.0 → 6.0 for Debian packaging compatibility (thanks [@nadzyah](https://github.com/nadzyah)! [#43](https://github.com/bgreenwell/xleak/pull/43))
- Nix flake version now read dynamically from Cargo.toml; homepage URL fixed
- Replaced `prettytable-rs` with `comfy-table` for non-interactive output, enabling correct multiline cell wrapping with `--wrap` ([#44](https://github.com/bgreenwell/xleak/pull/44))
- Non-interactive table output: green bold headers, red errors, green formula-mode cells
### Fixed
- CSV and text export wrote large numbers with thousands separators (e.g. `"18,441,600,422"` instead of `18441600422`), making them unparseable as numbers ([#34](https://github.com/bgreenwell/xleak/issues/34))
- AUR `xleak-bin` PKGBUILD: `package()` missing `cd "$srcdir/..."` caused install failures
- `?` help keybinding not firing on macOS — macOS terminals omit SHIFT for symbol chars
- Formulas fixture: `Formula` column now shows expression text; `Result` holds the live formula
## [0.2.5] - 2025-12-04
### Fixed
- Help popup not appearing on Windows - `?` key now correctly expects SHIFT modifier (thanks [@aarif](https://github.com/aarif)! [#27](https://github.com/bgreenwell/xleak/issues/27))
- VIM mode `$` keybinding now correctly expects SHIFT modifier on Windows
### Added
- Automated crates.io publishing via custom GitHub Action for all future releases
## [0.2.4] - 2025-12-04
### Fixed
- Time precision issue causing seconds to be off by 1 due to floating point truncation (thanks [@Xuquansheng](https://github.com/Xuquansheng)! [#25](https://github.com/bgreenwell/xleak/issues/25))
### Changed
- Enhanced installation documentation with Scoop (Windows), AUR (Arch Linux), shell/PowerShell installers, and MSI details
- Condensed AGENTS.md from 460 to 117 lines for better maintainability
## [0.2.3] - 2025-12-03
### Fixed
- Date display off by one day - corrected Excel epoch from December 30 to December 31, 1899 (thanks [@Xuquansheng](https://github.com/Xuquansheng)! [#25](https://github.com/bgreenwell/xleak/issues/25))
### Changed
- Consolidated test fixtures from 6 files to 3 standardized files (test_comprehensive.xlsx, test_large.xlsx, test_tables.xlsx)
### Added
- Release checklist and GitHub issue templates (Bug Report, Feature Request, Release)
## [0.2.0] - 2025-12-03
### Changed
- Migrated to cargo-dist for automated multi-platform releases
- Release process now supports shell/PowerShell installers and Homebrew tap updates
## [0.1.1] - 2025-12-03
### Added
- Configuration file support via TOML at `~/.config/xleak/config.toml` (thanks [@izelnakri](https://github.com/izelnakri) for the suggestion! [#1](https://github.com/bgreenwell/xleak/issues/1))
- Six built-in color themes: Default, Dracula, Solarized Dark/Light, GitHub Dark, Nord
- VIM keybinding profile with hjkl navigation, gg/G jumps, and yank operations
- Custom keybinding overrides for 23 different actions
- `--config` flag to specify custom configuration file location
- Excel Table support (.xlsx only) with `--list-tables` and `--table` flags (thanks [@jgranduel](https://github.com/jgranduel)! [#18](https://github.com/bgreenwell/xleak/issues/18), [#21](https://github.com/bgreenwell/xleak/pull/21))
- Horizontal scrolling mode with auto-sized columns via `-H` flag (thanks [@YannickHerrero](https://github.com/YannickHerrero)! [#13](https://github.com/bgreenwell/xleak/pull/13))
- Scrollable cell detail popup for viewing multi-line cells (thanks [@ket000](https://github.com/ket000)! [#16](https://github.com/bgreenwell/xleak/issues/16))
- MIT License (thanks [@hardBSDk](https://github.com/hardBSDk) and [@hwpplayer1](https://github.com/hwpplayer1)! [#6](https://github.com/bgreenwell/xleak/issues/6))
### Changed
- Help screen now includes configuration information
### Fixed
- UTF-8 character boundary panic with multi-byte characters like German umlauts (thanks [@steffenbusch](https://github.com/steffenbusch)! [#11](https://github.com/bgreenwell/xleak/issues/11), [#15](https://github.com/bgreenwell/xleak/pull/15))
- VIM key bindings for `Shift+G` and `$` not working properly (thanks [@hungltth](https://github.com/hungltth)! [#20](https://github.com/bgreenwell/xleak/pull/20))
- Nix installation from GitHub by adding missing `flake.lock` (thanks [@senorsmile](https://github.com/senorsmile)! [#17](https://github.com/bgreenwell/xleak/issues/17))
- Double keypress issue on Windows by filtering key release events (thanks [@clindholm](https://github.com/clindholm)! [#2](https://github.com/bgreenwell/xleak/issues/2), [#4](https://github.com/bgreenwell/xleak/pull/4))
- Needless borrow in table lookup (clippy warning)
## [0.1.0] - 2025-01-08
### Added
- Initial release of xleak
- Interactive TUI mode with ratatui
- Support for multiple Excel formats (.xlsx, .xls, .xlsm, .xlsb, .ods)
- Search functionality across sheets
- Formula display mode
- Export to CSV, JSON, and text formats
- Lazy loading for large files
- Sheet selection
- Row limit option
- Cross-platform support (Linux, macOS, Windows)
[Unreleased]: https://github.com/greenwbm/xleak/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/greenwbm/xleak/releases/tag/v0.1.0
xleak-0.2.6/Cargo.lock 0000644 00000131264 00000000001 0010127 0 ustar # This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "allocator-api2"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
dependencies = [
"windows-sys 0.60.2",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.60.2",
]
[[package]]
name = "anyhow"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
[[package]]
name = "arboard"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf"
dependencies = [
"clipboard-win",
"image",
"log",
"objc2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-foundation",
"parking_lot",
"percent-encoding",
"windows-sys 0.60.2",
"x11rb",
]
[[package]]
name = "atoi_simd"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ad17c7c205c2c28b527b9845eeb91cf1b4d008b438f98ce0e628227a822758e"
dependencies = [
"debug_unsafe",
]
[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "bitflags"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
[[package]]
name = "bumpalo"
version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
[[package]]
name = "bytemuck"
version = "1.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "byteorder-lite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]]
name = "calamine"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20ae05a4e39297eecf9a994210d27501318c37a9318201f8e11050add82bb6f0"
dependencies = [
"atoi_simd",
"byteorder",
"codepage",
"encoding_rs",
"fast-float2",
"log",
"quick-xml",
"serde",
"zip",
]
[[package]]
name = "cassowary"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "castaway"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a"
dependencies = [
"rustversion",
]
[[package]]
name = "cc"
version = "1.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
dependencies = [
"find-msvc-tools",
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "chrono"
version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-link",
]
[[package]]
name = "clap"
version = "4.5.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
[[package]]
name = "clipboard-win"
version = "5.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4"
dependencies = [
"error-code",
]
[[package]]
name = "codepage"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48f68d061bc2828ae826206326e61251aca94c1e4a5305cf52d9138639c918b4"
dependencies = [
"encoding_rs",
]
[[package]]
name = "colorchoice"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "comfy-table"
version = "7.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "958c5d6ecf1f214b4c2bbbbf6ab9523a864bd136dcf71a7e8904799acfe1ad47"
dependencies = [
"crossterm 0.29.0",
"unicode-segmentation",
"unicode-width 0.2.0",
]
[[package]]
name = "compact_str"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
dependencies = [
"castaway",
"cfg-if",
"itoa",
"rustversion",
"ryu",
"static_assertions",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "crc32fast"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossterm"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [
"bitflags",
"crossterm_winapi",
"mio",
"parking_lot",
"rustix 0.38.44",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
dependencies = [
"bitflags",
"crossterm_winapi",
"document-features",
"parking_lot",
"rustix 1.1.2",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
[[package]]
name = "crunchy"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
[[package]]
name = "darling"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "debug_unsafe"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eed2c4702fa172d1ce21078faa7c5203e69f5394d48cc436d25928394a867a2"
[[package]]
name = "dirs"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.61.2",
]
[[package]]
name = "dispatch2"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
dependencies = [
"bitflags",
"objc2",
]
[[package]]
name = "document-features"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61"
dependencies = [
"litrs",
]
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "encoding_rs"
version = "0.8.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
dependencies = [
"cfg-if",
]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.61.2",
]
[[package]]
name = "error-code"
version = "3.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
[[package]]
name = "fast-float2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8eb564c5c7423d25c886fb561d1e4ee69f72354d16918afa32c08811f6b6a55"
[[package]]
name = "fax"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab"
dependencies = [
"fax_derive",
]
[[package]]
name = "fax_derive"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "fdeflate"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
dependencies = [
"simd-adler32",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"
[[package]]
name = "flate2"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
dependencies = [
"crc32fast",
"libz-rs-sys",
"miniz_oxide",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "gethostname"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8"
dependencies = [
"rustix 1.1.2",
"windows-link",
]
[[package]]
name = "getrandom"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "half"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
dependencies = [
"cfg-if",
"crunchy",
"zerocopy",
]
[[package]]
name = "hashbrown"
version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash",
]
[[package]]
name = "hashbrown"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "iana-time-zone"
version = "0.1.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "image"
version = "0.25.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7"
dependencies = [
"bytemuck",
"byteorder-lite",
"moxcms",
"num-traits",
"png",
"tiff",
]
[[package]]
name = "indexmap"
version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f"
dependencies = [
"equivalent",
"hashbrown 0.16.0",
]
[[package]]
name = "indoc"
version = "2.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
dependencies = [
"rustversion",
]
[[package]]
name = "instability"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435d80800b936787d62688c927b6490e887c7ef5ff9ce922c6c6050fca75eb9a"
dependencies = [
"darling",
"indoc",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "js-sys"
version = "0.3.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]]
name = "libredox"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "libz-rs-sys"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c10501e7805cee23da17c7790e59df2870c0d4043ec6d03f67d31e2b53e77415"
dependencies = [
"zlib-rs",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "linux-raw-sys"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
[[package]]
name = "litrs"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
[[package]]
name = "lock_api"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
[[package]]
name = "lru"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
dependencies = [
"hashbrown 0.15.5",
]
[[package]]
name = "memchr"
version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
"simd-adler32",
]
[[package]]
name = "mio"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys 0.61.2",
]
[[package]]
name = "moxcms"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fbdd3d7436f8b5e892b8b7ea114271ff0fa00bc5acae845d53b07d498616ef6"
dependencies = [
"num-traits",
"pxfm",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "objc2"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
dependencies = [
"objc2-encode",
]
[[package]]
name = "objc2-app-kit"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
dependencies = [
"bitflags",
"objc2",
"objc2-core-graphics",
"objc2-foundation",
]
[[package]]
name = "objc2-core-foundation"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
"bitflags",
"dispatch2",
"objc2",
]
[[package]]
name = "objc2-core-graphics"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
dependencies = [
"bitflags",
"dispatch2",
"objc2",
"objc2-core-foundation",
"objc2-io-surface",
]
[[package]]
name = "objc2-encode"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
[[package]]
name = "objc2-foundation"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [
"bitflags",
"objc2",
"objc2-core-foundation",
]
[[package]]
name = "objc2-io-surface"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
dependencies = [
"bitflags",
"objc2",
"objc2-core-foundation",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "once_cell_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "parking_lot"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-link",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "percent-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "png"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0"
dependencies = [
"bitflags",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide",
]
[[package]]
name = "proc-macro2"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [
"unicode-ident",
]
[[package]]
name = "pxfm"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3cbdf373972bf78df4d3b518d07003938e2c7d1fb5891e55f9cb6df57009d84"
dependencies = [
"num-traits",
]
[[package]]
name = "quick-error"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quick-xml"
version = "0.39.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d"
dependencies = [
"encoding_rs",
"memchr",
]
[[package]]
name = "quote"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ratatui"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
dependencies = [
"bitflags",
"cassowary",
"compact_str",
"crossterm 0.28.1",
"indoc",
"instability",
"itertools",
"lru",
"paste",
"strum",
"unicode-segmentation",
"unicode-truncate",
"unicode-width 0.2.0",
]
[[package]]
name = "redox_syscall"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]]
name = "rustix"
version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys 0.4.15",
"windows-sys 0.59.0",
]
[[package]]
name = "rustix"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys 0.11.0",
"windows-sys 0.61.2",
]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
"serde_core",
]
[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
dependencies = [
"serde",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
dependencies = [
"libc",
]
[[package]]
name = "simd-adler32"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "strum"
version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "syn"
version = "2.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tiff"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f"
dependencies = [
"fax",
"flate2",
"half",
"quick-error",
"weezl",
"zune-jpeg",
]
[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"toml_write",
"winnow",
]
[[package]]
name = "toml_write"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "typed-path"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e"
[[package]]
name = "unicode-ident"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "unicode-segmentation"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "unicode-truncate"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
dependencies = [
"itertools",
"unicode-segmentation",
"unicode-width 0.1.14",
]
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unicode-width"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasm-bindgen"
version = "0.2.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76"
dependencies = [
"unicode-ident",
]
[[package]]
name = "weezl"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-implement"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets 0.53.5",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm 0.53.1",
"windows_aarch64_msvc 0.53.1",
"windows_i686_gnu 0.53.1",
"windows_i686_gnullvm 0.53.1",
"windows_i686_msvc 0.53.1",
"windows_x86_64_gnu 0.53.1",
"windows_x86_64_gnullvm 0.53.1",
"windows_x86_64_msvc 0.53.1",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "winnow"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
dependencies = [
"memchr",
]
[[package]]
name = "x11rb"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414"
dependencies = [
"gethostname",
"rustix 1.1.2",
"x11rb-protocol",
]
[[package]]
name = "x11rb-protocol"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
[[package]]
name = "xleak"
version = "0.2.6"
dependencies = [
"anyhow",
"arboard",
"calamine",
"chrono",
"clap",
"comfy-table",
"crossterm 0.28.1",
"dirs",
"ratatui",
"serde",
"serde_json",
"toml",
]
[[package]]
name = "zerocopy"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zip"
version = "7.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0"
dependencies = [
"crc32fast",
"flate2",
"indexmap",
"memchr",
"typed-path",
"zopfli",
]
[[package]]
name = "zlib-rs"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3"
[[package]]
name = "zopfli"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249"
dependencies = [
"bumpalo",
"crc32fast",
"log",
"simd-adler32",
]
[[package]]
name = "zune-core"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
[[package]]
name = "zune-jpeg"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713"
dependencies = [
"zune-core",
]
xleak-0.2.6/Cargo.toml 0000644 00000004362 00000000001 0010150 0 ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2024"
name = "xleak"
version = "0.2.6"
authors = ["Brandon Greenwell "]
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "A fast terminal Excel viewer with interactive TUI, search, formulas, and export capabilities"
homepage = "https://github.com/bgreenwell/xleak"
readme = "README.md"
keywords = [
"excel",
"xlsx",
"terminal",
"viewer",
"tui",
]
categories = [
"command-line-utilities",
"visualization",
]
license = "MIT"
repository = "https://github.com/bgreenwell/xleak"
[package.metadata.release]
pre-release-commit-message = "chore: release {{version}}"
tag-message = "Release {{version}}"
[[package.metadata.release.pre-release-replacements]]
file = "CHANGELOG.md"
search = '## \[Unreleased\]'
replace = """
## [Unreleased]
## [{{version}}] - {{date}}"""
exactly = 1
[package.metadata.aur]
depends = []
makedepends = ["cargo"]
[package.metadata.wix]
upgrade-guid = "7336173b-1ee3-408e-af34-d930507b8941"
path-guid = "67e1bb49-876f-4934-85e4-8faad4ada16f"
license = false
eula = false
[[bin]]
name = "xleak"
path = "src/main.rs"
[dependencies.anyhow]
version = "1.0"
[dependencies.arboard]
version = "3.4"
[dependencies.calamine]
version = "0.34"
[dependencies.chrono]
version = "0.4"
[dependencies.clap]
version = "4.5"
features = ["derive"]
[dependencies.comfy-table]
version = "7.1"
[dependencies.crossterm]
version = "0.28"
[dependencies.dirs]
version = "6"
[dependencies.ratatui]
version = "0.29"
[dependencies.serde]
version = "1.0"
features = ["derive"]
[dependencies.serde_json]
version = "1.0"
[dependencies.toml]
version = "0.8"
[profile.dist]
lto = "thin"
inherits = "release"
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
xleak-0.2.6/Cargo.toml.orig 0000644 0000000 0000000 00000003131 10461020230 0013622 0 ustar 0000000 0000000 [package]
name = "xleak"
version = "0.2.6"
edition = "2024"
authors = ["Brandon Greenwell "]
description = "A fast terminal Excel viewer with interactive TUI, search, formulas, and export capabilities"
license = "MIT"
repository = "https://github.com/bgreenwell/xleak"
homepage = "https://github.com/bgreenwell/xleak"
keywords = ["excel", "xlsx", "terminal", "viewer", "tui"]
categories = ["command-line-utilities", "visualization"]
readme = "README.md"
[dependencies]
calamine = "0.34"
clap = { version = "4.5", features = ["derive"] }
anyhow = "1.0"
comfy-table = "7.1"
# TUI dependencies
ratatui = "0.29"
crossterm = "0.28"
# Date/time handling
chrono = "0.4"
# Clipboard support
arboard = "3.4"
# Configuration file support
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "0.8"
dirs = "6"
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
# The profile that 'dist' will build with
[profile.dist]
inherits = "release"
lto = "thin"
# cargo-release configuration
[package.metadata.release]
pre-release-replacements = [
{ file = "CHANGELOG.md", search = "## \\[Unreleased\\]", replace = "## [Unreleased]\n\n## [{{version}}] - {{date}}", exactly = 1 },
]
pre-release-commit-message = "chore: release {{version}}"
tag-message = "Release {{version}}"
# cargo-aur configuration for Arch Linux
[package.metadata.aur]
depends = []
makedepends = ["cargo"]
# WiX configuration for MSI installer
[package.metadata.wix]
upgrade-guid = "7336173b-1ee3-408e-af34-d930507b8941"
path-guid = "67e1bb49-876f-4934-85e4-8faad4ada16f"
license = false
eula = false
xleak-0.2.6/LICENSE 0000644 0000000 0000000 00000002056 10461020230 0011745 0 ustar 0000000 0000000 MIT License
Copyright (c) 2025 Ben Greenwell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
xleak-0.2.6/README.md 0000644 0000000 0000000 00000034544 10461020230 0012226 0 ustar 0000000 0000000 # xleak
[](https://github.com/bgreenwell/xleak/actions/workflows/ci.yml)
[](https://crates.io/crates/xleak)
[](https://crates.io/crates/xleak)
[](https://opensource.org/licenses/MIT)
[](https://www.rust-lang.org/)
[](#installation)
[](https://github.com/bgreenwell/xleak/releases/latest)
> Expose Excel files in your terminal - no Microsoft Excel required!
Inspired by [doxx](https://github.com/bgreenwell/doxx), `xleak` brings Excel spreadsheets to your command line with beautiful rendering, powerful export capabilities, and a feature-rich interactive TUI.

## Features
### Core Functionality
- **Beautiful terminal rendering** with formatted tables
- **Interactive TUI mode** - full keyboard navigation with ratatui
- **Smart data type handling** - numbers right-aligned, text left-aligned, booleans centered
- **Multi-sheet support** - seamlessly navigate between sheets (Tab/Shift+Tab)
- **Excel Table support** - list and extract named tables (.xlsx only)
- **Multiple export formats** - CSV, JSON, plain text
- **Blazing fast** - powered by `calamine`, the fastest Excel parser in Rust
- **Multiple file formats** - supports `.xlsx`, `.xls`, `.xlsm`, `.xlsb`, `.ods`
### Interactive TUI Features
- **Full-text search** - search across all cells with `/`, navigate with `n`/`N`
- **Clipboard support** - copy cells (`c`) or entire rows (`C`) to clipboard
- **Formula display** - view Excel formulas in cell detail view (Enter key)
- **Jump to row/column** - press `Ctrl+G` to jump to any cell (e.g., `A100`, `500`, `10,5`)
- **Large file optimization** - lazy loading for files with 1000+ rows
- **Progress indicators** - real-time feedback for long operations
- **Visual cell highlighting** - current row, column, and cell clearly marked
## Installation
### Package Managers
**macOS / Linux (Homebrew):**
```bash
brew install bgreenwell/tap/xleak
```
**Windows (Scoop):**
```powershell
scoop bucket add bgreenwell https://github.com/bgreenwell/scoop-bucket
scoop install xleak
```
**Windows (WinGet):** _(Coming soon - pending initial PR merge)_
```powershell
winget install bgreenwell.xleak
```
**Arch Linux (AUR):**
```bash
# Using yay
yay -S xleak-bin
# Or using paru
paru -S xleak-bin
```
**NetBSD:**
```bash
pkgin install xleak
```
**Cargo (all platforms):**
```bash
cargo install xleak
```
**Nix:**
```bash
# Run directly
nix run github:bgreenwell/xleak -- file.xlsx
# Install with flakes
nix profile install github:bgreenwell/xleak
```
### Quick Install Scripts
**macOS / Linux:**
```bash
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/bgreenwell/xleak/releases/latest/download/xleak-installer.sh | sh
```
**Windows (PowerShell):**
```powershell
irm https://github.com/bgreenwell/xleak/releases/latest/download/xleak-installer.ps1 | iex
```
### Pre-built Binaries
Download platform-specific binaries from the [latest release](https://github.com/bgreenwell/xleak/releases/latest):
- **macOS**: Universal binary (Apple Silicon + Intel)
- **Linux**: x86_64 (glibc and musl)
- **Windows**: x86_64 MSI installer or standalone `.exe`
### Build from Source
```bash
git clone https://github.com/bgreenwell/xleak.git
cd xleak
cargo install --path .
```
**Requirements:** Rust 1.70 or later
## Usage
### Interactive TUI Mode (Recommended)
```bash
# Launch interactive viewer
xleak quarterly-report.xlsx -i
# Start on a specific sheet
xleak report.xlsx --sheet "Q3 Results" -i
# View formulas by default
xleak data.xlsx -i --formulas
# Enable horizontal scrolling for wide files (auto-size columns)
xleak wide-data.xlsx -i -H
```
**TUI Keyboard Shortcuts:**
- `↑ ↓ ← →` - Navigate cells
- `Enter` - View cell details (including formulas)
- `/` - Search across all cells
- `n` / `N` - Jump to next/previous search result
- `Ctrl+G` - Jump to specific row/cell (e.g., `100`, `A50`, `10,5`)
- `c` - Copy current cell to clipboard
- `C` - Copy entire row to clipboard
- `Tab` / `Shift+Tab` - Switch between sheets
- `?` - Show help
- `q` - Quit
### Non-Interactive Mode
#### View a spreadsheet
```bash
xleak quarterly-report.xlsx
```
#### View a specific sheet
```bash
# By name
xleak report.xlsx --sheet "Q3 Results"
# By index (1-based)
xleak report.xlsx --sheet 2
```
#### Limit displayed rows
```bash
# Show only first 20 rows
xleak large-file.xlsx -n 20
# Show all rows
xleak file.xlsx -n 0
```
#### Export data
```bash
# Export to CSV
xleak data.xlsx --export csv > output.csv
# Export to JSON
xleak data.xlsx --export json > output.json
# Export as plain text (tab-separated)
xleak data.xlsx --export text > output.txt
```
#### Work with Excel Tables (.xlsx only)
```bash
# List all tables in a workbook
xleak workbook.xlsx --list-tables
# Extract a specific table as JSON (default)
xleak workbook.xlsx --table "Sales"
# Extract table as CSV
xleak workbook.xlsx --table "Sales" --export csv > sales.csv
# Extract table as plain text
xleak workbook.xlsx --table "Employees" --export text
```
#### Combine options
```bash
# Export specific sheet as CSV
xleak workbook.xlsx --sheet "Sales" --export csv > sales.csv
```
## Examples
```bash
# Launch interactive viewer
xleak quarterly-report.xlsx -i
# Quick preview in non-interactive mode
xleak quarterly-report.xlsx
# See specific sheet with limited rows
xleak financial-data.xlsx --sheet "Summary" -n 10
# Interactive mode with formulas visible
xleak data.xlsx -i --formulas
# Export all data from a sheet
xleak survey-results.xlsx --sheet "Responses" --export csv -n 0
```
## Configuration
xleak supports configuration via a TOML file for persistent settings like default theme and keybindings.
### Config File Location
**Default:** `~/.config/xleak/config.toml` (or `$XDG_CONFIG_HOME/xleak/config.toml`)
**Platform-specific fallback locations:**
- **macOS:** `~/Library/Application Support/xleak/config.toml`
- **Linux:** `~/.config/xleak/config.toml` (same as XDG)
- **Windows:** `%APPDATA%\xleak\config.toml`
**Custom:** Use `--config` flag to specify a different location:
```bash
xleak --config /path/to/config.toml file.xlsx -i
```
### Quick Start
1. **Copy the example:**
```bash
mkdir -p ~/.config/xleak
cp config.toml.example ~/.config/xleak/config.toml
```
2. **Or create a minimal config:**
```bash
mkdir -p ~/.config/xleak
cat > ~/.config/xleak/config.toml << 'EOF'
[theme]
default = "Dracula"
[ui]
max_rows = 50
column_width = 30
[keybindings]
profile = "vim"
EOF
```
3. **Test your config:**
```bash
xleak file.xlsx -i
```
### Configuration Options
#### Theme Settings
```toml
[theme]
# Default theme to use on startup
default = "Dracula"
```
**Available themes:**
- `"Default"` - Clean light theme with subtle colors
- `"Dracula"` - Popular dark theme with purple accents
- `"Solarized Dark"` - Precision colors for machines and people
- `"Solarized Light"` - Light variant of Solarized
- `"GitHub Dark"` - GitHub's dark color scheme
- `"Nord"` - Arctic, north-bluish color palette
Press `t` in interactive mode to cycle through themes at runtime.
#### UI Settings
```toml
[ui]
# Default maximum rows to display in non-interactive mode (0 = all)
max_rows = 50
# Default maximum column width in characters
column_width = 30
```
**Notes:**
- `max_rows` only affects non-interactive display mode (`xleak file.xlsx`)
- Interactive TUI mode (`-i`) always shows all rows with lazy loading for large files
- `column_width` applies to both modes and can be overridden with `-w` flag
#### Keybindings
xleak supports two built-in profiles plus custom keybindings:
```toml
[keybindings]
# Profile: "default" or "vim"
profile = "default"
# Optional: override individual keys
[keybindings.custom]
quit = "x"
search = "?"
copy_cell = "y"
```
### Keybinding Profiles
#### Default Profile
Standard keybindings for terminal applications:
| Action | Key | Description |
|--------|-----|-------------|
| **Navigation** | | |
| Move up/down/left/right | `↑` `↓` `←` `→` | Navigate cells |
| Page up/down | `PgUp` `PgDn` | Scroll by page |
| Jump to top/bottom | `Ctrl+Home` `Ctrl+End` | Jump to first/last row |
| Jump to row start/end | `Home` `End` | Jump to first/last column |
| **Actions** | | |
| View cell details | `Enter` | Show formula and full value |
| Jump to cell | `Ctrl+G` | Jump to specific row/cell |
| Search | `/` | Full-text search |
| Next/prev match | `n` `N` | Navigate search results |
| Copy cell | `c` | Copy cell to clipboard |
| Copy row | `C` (Shift+c) | Copy entire row |
| **Sheets** | | |
| Next/prev sheet | `Tab` `Shift+Tab` | Switch between sheets |
| **General** | | |
| Toggle theme | `t` | Cycle through themes |
| Show help | `?` | Display help screen |
| Quit | `q` | Exit application |
#### VIM Profile
VIM-style keybindings for efficient keyboard navigation:
| Action | Key | Default Key | Description |
|--------|-----|-------------|-------------|
| **VIM Navigation** | | | |
| Move left/down/up/right | `h` `j` `k` `l` | ← ↓ ↑ → | VIM-style movement |
| Page up/down | `Ctrl+u` `Ctrl+d` | PgUp PgDn | Half-page scrolling |
| Jump to top | `gg` | Ctrl+Home | Jump to first row |
| Jump to bottom | `G` (Shift+g) | Ctrl+End | Jump to last row |
| Jump to row start/end | `0` `$` | Home End | First/last column |
| **VIM Actions** | | | |
| Yank cell | `y` | `c` | Copy cell (yank) |
| Yank row | `Y` (Shift+y) | `C` | Copy row (yank) |
| **Standard** | | | |
| Quit | `q` | `q` | Same as default |
| Search | `/` | `/` | Same as default |
| Next/prev match | `n` `N` | `n` `N` | Same as default |
| All other keys | | | Same as default profile |
**Enable VIM mode:**
```toml
[keybindings]
profile = "vim"
```
### Custom Keybindings
Override individual keys while keeping the profile defaults:
```toml
[keybindings]
profile = "default"
[keybindings.custom]
# Use 'x' to quit instead of 'q'
quit = "x"
# Use '?' for search instead of '/'
search = "?"
# Use 'T' (Shift+t) to toggle theme
theme_toggle = "T"
# Use Ctrl+J to jump to cell
jump = "Ctrl+j"
```
**All customizable actions:**
| Action | Default | VIM | Description |
|--------|---------|-----|-------------|
| `quit` | `q` | `q` | Exit application |
| `help` | `?` | `?` | Show help |
| `theme_toggle` | `t` | `t` | Cycle themes |
| `search` | `/` | `/` | Search cells |
| `next_match` | `n` | `n` | Next search result |
| `prev_match` | `N` | `N` | Previous result |
| `copy_cell` | `c` | `y` | Copy cell |
| `copy_row` | `C` | `Y` | Copy row |
| `jump` | `Ctrl+g` | `Ctrl+g` | Jump to cell |
| `show_cell_detail` | `Enter` | `Enter` | Show details |
| `next_sheet` | `Tab` | `Tab` | Next sheet |
| `prev_sheet` | `Shift+Tab` | `Shift+Tab` | Previous sheet |
| `up` | `Up` | `k` | Move up |
| `down` | `Down` | `j` | Move down |
| `left` | `Left` | `h` | Move left |
| `right` | `Right` | `l` | Move right |
| `page_up` | `PageUp` | `Ctrl+u` | Page up |
| `page_down` | `PageDown` | `Ctrl+d` | Page down |
| `jump_to_top` | `Ctrl+Home` | `g` | First row |
| `jump_to_bottom` | `Ctrl+End` | `G` | Last row |
| `jump_to_row_start` | `Home` | `0` | First column |
| `jump_to_row_end` | `End` | `$` | Last column |
**Key format:**
- Single key: `"q"`, `"/"`, `"Enter"`
- With modifier: `"Ctrl+g"`, `"Shift+Tab"`, `"Alt+s"`
- Special keys: `"Enter"`, `"Esc"`, `"Tab"`, `"Home"`, `"End"`, `"PageUp"`, `"PageDown"`, `"Up"`, `"Down"`, `"Left"`, `"Right"`
### Example Configurations
**Minimal (theme only):**
```toml
[theme]
default = "Nord"
```
**VIM user:**
```toml
[theme]
default = "Dracula"
[keybindings]
profile = "vim"
```
**Custom workflow:**
```toml
[theme]
default = "GitHub Dark"
[ui]
max_rows = 100
column_width = 40
[keybindings]
profile = "default"
[keybindings.custom]
quit = "x"
search = "s"
copy_cell = "Ctrl+c"
copy_row = "Ctrl+Shift+c"
```
**Full reference:** See `config.toml.example` for all options with detailed comments.
## Performance
xleak is optimized for both small and large files:
- **Small files** (< 1000 rows): Instant loading with full eager loading
- **Large files** (≥ 1000 rows): Automatic lazy loading with row caching
- Memory usage: ~400KB for 10,000 row files
- Loads only visible rows on demand
- Progress indicators for long operations
## Comparison to Alternatives
| Tool | Format | Speed | Terminal Native | Interactive | Search | Formulas |
|------|--------|-------|----------------|-------------|--------|----------|
| **xleak** | ✅ xlsx/xls/ods | ⚡ Fast | ✅ Yes | ✅ Full TUI | ✅ Yes | ✅ Yes |
| Excel | ✅ xlsx | ❌ Slow startup | ❌ GUI only | ✅ Yes | ✅ Yes | ✅ Yes |
| pandas | ✅ Many | ❌ Slow | ❌ Python required | ❌ No | ❌ No | ❌ No |
| csvlook | ❌ CSV only | ✅ Fast | ✅ Yes | ❌ No | ❌ No | ❌ No |
## Related Projects
Looking to view Word documents in the terminal? Check out **[doxx](https://github.com/bgreenwell/doxx)** - a terminal viewer for `.docx` files with similar TUI capabilities.
## Built With
- **Rust** - for performance and reliability
- **calamine** - the fastest Excel/ODS parser
- **ratatui** - terminal user interface framework
- **prettytable-rs** - beautiful terminal tables
- **clap** - elegant CLI argument parsing
- **arboard** - cross-platform clipboard support
## Troubleshooting
**"File not found"**
- Ensure the file path is correct
- Use quotes if the filename has spaces: `xleak "My Report.xlsx"`
**"No sheets found"**
- The Excel file might be corrupted
- Try opening it in Excel/LibreOffice first to verify
**"Sheet 'X' not found"**
- Run `xleak file.xlsx` (without --sheet) to see all available sheets
- Sheet names are case-sensitive
## License
MIT License — see [LICENSE](LICENSE) file for details.
## Credits
- Inspired by [doxx](https://github.com/bgreenwell/doxx) by bgreenwell
- Powered by [calamine](https://github.com/tafia/calamine)
---
**Made for developers who live in the terminal** 🚀
xleak-0.2.6/RELEASE_CHECKLIST.md 0000644 0000000 0000000 00000011206 10461020230 0013730 0 ustar 0000000 0000000 # Release Checklist
Use this checklist when preparing a new release of xleak. You can also create a GitHub issue using the "Release" template to track progress.
## Pre-Release
- [ ] All tests passing: `cargo test`
- [ ] No clippy warnings: `cargo clippy`
- [ ] Code is formatted: `cargo fmt --check`
- [ ] CHANGELOG.md updated:
- [ ] Move items from `[Unreleased]` to new `[X.Y.Z] - YYYY-MM-DD` section
- [ ] Keep `[Unreleased]` section empty for future changes
- [ ] Verify changelog entries are accurate and complete
- [ ] Version bumped in `Cargo.toml`
- [ ] Test binary works: `cargo run --release -- tests/fixtures/test_comprehensive.xlsx`
## Create Release
- [ ] Commit version bump: `git commit -m "chore: release X.Y.Z"`
- [ ] Push to main: `git push`
- [ ] Create version tag: `git tag vX.Y.Z`
- [ ] Push tag: `git push origin vX.Y.Z`
- [ ] Wait for GitHub Actions workflows to complete (~10-15 minutes)
## Verify Automated Releases
All of the following are now automated via GitHub Actions:
- [ ] **GitHub Release** created at https://github.com/bgreenwell/xleak/releases/tag/vX.Y.Z
- [ ] All platform binaries present (Linux, macOS, Windows)
- [ ] Tarballs (.tar.xz, .tar.gz) and ZIP archive
- [ ] MSI installer for Windows
- [ ] Shell/PowerShell installer scripts
- [ ] SHA256 checksum files
- [ ] **Homebrew** formula published to [bgreenwell/homebrew-tap](https://github.com/bgreenwell/homebrew-tap)
- Automated by: `publish-homebrew-formula` job in release.yml
- [ ] **Scoop** manifest published to [bgreenwell/scoop-bucket](https://github.com/bgreenwell/scoop-bucket)
- Automated by: `.github/workflows/publish-scoop.yml`
- [ ] **crates.io** published at https://crates.io/crates/xleak
- Automated by: `publish-crates-io` job in release.yml
- [ ] **AUR** package updated at [xleak-bin](https://aur.archlinux.org/packages/xleak-bin)
- Automated by: `.github/workflows/publish-aur.yml`
- PKGBUILD and .SRCINFO auto-generated and pushed
- [ ] **WinGet** manifest PR created to [microsoft/winget-pkgs](https://github.com/microsoft/winget-pkgs)
- Automated by: `.github/workflows/publish-winget.yml`
- **Note:** PR may require manual merge approval from Microsoft team (1-2 days)
## Test Installations
- [ ] **Homebrew (macOS/Linux)**:
```bash
brew update
brew upgrade xleak
xleak --version
```
- [ ] **Scoop (Windows)**:
```powershell
scoop update
scoop update xleak
xleak --version
```
- [ ] **AUR (Arch Linux)**:
```bash
yay -Syu xleak-bin
xleak --version
```
- [ ] **WinGet (Windows)**:
```powershell
winget upgrade bgreenwell.xleak
xleak --version
```
**Note:** May take 1-2 days for WinGet PR to be merged
- [ ] **Shell installer (Linux/macOS)**:
```bash
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/bgreenwell/xleak/releases/latest/download/xleak-installer.sh | sh
```
- [ ] **MSI installer (Windows)**: Download and test from GitHub Releases
## Post-Release
- [ ] All automated workflows completed successfully (check GitHub Actions)
- [ ] Announcement published (if applicable)
- [ ] Documentation updated if needed
- [ ] Close release tracking issue
## Troubleshooting
### Common Issues
**GitHub Actions fails:**
- Check workflow logs for specific error
- Verify all secrets are configured: `HOMEBREW_TAP_TOKEN`, `SCOOP_BUCKET_TOKEN`, `CARGO_REGISTRY_TOKEN`, `AUR_SSH_PRIVATE_KEY`, `WINGET_TOKEN`
**Scoop installation broken:**
- Verify manifest in scoop-bucket uses `.zip` file
- Check SHA256 hash matches release artifact
**AUR automation fails:**
- Check SSH key is valid: Secret `AUR_SSH_PRIVATE_KEY`
- Verify PKGBUILD generation in workflow logs
- Fallback: Manual publish (see old checklist in git history)
**WinGet PR not appearing:**
- Check `.github/workflows/publish-winget.yml` logs
- Verify `WINGET_TOKEN` has correct permissions
- May need to create PR manually with `komac update`
**Homebrew formula outdated:**
- Check [homebrew-tap repo](https://github.com/bgreenwell/homebrew-tap) for commit
- Verify `HOMEBREW_TAP_TOKEN` secret is valid
### Manual Intervention Required
If automation fails for a specific channel, you can fall back to manual publishing:
- **AUR Manual Process**: See git history of this file (commit before automation)
- **WinGet Manual Process**: Use `komac update` CLI tool
- **Scoop Manual Process**: Manually edit bucket/xleak.json in scoop-bucket repo
### Workflow Summaries
For detailed workflow information, see:
- `.github/workflows/release.yml` - Main release, Homebrew, crates.io
- `.github/workflows/publish-scoop.yml` - Scoop bucket
- `.github/workflows/publish-aur.yml` - AUR publishing
- `.github/workflows/publish-winget.yml` - WinGet manifests
xleak-0.2.6/assets/DEMO_RECORDING.md 0000644 0000000 0000000 00000005475 10461020230 0014714 0 ustar 0000000 0000000 # Creating a Demo GIF for xleak
## Recommended Tools
### Option 1: VHS (Recommended for automation)
[VHS](https://github.com/charmbracelet/vhs) lets you script terminal recordings.
```bash
# Install
brew install vhs
# Create a tape file (see demo.tape below)
vhs demo.tape
```
### Option 2: Asciinema + agg
Record with asciinema, convert to GIF with agg.
```bash
# Install
brew install asciinema
cargo install --git https://github.com/asciinema/agg
# Record
asciinema rec demo.cast
# Convert to GIF
agg demo.cast demo.gif
```
### Option 3: ttystudio
Lightweight terminal recorder.
```bash
npm install -g ttystudio
ttystudio demo.gif
```
## Demo Script
Here's a suggested demo flow showcasing xleak's key features:
1. **Launch interactive mode**
```bash
xleak tests/fixtures/test_data.xlsx -i
```
2. **Navigate cells** (arrow keys for 2-3 seconds)
3. **Search feature** (`/`)
- Type: `Widgets`
- Press Enter
- Press `n` to jump to next match
4. **Jump to row** (`Ctrl+G`)
- Type: `25`
- Press Enter
5. **View cell details** (Enter)
- Show a cell with a formula
6. **Copy cell** (`c`)
- Show feedback message
7. **Switch sheets** (Tab)
- Navigate to another sheet
8. **Show help** (`?`)
- Display help overlay briefly
9. **Quit** (`q`)
## VHS Tape File
Create `assets/demo.tape`:
```tape
Output assets/demo.gif
Set FontSize 18
Set Width 1200
Set Height 700
Set Theme "Dracula"
Type "xleak tests/fixtures/test_data.xlsx -i"
Enter
Sleep 2s
# Navigate around
Down 3
Right 2
Sleep 1s
# Search
Type "/"
Sleep 500ms
Type "Widgets"
Enter
Sleep 1s
Type "n"
Sleep 1s
# Jump to row
Ctrl+G
Sleep 500ms
Type "15"
Enter
Sleep 1s
# View cell detail
Enter
Sleep 2s
Escape
Sleep 500ms
# Show help
Type "?"
Sleep 3s
Escape
Sleep 500ms
# Quit
Type "q"
Sleep 1s
```
Run with:
```bash
vhs assets/demo.tape
```
## Manual Recording Tips
If recording manually:
1. **Terminal setup:**
- Clear terminal: `clear`
- Set appropriate size: ~120x30 is good for readability
- Use a clean theme (light or dark with good contrast)
2. **File to demo:**
- Use `tests/fixtures/test_data.xlsx` (has multiple sheets, formulas, variety of data)
3. **Keep it short:**
- Aim for 20-30 seconds
- Focus on 3-4 key features
4. **Features to highlight:**
- Interactive navigation
- Search with `/`
- Formula display (Enter on a formula cell)
- Jump to row with Ctrl+G
- Multi-sheet support (Tab)
## Optimizing the GIF
After creating the GIF:
```bash
# Optimize with gifsicle (optional)
brew install gifsicle
gifsicle -O3 --colors 256 assets/demo.gif -o assets/demo-optimized.gif
# Or use online tool: https://ezgif.com/optimize
```
## Adding to README
The demo gif is already referenced in README.md:
```markdown

```
Alternatively, upload to GitHub releases and link it there.
xleak-0.2.6/assets/demo.gif 0000644 0000000 0000000 00004141275 10461020230 0013670 0 ustar 0000000 0000000 GIF89a1 '
.<$0 "*")$#"%D%' &("+')!+%#%$+CO '!!$!"'"#,####.$KZ&&2&(0''1''3('2))3)*+)*0*+5+M++*-6-E 22222622;33156=5;C8T_99D9:=:;D:et<<:<<<<=1>D?tCGJCWDEEDELDF>GGEGGGIIIKKSKLLLMMJMNPOOOOPEOh&OzPVQ>RQXRRPRRRTYGUUUUVZVVWWXVXu#ZY`ZZZZ[_b[[]a>^_Y__[_____fblrbcgggggognZhinhiigjjfjo/jnnonnvo{qqput{uvwuutwzcxxxxyty=y{{y}|~~~j<֍험Rj߱½ľ|ʧԅ !NETSCAPE2.0 ! , '
.<$0 "*")$#"%D%' &("+')!+%#%$+CO '!!$!"'"#,####.$KZ&&2&(0''1''3('2))3)*+)*0*+5+M++*-6-E 22222622;33156=5;C8T_99D9:=:;D:et<<:<<<<=1>D?tCGJCWDEEDELDF>GGEGGGIIIKKSKLLLMMJMNPOOOOPEOh&OzPVQ>RQXRRPRRRTYGUUUUVZVVWWXVXu#ZY`ZZZZ[_b[[]a>^_Y__[_____fblrbcgggggognZhinhiigjjfjo/jnnonnvo{qqput{uvwuutwzcxxxxyty=y{{y}|~~~j<֍험Rj߱½ľ|ʧԅ aH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@
JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻNȓ+_μУKNسkνËOӫ_Ͼ˟OϿ (h&6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄jѠ(
/裐>(Fj!@,4ʐ
"H
ЀpH B $* Ȳpj"AC
9<9elhPXnPA+@<=x2
;fFZ)M?̀/G.3NGO? B( )`(#-@00-Gk
ٰ@3:$W"C+p'
P
`uwPU2<?T|3rЩp.Sl?pBߔ
0 `D+&@ty9
`Tzko'7G/Wogw/o觯/o HL:'H
Z̠7z GH(L
W0gH8̡w@H"HL&:PH*ZX̢.z`H2hL6pH:x̣> IBL"F:$'IJZ̤&7Nz(GIRL*WV,gIZ̥.w^0IbL2f:Ќ4IjZ̦6nz8IrL:v~
@JЂMBІ:D'JъZͨF7юz
HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@
PJԢHMRԦ:PTJժZXͪVծz`
XJֲhMZֶp\Jxͫ^
`KMb:d'KZͬf7z
hGKҚMjWֺlgKͭnw
pKMr:ЍtKZͮvz
xKMz|Kͯ~ LN;'L
[ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~ NO;'N[ϸ7{ GN ! ,_ <