mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
Merge branch 'sxyazi:main' into feat/independent-style-on-inner-section-of-status
This commit is contained in:
commit
f5effc8845
139 changed files with 1940 additions and 1237 deletions
27
.github/workflows/cachix.yml
vendored
Normal file
27
.github/workflows/cachix.yml
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
name: Cachix
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
name: Publish Flake
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Nix
|
||||||
|
uses: cachix/install-nix-action@v25
|
||||||
|
|
||||||
|
- name: Authenticate with Cachix
|
||||||
|
uses: cachix/cachix-action@v14
|
||||||
|
with:
|
||||||
|
name: yazi
|
||||||
|
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||||
|
|
||||||
|
- name: Build Flake
|
||||||
|
run: nix build -L
|
||||||
122
.github/workflows/release.yml
vendored
122
.github/workflows/release.yml
vendored
|
|
@ -6,9 +6,7 @@ on:
|
||||||
- "v[0-9]+.[0-9]+.[0-9]+"
|
- "v[0-9]+.[0-9]+.[0-9]+"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
build-unix:
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
|
@ -20,6 +18,27 @@ jobs:
|
||||||
target: x86_64-apple-darwin
|
target: x86_64-apple-darwin
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
target: aarch64-apple-darwin
|
target: aarch64-apple-darwin
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install gcc-aarch64-linux-gnu
|
||||||
|
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||||
|
run: sudo apt-get update && sudo apt-get install -yq gcc-aarch64-linux-gnu
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: ./scripts/build.sh ${{ matrix.target }}
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: yazi-${{ matrix.target }}.zip
|
||||||
|
path: yazi-${{ matrix.target }}.zip
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
target: x86_64-pc-windows-msvc
|
target: x86_64-pc-windows-msvc
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
|
|
@ -31,57 +50,92 @@ jobs:
|
||||||
- name: Setup Rust toolchain
|
- name: Setup Rust toolchain
|
||||||
run: rustup toolchain install stable --profile minimal
|
run: rustup toolchain install stable --profile minimal
|
||||||
|
|
||||||
- name: Add aarch64 target
|
- name: Add target
|
||||||
if: contains(fromJson('["aarch64-unknown-linux-gnu", "aarch64-apple-darwin", "aarch64-pc-windows-msvc"]'), matrix.target)
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
run: rustup target add ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Install gcc-aarch64-linux-gnu
|
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -yq gcc-aarch64-linux-gnu
|
|
||||||
|
|
||||||
- name: Setup Rust cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
YAZI_GEN_COMPLETIONS: true
|
YAZI_GEN_COMPLETIONS: true
|
||||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: /usr/bin/aarch64-linux-gnu-gcc
|
|
||||||
run: cargo build --release --locked --target ${{ matrix.target }}
|
run: cargo build --release --locked --target ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Build snap
|
- name: Pack artifact
|
||||||
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
|
||||||
uses: snapcore/action-build@v1
|
|
||||||
|
|
||||||
- name: Pack artifacts [Linux & macOS]
|
|
||||||
if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
|
|
||||||
env:
|
|
||||||
TARGET_NAME: yazi-${{ matrix.target }}
|
|
||||||
run: |
|
|
||||||
mkdir $TARGET_NAME
|
|
||||||
cp target/${{ matrix.target }}/release/yazi $TARGET_NAME
|
|
||||||
cp -r yazi-config/completions $TARGET_NAME
|
|
||||||
cp README.md LICENSE $TARGET_NAME
|
|
||||||
zip -r $TARGET_NAME.zip $TARGET_NAME
|
|
||||||
|
|
||||||
- name: Pack artifacts [Windows]
|
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
env:
|
env:
|
||||||
TARGET_NAME: yazi-${{ matrix.target }}
|
TARGET_NAME: yazi-${{ matrix.target }}
|
||||||
run: |
|
run: |
|
||||||
New-Item -ItemType Directory -Path ${env:TARGET_NAME}
|
New-Item -ItemType Directory -Path ${env:TARGET_NAME}
|
||||||
Copy-Item -Path "target\${{ matrix.target }}\release\yazi.exe" -Destination ${env:TARGET_NAME}
|
Copy-Item -Path "target\${{ matrix.target }}\release\yazi.exe" -Destination ${env:TARGET_NAME}
|
||||||
Copy-Item -Path "yazi-config\completions" -Destination ${env:TARGET_NAME} -Recurse
|
Copy-Item -Path "yazi-boot\completions" -Destination ${env:TARGET_NAME} -Recurse
|
||||||
Copy-Item -Path "README.md", "LICENSE" -Destination ${env:TARGET_NAME}
|
Copy-Item -Path "README.md", "LICENSE" -Destination ${env:TARGET_NAME}
|
||||||
Compress-Archive -Path ${env:TARGET_NAME} -DestinationPath "${env:TARGET_NAME}.zip"
|
Compress-Archive -Path ${env:TARGET_NAME} -DestinationPath "${env:TARGET_NAME}.zip"
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: yazi-${{ matrix.target }}.zip
|
||||||
|
path: yazi-${{ matrix.target }}.zip
|
||||||
|
|
||||||
|
build-musl:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- target: x86_64-unknown-linux-musl
|
||||||
|
image: rust-musl-cross:x86_64-musl
|
||||||
|
- target: aarch64-unknown-linux-musl
|
||||||
|
image: rust-musl-cross:aarch64-musl
|
||||||
|
container:
|
||||||
|
image: docker://ghcr.io/rust-cross/${{ matrix.image }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: ./scripts/build.sh ${{ matrix.target }}
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: yazi-${{ matrix.target }}.zip
|
||||||
|
path: yazi-${{ matrix.target }}.zip
|
||||||
|
|
||||||
|
build-snap:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
target: x86_64-unknown-linux-gnu
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build snap
|
||||||
|
uses: snapcore/action-build@v1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: mv yazi_*.snap yazi-${{ matrix.target }}.snap
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: yazi-${{ matrix.target }}.snap
|
||||||
|
path: yazi-${{ matrix.target }}.snap
|
||||||
|
|
||||||
|
release:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [build-unix, build-windows, build-musl, build-snap]
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
files: |
|
files: |
|
||||||
yazi-${{ matrix.target }}.zip
|
yazi-*.zip
|
||||||
yazi*.snap
|
yazi-*.snap
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
|
|
|
||||||
345
Cargo.lock
generated
345
Cargo.lock
generated
|
|
@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.8"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff"
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
@ -72,9 +72,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.6.12"
|
version = "0.6.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540"
|
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"anstyle-parse",
|
"anstyle-parse",
|
||||||
|
|
@ -120,15 +120,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.79"
|
version = "1.0.80"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arc-swap"
|
name = "arc-swap"
|
||||||
version = "1.6.0"
|
version = "1.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-priority-channel"
|
name = "async-priority-channel"
|
||||||
|
|
@ -166,6 +166,12 @@ version = "0.21.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "better-panic"
|
name = "better-panic"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
@ -214,9 +220,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "1.9.0"
|
version = "1.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
|
checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
@ -224,9 +230,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.15.0"
|
version = "3.15.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f"
|
checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck"
|
name = "bytemuck"
|
||||||
|
|
@ -263,12 +269,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.83"
|
version = "1.0.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
|
|
@ -285,7 +288,7 @@ dependencies = [
|
||||||
"android-tzdata",
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"windows-targets 0.52.0",
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -307,7 +310,7 @@ dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
"strsim",
|
"strsim 0.11.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -348,7 +351,7 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -431,9 +434,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.11"
|
version = "0.5.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b"
|
checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
@ -505,6 +508,41 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.20.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.20.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim 0.10.0",
|
||||||
|
"syn 2.0.52",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.20.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.52",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.3.11"
|
version = "0.3.11"
|
||||||
|
|
@ -565,9 +603,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erased-serde"
|
name = "erased-serde"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "55d05712b2d8d88102bc9868020c9e5c7a1f5527c452b9b97450a1d006140ba7"
|
checksum = "388979d208a049ffdfb22fa33b9c81942215b940910bccfe258caeb25d125cb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
@ -749,7 +787,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -805,9 +843,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gif"
|
name = "gif"
|
||||||
version = "0.12.0"
|
version = "0.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
|
checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"color_quant",
|
"color_quant",
|
||||||
"weezl",
|
"weezl",
|
||||||
|
|
@ -827,9 +865,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "half"
|
name = "half"
|
||||||
version = "2.3.1"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872"
|
checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"crunchy",
|
"crunchy",
|
||||||
|
|
@ -853,9 +891,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.6"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
|
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
|
|
@ -890,14 +928,10 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "ident_case"
|
||||||
version = "0.4.0"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
dependencies = [
|
|
||||||
"unicode-bidi",
|
|
||||||
"unicode-normalization",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
|
|
@ -909,17 +943,11 @@ dependencies = [
|
||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "if_chain"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "image"
|
name = "image"
|
||||||
version = "0.24.8"
|
version = "0.24.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23"
|
checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
|
@ -941,9 +969,9 @@ checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.2.3"
|
version = "2.2.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
|
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
|
@ -1001,9 +1029,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.68"
|
version = "0.3.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
|
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
@ -1093,15 +1121,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.20"
|
version = "0.4.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lru"
|
name = "lru"
|
||||||
version = "0.12.2"
|
version = "0.12.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "db2c024b41519440580066ba82aab04092b333e09066a5eb86c7c4890df31f22"
|
checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
@ -1168,9 +1196,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.10"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
|
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
|
|
@ -1180,9 +1208,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mlua"
|
name = "mlua"
|
||||||
version = "0.9.5"
|
version = "0.9.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d3561f79659ff3afad7b25e2bf2ec21507fe601ebecb7f81088669ec4bfd51e"
|
checksum = "868d02cb5eb97761bbf6bd6922c1c7a88b8ea252bbf43bd8350a0bf8497a1fc0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"erased-serde",
|
"erased-serde",
|
||||||
|
|
@ -1221,7 +1249,7 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"regex",
|
"regex",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1434,7 +1462,7 @@ version = "1.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef"
|
checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.21.7",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"line-wrap",
|
"line-wrap",
|
||||||
"quick-xml",
|
"quick-xml",
|
||||||
|
|
@ -1444,9 +1472,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.12"
|
version = "0.17.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78c2378060fb13acff3ba0325b83442c1d2c44fbb76df481160ddc1687cce160"
|
checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
|
|
@ -1543,9 +1571,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.8.1"
|
version = "1.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
|
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
"rayon-core",
|
"rayon-core",
|
||||||
|
|
@ -1595,9 +1623,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.4.5"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
|
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
@ -1643,9 +1671,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.16"
|
version = "1.0.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "safemem"
|
name = "safemem"
|
||||||
|
|
@ -1670,9 +1698,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.196"
|
version = "1.0.197"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
|
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
@ -1689,20 +1717,20 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.196"
|
version = "1.0.197"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
|
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.113"
|
version = "1.0.114"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
|
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
|
|
@ -1804,12 +1832,12 @@ checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.5.5"
|
version = "0.5.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
|
checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1843,6 +1871,12 @@ version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
|
checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
|
@ -1868,7 +1902,7 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1884,9 +1918,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.49"
|
version = "2.0.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
|
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -1931,14 +1965,14 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
|
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
@ -2050,7 +2084,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2143,7 +2177,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2217,9 +2251,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-normalization"
|
name = "unicode-normalization"
|
||||||
version = "0.1.22"
|
version = "0.1.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
@ -2243,7 +2277,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
|
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"idna 0.5.0",
|
"idna",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -2265,12 +2299,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "validator"
|
name = "validator"
|
||||||
version = "0.16.1"
|
version = "0.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b92f40481c04ff1f4f61f304d61793c7b56ff76ac1469f1beb199b1445b253bd"
|
checksum = "da339118f018cc70ebf01fafc103360528aad53717e4bf311db929cb01cb9345"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"idna 0.4.0",
|
"idna",
|
||||||
"lazy_static",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
|
|
@ -2281,28 +2315,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "validator_derive"
|
name = "validator_derive"
|
||||||
version = "0.16.0"
|
version = "0.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc44ca3088bb3ba384d9aecf40c6a23a676ce23e09bdaca2073d99c207f864af"
|
checksum = "76e88ea23b8f5e59230bff8a2f03c0ee0054a61d5b8343a38946bcd406fe624c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"if_chain",
|
"darling",
|
||||||
"lazy_static",
|
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"regex",
|
"regex",
|
||||||
"syn 1.0.109",
|
"syn 2.0.52",
|
||||||
"validator_types",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "validator_types"
|
|
||||||
version = "0.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "111abfe30072511849c5910134e8baf8dc05de4c0e5903d681cbd5c9c4d611e3"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2331,9 +2353,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.4.0"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"same-file",
|
"same-file",
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
|
|
@ -2347,9 +2369,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.91"
|
version = "0.2.92"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
|
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"wasm-bindgen-macro",
|
"wasm-bindgen-macro",
|
||||||
|
|
@ -2357,24 +2379,24 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-backend"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.2.91"
|
version = "0.2.92"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
|
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.91"
|
version = "0.2.92"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
|
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
|
|
@ -2382,22 +2404,22 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.91"
|
version = "0.2.92"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
|
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.91"
|
version = "0.2.92"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
|
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "weezl"
|
name = "weezl"
|
||||||
|
|
@ -2464,7 +2486,7 @@ version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.0",
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2482,7 +2504,7 @@ version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.0",
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2517,17 +2539,17 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm 0.52.0",
|
"windows_aarch64_gnullvm 0.52.4",
|
||||||
"windows_aarch64_msvc 0.52.0",
|
"windows_aarch64_msvc 0.52.4",
|
||||||
"windows_i686_gnu 0.52.0",
|
"windows_i686_gnu 0.52.4",
|
||||||
"windows_i686_msvc 0.52.0",
|
"windows_i686_msvc 0.52.4",
|
||||||
"windows_x86_64_gnu 0.52.0",
|
"windows_x86_64_gnu 0.52.4",
|
||||||
"windows_x86_64_gnullvm 0.52.0",
|
"windows_x86_64_gnullvm 0.52.4",
|
||||||
"windows_x86_64_msvc 0.52.0",
|
"windows_x86_64_msvc 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2544,9 +2566,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
|
|
@ -2562,9 +2584,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
|
|
@ -2580,9 +2602,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
|
|
@ -2598,9 +2620,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
|
|
@ -2616,9 +2638,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
|
|
@ -2634,9 +2656,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
|
|
@ -2652,15 +2674,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.6.1"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d90f4e0f530c4c69f62b80d839e9ef3855edc9cba471a160c4d692deed62b401"
|
checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
@ -2671,7 +2693,7 @@ version = "0.2.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"base64",
|
"base64 0.22.0",
|
||||||
"color_quant",
|
"color_quant",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"image",
|
"image",
|
||||||
|
|
@ -2722,7 +2744,7 @@ name = "yazi-core"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64 0.22.0",
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.4.2",
|
||||||
"clipboard-win",
|
"clipboard-win",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
|
|
@ -2743,6 +2765,7 @@ dependencies = [
|
||||||
"yazi-boot",
|
"yazi-boot",
|
||||||
"yazi-config",
|
"yazi-config",
|
||||||
"yazi-plugin",
|
"yazi-plugin",
|
||||||
|
"yazi-proxy",
|
||||||
"yazi-scheduler",
|
"yazi-scheduler",
|
||||||
"yazi-shared",
|
"yazi-shared",
|
||||||
]
|
]
|
||||||
|
|
@ -2773,6 +2796,7 @@ dependencies = [
|
||||||
"yazi-config",
|
"yazi-config",
|
||||||
"yazi-core",
|
"yazi-core",
|
||||||
"yazi-plugin",
|
"yazi-plugin",
|
||||||
|
"yazi-proxy",
|
||||||
"yazi-scheduler",
|
"yazi-scheduler",
|
||||||
"yazi-shared",
|
"yazi-shared",
|
||||||
]
|
]
|
||||||
|
|
@ -2804,6 +2828,7 @@ dependencies = [
|
||||||
"yazi-boot",
|
"yazi-boot",
|
||||||
"yazi-config",
|
"yazi-config",
|
||||||
"yazi-prebuild",
|
"yazi-prebuild",
|
||||||
|
"yazi-proxy",
|
||||||
"yazi-shared",
|
"yazi-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -2813,13 +2838,24 @@ version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f4b6c8e12e39ac0f79fa96f36e5b88e0da8d230691abd729eec709b43c74f632"
|
checksum = "f4b6c8e12e39ac0f79fa96f36e5b88e0da8d230691abd729eec709b43c74f632"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yazi-proxy"
|
||||||
|
version = "0.2.3"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"mlua",
|
||||||
|
"tokio",
|
||||||
|
"yazi-config",
|
||||||
|
"yazi-shared",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yazi-scheduler"
|
name = "yazi-scheduler"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-priority-channel",
|
"async-priority-channel",
|
||||||
"base64",
|
"base64 0.22.0",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"futures",
|
"futures",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
|
@ -2831,6 +2867,7 @@ dependencies = [
|
||||||
"yazi-adaptor",
|
"yazi-adaptor",
|
||||||
"yazi-config",
|
"yazi-config",
|
||||||
"yazi-plugin",
|
"yazi-plugin",
|
||||||
|
"yazi-proxy",
|
||||||
"yazi-shared",
|
"yazi-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -2869,7 +2906,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.49",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
11
README.md
11
README.md
|
|
@ -12,10 +12,10 @@ Yazi (means "duck") is a terminal file manager written in Rust, based on non-blo
|
||||||
- 💪 **Powerful Async Task Scheduling and Management**: Provides real-time progress updates, task cancellation, and internal task priority assignment.
|
- 💪 **Powerful Async Task Scheduling and Management**: Provides real-time progress updates, task cancellation, and internal task priority assignment.
|
||||||
- 🖼️ **Built-in Support for Multiple Image Protocols**: Also integrated with Überzug++, covering almost all terminals.
|
- 🖼️ **Built-in Support for Multiple Image Protocols**: Also integrated with Überzug++, covering almost all terminals.
|
||||||
- 🌟 **Built-in Code Highlighting and Image Decoding**: Combined with the pre-loading mechanism, greatly accelerates image and normal file loading.
|
- 🌟 **Built-in Code Highlighting and Image Decoding**: Combined with the pre-loading mechanism, greatly accelerates image and normal file loading.
|
||||||
- 🔌 **Concurrent Plugin System**: UI plugins (rewriting most of the UI), functional plugins (coming soon), custom previewer, and custom preloader; Just some pieces of Lua.
|
- 🔌 **Concurrent Plugin System**: UI plugins (rewriting most of the UI), functional plugins, custom previewer, and custom preloader; Just some pieces of Lua.
|
||||||
- 🧰 Integration with fd, rg, fzf, zoxide
|
- 🧰 Integration with fd, rg, fzf, zoxide
|
||||||
- 💫 Vim-like input/select component, auto-completion for cd paths
|
- 💫 Vim-like input/select/notify component, auto-completion for cd paths
|
||||||
- 🏷️ Multi-Tab Support, Scrollable Preview (for videos, PDFs, archives, directories, code, etc.)
|
- 🏷️ Multi-Tab Support, Cross-directory selection, Scrollable Preview (for videos, PDFs, archives, directories, code, etc.)
|
||||||
- 🔄 Bulk Renaming, Visual Mode, File Chooser
|
- 🔄 Bulk Renaming, Visual Mode, File Chooser
|
||||||
- 🎨 Theme System, Custom Layouts, Trash Bin, CSI u
|
- 🎨 Theme System, Custom Layouts, Trash Bin, CSI u
|
||||||
- ... and more!
|
- ... and more!
|
||||||
|
|
@ -46,8 +46,9 @@ https://github.com/sxyazi/yazi/assets/17523360/92ff23fa-0cd5-4f04-b387-894c12265
|
||||||
| foot | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
|
| foot | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
|
||||||
| Ghostty | [Kitty old protocol](https://github.com/sxyazi/yazi/blob/main/yazi-adaptor/src/kitty_old.rs) | ✅ Built-in |
|
| Ghostty | [Kitty old protocol](https://github.com/sxyazi/yazi/blob/main/yazi-adaptor/src/kitty_old.rs) | ✅ Built-in |
|
||||||
| Black Box | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
|
| Black Box | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
|
||||||
| Tabby | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
|
| VSCode | [Inline images protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |
|
||||||
| Hyper | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
|
| Tabby | [Inline images protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |
|
||||||
|
| Hyper | [Inline images protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |
|
||||||
| X11 / Wayland | Window system protocol | ☑️ Überzug++ required |
|
| X11 / Wayland | Window system protocol | ☑️ Überzug++ required |
|
||||||
| Fallback | [Chafa](https://hpjansson.org/chafa/) | ☑️ Überzug++ required |
|
| Fallback | [Chafa](https://hpjansson.org/chafa/) | ☑️ Überzug++ required |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,9 +60,9 @@
|
||||||
wrapProgram $out/bin/yazi \
|
wrapProgram $out/bin/yazi \
|
||||||
--prefix PATH : "${makeBinPath runtimePaths}"
|
--prefix PATH : "${makeBinPath runtimePaths}"
|
||||||
installShellCompletion --cmd yazi \
|
installShellCompletion --cmd yazi \
|
||||||
--bash ./yazi-config/completions/yazi.bash \
|
--bash ./yazi-boot/completions/yazi.bash \
|
||||||
--fish ./yazi-config/completions/yazi.fish \
|
--fish ./yazi-boot/completions/yazi.fish \
|
||||||
--zsh ./yazi-config/completions/_yazi
|
--zsh ./yazi-boot/completions/_yazi
|
||||||
|
|
||||||
# Resize logo
|
# Resize logo
|
||||||
for RES in 16 24 32 48 64 128 256; do
|
for RES in 16 24 32 48 64 128 256; do
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,26 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
export ARTIFACT_NAME="yazi-$1"
|
||||||
cd $SCRIPT_DIR/..
|
export YAZI_GEN_COMPLETIONS=1
|
||||||
|
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/aarch64-linux-gnu-gcc
|
||||||
|
|
||||||
cargo +stable build --release --target aarch64-apple-darwin
|
# Setup Rust toolchain
|
||||||
cargo +stable build --release --target x86_64-apple-darwin
|
rustup toolchain install stable --profile minimal
|
||||||
cargo +stable build --release --target x86_64-unknown-linux-gnu
|
rustup target add "$1"
|
||||||
cargo +stable build --release --target x86_64-pc-windows-gnu
|
|
||||||
|
|
||||||
mv target/aarch64-apple-darwin/release/yazi yazi-aarch64-apple-darwin
|
# Build for the target
|
||||||
mv target/x86_64-apple-darwin/release/yazi yazi-x86_64-apple-darwin
|
cargo build --release --locked --target "$1"
|
||||||
mv target/x86_64-unknown-linux-gnu/release/yazi yazi-x86_64-unknown-linux-gnu
|
|
||||||
mv target/x86_64-pc-windows-gnu/release/yazi.exe yazi-x86_64-pc-windows-gnu.exe
|
|
||||||
|
|
||||||
zip -j yazi-aarch64-apple-darwin.zip yazi-aarch64-apple-darwin
|
# Create the artifact
|
||||||
zip -j yazi-x86_64-apple-darwin.zip yazi-x86_64-apple-darwin
|
mkdir "$ARTIFACT_NAME"
|
||||||
zip -j yazi-x86_64-unknown-linux-gnu.zip yazi-x86_64-unknown-linux-gnu
|
cp "target/$1/release/yazi" "$ARTIFACT_NAME"
|
||||||
zip -j yazi-x86_64-pc-windows-gnu.zip yazi-x86_64-pc-windows-gnu.exe
|
cp -r yazi-boot/completions "$ARTIFACT_NAME"
|
||||||
|
cp README.md LICENSE "$ARTIFACT_NAME"
|
||||||
|
|
||||||
|
# Zip the artifact
|
||||||
|
if ! command -v zip &> /dev/null
|
||||||
|
then
|
||||||
|
sudo apt-get update && sudo apt-get install -yq zip
|
||||||
|
fi
|
||||||
|
zip -r "$ARTIFACT_NAME.zip" "$ARTIFACT_NAME"
|
||||||
|
|
|
||||||
|
|
@ -92,9 +92,9 @@ impl Adaptor {
|
||||||
Emulator::Foot => vec![Self::Sixel],
|
Emulator::Foot => vec![Self::Sixel],
|
||||||
Emulator::Ghostty => vec![Self::KittyOld],
|
Emulator::Ghostty => vec![Self::KittyOld],
|
||||||
Emulator::BlackBox => vec![Self::Sixel],
|
Emulator::BlackBox => vec![Self::Sixel],
|
||||||
Emulator::VSCode => vec![Self::Sixel],
|
Emulator::VSCode => vec![Self::Iterm2, Self::Sixel],
|
||||||
Emulator::Tabby => vec![Self::Sixel],
|
Emulator::Tabby => vec![Self::Iterm2, Self::Sixel],
|
||||||
Emulator::Hyper => vec![Self::Sixel],
|
Emulator::Hyper => vec![Self::Iterm2, Self::Sixel],
|
||||||
Emulator::Mintty => vec![Self::Iterm2],
|
Emulator::Mintty => vec![Self::Iterm2],
|
||||||
Emulator::Neovim => vec![],
|
Emulator::Neovim => vec![],
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#[path = "src/args.rs"]
|
#[path = "src/args.rs"]
|
||||||
mod args;
|
mod args;
|
||||||
|
|
||||||
use std::{env, error::Error, fs};
|
use std::{env, error::Error};
|
||||||
|
|
||||||
use clap::CommandFactory;
|
use clap::CommandFactory;
|
||||||
use clap_complete::{generate_to, Shell};
|
use clap_complete::{generate_to, Shell};
|
||||||
|
|
@ -18,7 +18,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let bin = "yazi";
|
let bin = "yazi";
|
||||||
let out = "completions";
|
let out = "completions";
|
||||||
|
|
||||||
fs::create_dir_all(out)?;
|
std::fs::create_dir_all(out)?;
|
||||||
generate_to(Shell::Bash, cmd, bin, out)?;
|
generate_to(Shell::Bash, cmd, bin, out)?;
|
||||||
generate_to(Shell::Fish, cmd, bin, out)?;
|
generate_to(Shell::Fish, cmd, bin, out)?;
|
||||||
generate_to(Shell::Zsh, cmd, bin, out)?;
|
generate_to(Shell::Zsh, cmd, bin, out)?;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{ffi::OsString, fs, path::{Path, PathBuf}, process};
|
use std::{ffi::OsString, path::{Path, PathBuf}, process};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
@ -14,8 +14,8 @@ pub struct Boot {
|
||||||
pub file: Option<OsString>,
|
pub file: Option<OsString>,
|
||||||
|
|
||||||
pub config_dir: PathBuf,
|
pub config_dir: PathBuf,
|
||||||
|
pub flavor_dir: PathBuf,
|
||||||
pub plugin_dir: PathBuf,
|
pub plugin_dir: PathBuf,
|
||||||
pub state_dir: PathBuf,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Boot {
|
impl Boot {
|
||||||
|
|
@ -36,20 +36,20 @@ impl Boot {
|
||||||
|
|
||||||
impl Default for Boot {
|
impl Default for Boot {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
let config_dir = Xdg::config_dir();
|
||||||
let (cwd, file) = Self::parse_entry(ARGS.entry.as_deref());
|
let (cwd, file) = Self::parse_entry(ARGS.entry.as_deref());
|
||||||
|
|
||||||
let boot = Self {
|
let boot = Self {
|
||||||
cwd,
|
cwd,
|
||||||
file,
|
file,
|
||||||
|
|
||||||
config_dir: Xdg::config_dir().unwrap(),
|
flavor_dir: config_dir.join("flavors"),
|
||||||
plugin_dir: Xdg::plugin_dir().unwrap(),
|
plugin_dir: config_dir.join("plugins"),
|
||||||
state_dir: Xdg::state_dir().unwrap(),
|
config_dir,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !boot.state_dir.is_dir() {
|
std::fs::create_dir_all(&boot.flavor_dir).expect("Failed to create flavor directory");
|
||||||
fs::create_dir_all(&boot.state_dir).unwrap();
|
std::fs::create_dir_all(&boot.plugin_dir).expect("Failed to create plugin directory");
|
||||||
}
|
|
||||||
|
|
||||||
boot
|
boot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -71,7 +71,7 @@ impl Default for Args {
|
||||||
if args.clear_cache {
|
if args.clear_cache {
|
||||||
if PREVIEW.cache_dir == Xdg::cache_dir() {
|
if PREVIEW.cache_dir == Xdg::cache_dir() {
|
||||||
println!("Clearing cache directory: \n{:?}", PREVIEW.cache_dir);
|
println!("Clearing cache directory: \n{:?}", PREVIEW.cache_dir);
|
||||||
fs::remove_dir_all(&PREVIEW.cache_dir).unwrap();
|
std::fs::remove_dir_all(&PREVIEW.cache_dir).unwrap();
|
||||||
} else {
|
} else {
|
||||||
println!(
|
println!(
|
||||||
"You've changed the default cache directory, for your data's safety, please clear it manually: \n{:?}",
|
"You've changed the default cache directory, for your data's safety, please clear it manually: \n{:?}",
|
||||||
|
|
|
||||||
|
|
@ -5,296 +5,301 @@
|
||||||
[manager]
|
[manager]
|
||||||
|
|
||||||
keymap = [
|
keymap = [
|
||||||
{ on = [ "<Esc>" ], exec = "escape", desc = "Exit visual mode, clear selected, or cancel search" },
|
{ on = [ "<Esc>" ], run = "escape", desc = "Exit visual mode, clear selected, or cancel search" },
|
||||||
{ on = [ "q" ], exec = "quit", desc = "Exit the process" },
|
{ on = [ "<C-[>" ], run = "escape", desc = "Exit visual mode, clear selected, or cancel search" },
|
||||||
{ on = [ "Q" ], exec = "quit --no-cwd-file", desc = "Exit the process without writing cwd-file" },
|
{ on = [ "q" ], run = "quit", desc = "Exit the process" },
|
||||||
{ on = [ "<C-q>" ], exec = "close", desc = "Close the current tab, or quit if it is last tab" },
|
{ on = [ "Q" ], run = "quit --no-cwd-file", desc = "Exit the process without writing cwd-file" },
|
||||||
{ on = [ "<C-z>" ], exec = "suspend", desc = "Suspend the process" },
|
{ on = [ "<C-q>" ], run = "close", desc = "Close the current tab, or quit if it is last tab" },
|
||||||
|
{ on = [ "<C-z>" ], run = "suspend", desc = "Suspend the process" },
|
||||||
|
|
||||||
# Navigation
|
# Navigation
|
||||||
{ on = [ "k" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "k" ], run = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "j" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "j" ], run = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
||||||
{ on = [ "K" ], exec = "arrow -5", desc = "Move cursor up 5 lines" },
|
{ on = [ "K" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||||
{ on = [ "J" ], exec = "arrow 5", desc = "Move cursor down 5 lines" },
|
{ on = [ "J" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||||
|
|
||||||
{ on = [ "<S-Up>" ], exec = "arrow -5", desc = "Move cursor up 5 lines" },
|
{ on = [ "<S-Up>" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||||
{ on = [ "<S-Down>" ], exec = "arrow 5", desc = "Move cursor down 5 lines" },
|
{ on = [ "<S-Down>" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||||
|
|
||||||
{ on = [ "<C-u>" ], exec = "arrow -50%", desc = "Move cursor up half page" },
|
{ on = [ "<C-u>" ], run = "arrow -50%", desc = "Move cursor up half page" },
|
||||||
{ on = [ "<C-d>" ], exec = "arrow 50%", desc = "Move cursor down half page" },
|
{ on = [ "<C-d>" ], run = "arrow 50%", desc = "Move cursor down half page" },
|
||||||
{ on = [ "<C-b>" ], exec = "arrow -100%", desc = "Move cursor up one page" },
|
{ on = [ "<C-b>" ], run = "arrow -100%", desc = "Move cursor up one page" },
|
||||||
{ on = [ "<C-f>" ], exec = "arrow 100%", desc = "Move cursor down one page" },
|
{ on = [ "<C-f>" ], run = "arrow 100%", desc = "Move cursor down one page" },
|
||||||
|
|
||||||
{ on = [ "<C-PageUp>" ], exec = "arrow -50%", desc = "Move cursor up half page" },
|
{ on = [ "<C-PageUp>" ], run = "arrow -50%", desc = "Move cursor up half page" },
|
||||||
{ on = [ "<C-PageDown>" ], exec = "arrow 50%", desc = "Move cursor down half page" },
|
{ on = [ "<C-PageDown>" ], run = "arrow 50%", desc = "Move cursor down half page" },
|
||||||
{ on = [ "<PageUp>" ], exec = "arrow -100%", desc = "Move cursor up one page" },
|
{ on = [ "<PageUp>" ], run = "arrow -100%", desc = "Move cursor up one page" },
|
||||||
{ on = [ "<PageDown>" ], exec = "arrow 100%", desc = "Move cursor down one page" },
|
{ on = [ "<PageDown>" ], run = "arrow 100%", desc = "Move cursor down one page" },
|
||||||
|
|
||||||
{ on = [ "h" ], exec = "leave", desc = "Go back to the parent directory" },
|
{ on = [ "h" ], run = "leave", desc = "Go back to the parent directory" },
|
||||||
{ on = [ "l" ], exec = "enter", desc = "Enter the child directory" },
|
{ on = [ "l" ], run = "enter", desc = "Enter the child directory" },
|
||||||
|
|
||||||
{ on = [ "H" ], exec = "back", desc = "Go back to the previous directory" },
|
{ on = [ "H" ], run = "back", desc = "Go back to the previous directory" },
|
||||||
{ on = [ "L" ], exec = "forward", desc = "Go forward to the next directory" },
|
{ on = [ "L" ], run = "forward", desc = "Go forward to the next directory" },
|
||||||
|
|
||||||
{ on = [ "<A-k>" ], exec = "seek -5", desc = "Seek up 5 units in the preview" },
|
{ on = [ "<A-k>" ], run = "seek -5", desc = "Seek up 5 units in the preview" },
|
||||||
{ on = [ "<A-j>" ], exec = "seek 5", desc = "Seek down 5 units in the preview" },
|
{ on = [ "<A-j>" ], run = "seek 5", desc = "Seek down 5 units in the preview" },
|
||||||
{ on = [ "<A-PageUp>" ], exec = "seek -5", desc = "Seek up 5 units in the preview" },
|
{ on = [ "<A-PageUp>" ], run = "seek -5", desc = "Seek up 5 units in the preview" },
|
||||||
{ on = [ "<A-PageDown>" ], exec = "seek 5", desc = "Seek down 5 units in the preview" },
|
{ on = [ "<A-PageDown>" ], run = "seek 5", desc = "Seek down 5 units in the preview" },
|
||||||
|
|
||||||
{ on = [ "<Up>" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "<Up>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "<Down>" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "<Down>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||||
{ on = [ "<Left>" ], exec = "leave", desc = "Go back to the parent directory" },
|
{ on = [ "<Left>" ], run = "leave", desc = "Go back to the parent directory" },
|
||||||
{ on = [ "<Right>" ], exec = "enter", desc = "Enter the child directory" },
|
{ on = [ "<Right>" ], run = "enter", desc = "Enter the child directory" },
|
||||||
|
|
||||||
{ on = [ "g", "g" ], exec = "arrow -99999999", desc = "Move cursor to the top" },
|
{ on = [ "g", "g" ], run = "arrow -99999999", desc = "Move cursor to the top" },
|
||||||
{ on = [ "G" ], exec = "arrow 99999999", desc = "Move cursor to the bottom" },
|
{ on = [ "G" ], run = "arrow 99999999", desc = "Move cursor to the bottom" },
|
||||||
|
|
||||||
# Selection
|
# Selection
|
||||||
{ on = [ "<Space>" ], exec = [ "select --state=none", "arrow 1" ], desc = "Toggle the current selection state" },
|
{ on = [ "<Space>" ], run = [ "select --state=none", "arrow 1" ], desc = "Toggle the current selection state" },
|
||||||
{ on = [ "v" ], exec = "visual_mode", desc = "Enter visual mode (selection mode)" },
|
{ on = [ "v" ], run = "visual_mode", desc = "Enter visual mode (selection mode)" },
|
||||||
{ on = [ "V" ], exec = "visual_mode --unset", desc = "Enter visual mode (unset mode)" },
|
{ on = [ "V" ], run = "visual_mode --unset", desc = "Enter visual mode (unset mode)" },
|
||||||
{ on = [ "<C-a>" ], exec = "select_all --state=true", desc = "Select all files" },
|
{ on = [ "<C-a>" ], run = "select_all --state=true", desc = "Select all files" },
|
||||||
{ on = [ "<C-r>" ], exec = "select_all --state=none", desc = "Inverse selection of all files" },
|
{ on = [ "<C-r>" ], run = "select_all --state=none", desc = "Inverse selection of all files" },
|
||||||
|
|
||||||
# Operation
|
# Operation
|
||||||
{ on = [ "o" ], exec = "open", desc = "Open the selected files" },
|
{ on = [ "o" ], run = "open", desc = "Open the selected files" },
|
||||||
{ on = [ "O" ], exec = "open --interactive", desc = "Open the selected files interactively" },
|
{ on = [ "O" ], run = "open --interactive", desc = "Open the selected files interactively" },
|
||||||
{ on = [ "<Enter>" ], exec = "open", desc = "Open the selected files" },
|
{ on = [ "<Enter>" ], run = "open", desc = "Open the selected files" },
|
||||||
{ on = [ "<C-Enter>" ], exec = "open --interactive", desc = "Open the selected files interactively" },
|
{ on = [ "<C-Enter>" ], run = "open --interactive", desc = "Open the selected files interactively" },
|
||||||
{ on = [ "y" ], exec = "yank", desc = "Copy the selected files" },
|
{ on = [ "y" ], run = "yank", desc = "Copy the selected files" },
|
||||||
{ on = [ "Y" ], exec = "unyank", desc = "Cancel the yank status of files" },
|
{ on = [ "Y" ], run = "unyank", desc = "Cancel the yank status of files" },
|
||||||
{ on = [ "x" ], exec = "yank --cut", desc = "Cut the selected files" },
|
{ on = [ "x" ], run = "yank --cut", desc = "Cut the selected files" },
|
||||||
{ on = [ "p" ], exec = "paste", desc = "Paste the files" },
|
{ on = [ "p" ], run = "paste", desc = "Paste the files" },
|
||||||
{ on = [ "P" ], exec = "paste --force", desc = "Paste the files (overwrite if the destination exists)" },
|
{ on = [ "P" ], run = "paste --force", desc = "Paste the files (overwrite if the destination exists)" },
|
||||||
{ on = [ "-" ], exec = "link", desc = "Symlink the absolute path of files" },
|
{ on = [ "-" ], run = "link", desc = "Symlink the absolute path of files" },
|
||||||
{ on = [ "_" ], exec = "link --relative", desc = "Symlink the relative path of files" },
|
{ on = [ "_" ], run = "link --relative", desc = "Symlink the relative path of files" },
|
||||||
{ on = [ "d" ], exec = "remove", desc = "Move the files to the trash" },
|
{ on = [ "d" ], run = "remove", desc = "Move the files to the trash" },
|
||||||
{ on = [ "D" ], exec = "remove --permanently", desc = "Permanently delete the files" },
|
{ on = [ "D" ], run = "remove --permanently", desc = "Permanently delete the files" },
|
||||||
{ on = [ "a" ], exec = "create", desc = "Create a file or directory (ends with / for directories)" },
|
{ on = [ "a" ], run = "create", desc = "Create a file or directory (ends with / for directories)" },
|
||||||
{ on = [ "r" ], exec = "rename --cursor=before_ext", desc = "Rename a file or directory" },
|
{ on = [ "r" ], run = "rename --cursor=before_ext", desc = "Rename a file or directory" },
|
||||||
{ on = [ ";" ], exec = "shell", desc = "Run a shell command" },
|
{ on = [ ";" ], run = "shell", desc = "Run a shell command" },
|
||||||
{ on = [ ":" ], exec = "shell --block", desc = "Run a shell command (block the UI until the command finishes)" },
|
{ on = [ ":" ], run = "shell --block", desc = "Run a shell command (block the UI until the command finishes)" },
|
||||||
{ on = [ "." ], exec = "hidden toggle", desc = "Toggle the visibility of hidden files" },
|
{ on = [ "." ], run = "hidden toggle", desc = "Toggle the visibility of hidden files" },
|
||||||
{ on = [ "s" ], exec = "search fd", desc = "Search files by name using fd" },
|
{ on = [ "s" ], run = "search fd", desc = "Search files by name using fd" },
|
||||||
{ on = [ "S" ], exec = "search rg", desc = "Search files by content using ripgrep" },
|
{ on = [ "S" ], run = "search rg", desc = "Search files by content using ripgrep" },
|
||||||
{ on = [ "<C-s>" ], exec = "search none", desc = "Cancel the ongoing search" },
|
{ on = [ "<C-s>" ], run = "search none", desc = "Cancel the ongoing search" },
|
||||||
{ on = [ "z" ], exec = "jump zoxide", desc = "Jump to a directory using zoxide" },
|
{ on = [ "z" ], run = "jump zoxide", desc = "Jump to a directory using zoxide" },
|
||||||
{ on = [ "Z" ], exec = "jump fzf", desc = "Jump to a directory, or reveal a file using fzf" },
|
{ on = [ "Z" ], run = "jump fzf", desc = "Jump to a directory, or reveal a file using fzf" },
|
||||||
|
|
||||||
# Linemode
|
# Linemode
|
||||||
{ on = [ "m", "s" ], exec = "linemode size", desc = "Set linemode to size" },
|
{ on = [ "m", "s" ], run = "linemode size", desc = "Set linemode to size" },
|
||||||
{ on = [ "m", "p" ], exec = "linemode permissions", desc = "Set linemode to permissions" },
|
{ on = [ "m", "p" ], run = "linemode permissions", desc = "Set linemode to permissions" },
|
||||||
{ on = [ "m", "m" ], exec = "linemode mtime", desc = "Set linemode to mtime" },
|
{ on = [ "m", "m" ], run = "linemode mtime", desc = "Set linemode to mtime" },
|
||||||
{ on = [ "m", "n" ], exec = "linemode none", desc = "Set linemode to none" },
|
{ on = [ "m", "n" ], run = "linemode none", desc = "Set linemode to none" },
|
||||||
|
|
||||||
# Copy
|
# Copy
|
||||||
{ on = [ "c", "c" ], exec = "copy path", desc = "Copy the absolute path" },
|
{ on = [ "c", "c" ], run = "copy path", desc = "Copy the absolute path" },
|
||||||
{ on = [ "c", "d" ], exec = "copy dirname", desc = "Copy the path of the parent directory" },
|
{ on = [ "c", "d" ], run = "copy dirname", desc = "Copy the path of the parent directory" },
|
||||||
{ on = [ "c", "f" ], exec = "copy filename", desc = "Copy the name of the file" },
|
{ on = [ "c", "f" ], run = "copy filename", desc = "Copy the name of the file" },
|
||||||
{ on = [ "c", "n" ], exec = "copy name_without_ext", desc = "Copy the name of the file without the extension" },
|
{ on = [ "c", "n" ], run = "copy name_without_ext", desc = "Copy the name of the file without the extension" },
|
||||||
|
|
||||||
# Filter
|
# Filter
|
||||||
{ on = [ "f" ], exec = "filter --smart", desc = "Filter the files" },
|
{ on = [ "f" ], run = "filter --smart", desc = "Filter the files" },
|
||||||
|
|
||||||
# Find
|
# Find
|
||||||
{ on = [ "/" ], exec = "find --smart", desc = "Find next file" },
|
{ on = [ "/" ], run = "find --smart", desc = "Find next file" },
|
||||||
{ on = [ "?" ], exec = "find --previous --smart", desc = "Find previous file" },
|
{ on = [ "?" ], run = "find --previous --smart", desc = "Find previous file" },
|
||||||
{ on = [ "n" ], exec = "find_arrow", desc = "Go to next found file" },
|
{ on = [ "n" ], run = "find_arrow", desc = "Go to next found file" },
|
||||||
{ on = [ "N" ], exec = "find_arrow --previous", desc = "Go to previous found file" },
|
{ on = [ "N" ], run = "find_arrow --previous", desc = "Go to previous found file" },
|
||||||
|
|
||||||
# Sorting
|
# Sorting
|
||||||
{ on = [ ",", "m" ], exec = "sort modified --dir-first", desc = "Sort by modified time" },
|
{ on = [ ",", "m" ], run = "sort modified --dir-first", desc = "Sort by modified time" },
|
||||||
{ on = [ ",", "M" ], exec = "sort modified --reverse --dir-first", desc = "Sort by modified time (reverse)" },
|
{ on = [ ",", "M" ], run = "sort modified --reverse --dir-first", desc = "Sort by modified time (reverse)" },
|
||||||
{ on = [ ",", "c" ], exec = "sort created --dir-first", desc = "Sort by created time" },
|
{ on = [ ",", "c" ], run = "sort created --dir-first", desc = "Sort by created time" },
|
||||||
{ on = [ ",", "C" ], exec = "sort created --reverse --dir-first", desc = "Sort by created time (reverse)" },
|
{ on = [ ",", "C" ], run = "sort created --reverse --dir-first", desc = "Sort by created time (reverse)" },
|
||||||
{ on = [ ",", "e" ], exec = "sort extension --dir-first", desc = "Sort by extension" },
|
{ on = [ ",", "e" ], run = "sort extension --dir-first", desc = "Sort by extension" },
|
||||||
{ on = [ ",", "E" ], exec = "sort extension --reverse --dir-first", desc = "Sort by extension (reverse)" },
|
{ on = [ ",", "E" ], run = "sort extension --reverse --dir-first", desc = "Sort by extension (reverse)" },
|
||||||
{ on = [ ",", "a" ], exec = "sort alphabetical --dir-first", desc = "Sort alphabetically" },
|
{ on = [ ",", "a" ], run = "sort alphabetical --dir-first", desc = "Sort alphabetically" },
|
||||||
{ on = [ ",", "A" ], exec = "sort alphabetical --reverse --dir-first", desc = "Sort alphabetically (reverse)" },
|
{ on = [ ",", "A" ], run = "sort alphabetical --reverse --dir-first", desc = "Sort alphabetically (reverse)" },
|
||||||
{ on = [ ",", "n" ], exec = "sort natural --dir-first", desc = "Sort naturally" },
|
{ on = [ ",", "n" ], run = "sort natural --dir-first", desc = "Sort naturally" },
|
||||||
{ on = [ ",", "N" ], exec = "sort natural --reverse --dir-first", desc = "Sort naturally (reverse)" },
|
{ on = [ ",", "N" ], run = "sort natural --reverse --dir-first", desc = "Sort naturally (reverse)" },
|
||||||
{ on = [ ",", "s" ], exec = "sort size --dir-first", desc = "Sort by size" },
|
{ on = [ ",", "s" ], run = "sort size --dir-first", desc = "Sort by size" },
|
||||||
{ on = [ ",", "S" ], exec = "sort size --reverse --dir-first", desc = "Sort by size (reverse)" },
|
{ on = [ ",", "S" ], run = "sort size --reverse --dir-first", desc = "Sort by size (reverse)" },
|
||||||
|
|
||||||
# Tabs
|
# Tabs
|
||||||
{ on = [ "t" ], exec = "tab_create --current", desc = "Create a new tab using the current path" },
|
{ on = [ "t" ], run = "tab_create --current", desc = "Create a new tab using the current path" },
|
||||||
|
|
||||||
{ on = [ "1" ], exec = "tab_switch 0", desc = "Switch to the first tab" },
|
{ on = [ "1" ], run = "tab_switch 0", desc = "Switch to the first tab" },
|
||||||
{ on = [ "2" ], exec = "tab_switch 1", desc = "Switch to the second tab" },
|
{ on = [ "2" ], run = "tab_switch 1", desc = "Switch to the second tab" },
|
||||||
{ on = [ "3" ], exec = "tab_switch 2", desc = "Switch to the third tab" },
|
{ on = [ "3" ], run = "tab_switch 2", desc = "Switch to the third tab" },
|
||||||
{ on = [ "4" ], exec = "tab_switch 3", desc = "Switch to the fourth tab" },
|
{ on = [ "4" ], run = "tab_switch 3", desc = "Switch to the fourth tab" },
|
||||||
{ on = [ "5" ], exec = "tab_switch 4", desc = "Switch to the fifth tab" },
|
{ on = [ "5" ], run = "tab_switch 4", desc = "Switch to the fifth tab" },
|
||||||
{ on = [ "6" ], exec = "tab_switch 5", desc = "Switch to the sixth tab" },
|
{ on = [ "6" ], run = "tab_switch 5", desc = "Switch to the sixth tab" },
|
||||||
{ on = [ "7" ], exec = "tab_switch 6", desc = "Switch to the seventh tab" },
|
{ on = [ "7" ], run = "tab_switch 6", desc = "Switch to the seventh tab" },
|
||||||
{ on = [ "8" ], exec = "tab_switch 7", desc = "Switch to the eighth tab" },
|
{ on = [ "8" ], run = "tab_switch 7", desc = "Switch to the eighth tab" },
|
||||||
{ on = [ "9" ], exec = "tab_switch 8", desc = "Switch to the ninth tab" },
|
{ on = [ "9" ], run = "tab_switch 8", desc = "Switch to the ninth tab" },
|
||||||
|
|
||||||
{ on = [ "[" ], exec = "tab_switch -1 --relative", desc = "Switch to the previous tab" },
|
{ on = [ "[" ], run = "tab_switch -1 --relative", desc = "Switch to the previous tab" },
|
||||||
{ on = [ "]" ], exec = "tab_switch 1 --relative", desc = "Switch to the next tab" },
|
{ on = [ "]" ], run = "tab_switch 1 --relative", desc = "Switch to the next tab" },
|
||||||
|
|
||||||
{ on = [ "{" ], exec = "tab_swap -1", desc = "Swap the current tab with the previous tab" },
|
{ on = [ "{" ], run = "tab_swap -1", desc = "Swap the current tab with the previous tab" },
|
||||||
{ on = [ "}" ], exec = "tab_swap 1", desc = "Swap the current tab with the next tab" },
|
{ on = [ "}" ], run = "tab_swap 1", desc = "Swap the current tab with the next tab" },
|
||||||
|
|
||||||
# Tasks
|
# Tasks
|
||||||
{ on = [ "w" ], exec = "tasks_show", desc = "Show the tasks manager" },
|
{ on = [ "w" ], run = "tasks_show", desc = "Show the tasks manager" },
|
||||||
|
|
||||||
# Goto
|
# Goto
|
||||||
{ on = [ "g", "h" ], exec = "cd ~", desc = "Go to the home directory" },
|
{ on = [ "g", "h" ], run = "cd ~", desc = "Go to the home directory" },
|
||||||
{ on = [ "g", "c" ], exec = "cd ~/.config", desc = "Go to the config directory" },
|
{ on = [ "g", "c" ], run = "cd ~/.config", desc = "Go to the config directory" },
|
||||||
{ on = [ "g", "d" ], exec = "cd ~/Downloads", desc = "Go to the downloads directory" },
|
{ on = [ "g", "d" ], run = "cd ~/Downloads", desc = "Go to the downloads directory" },
|
||||||
{ on = [ "g", "t" ], exec = "cd /tmp", desc = "Go to the temporary directory" },
|
{ on = [ "g", "t" ], run = "cd /tmp", desc = "Go to the temporary directory" },
|
||||||
{ on = [ "g", "<Space>" ], exec = "cd --interactive", desc = "Go to a directory interactively" },
|
{ on = [ "g", "<Space>" ], run = "cd --interactive", desc = "Go to a directory interactively" },
|
||||||
|
|
||||||
# Help
|
# Help
|
||||||
{ on = [ "~" ], exec = "help", desc = "Open help" },
|
{ on = [ "~" ], run = "help", desc = "Open help" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[tasks]
|
[tasks]
|
||||||
|
|
||||||
keymap = [
|
keymap = [
|
||||||
{ on = [ "<Esc>" ], exec = "close", desc = "Hide the task manager" },
|
{ on = [ "<Esc>" ], run = "close", desc = "Hide the task manager" },
|
||||||
{ on = [ "<C-q>" ], exec = "close", desc = "Hide the task manager" },
|
{ on = [ "<C-[>" ], run = "close", desc = "Hide the task manager" },
|
||||||
{ on = [ "w" ], exec = "close", desc = "Hide the task manager" },
|
{ on = [ "<C-q>" ], run = "close", desc = "Hide the task manager" },
|
||||||
|
{ on = [ "w" ], run = "close", desc = "Hide the task manager" },
|
||||||
|
|
||||||
{ on = [ "k" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "k" ], run = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "j" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "j" ], run = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
||||||
{ on = [ "<Up>" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "<Up>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "<Down>" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "<Down>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
||||||
{ on = [ "<Enter>" ], exec = "inspect", desc = "Inspect the task" },
|
{ on = [ "<Enter>" ], run = "inspect", desc = "Inspect the task" },
|
||||||
{ on = [ "x" ], exec = "cancel", desc = "Cancel the task" },
|
{ on = [ "x" ], run = "cancel", desc = "Cancel the task" },
|
||||||
|
|
||||||
{ on = [ "~" ], exec = "help", desc = "Open help" }
|
{ on = [ "~" ], run = "help", desc = "Open help" }
|
||||||
]
|
]
|
||||||
|
|
||||||
[select]
|
[select]
|
||||||
|
|
||||||
keymap = [
|
keymap = [
|
||||||
{ on = [ "<C-q>" ], exec = "close", desc = "Cancel selection" },
|
{ on = [ "<Esc>" ], run = "close", desc = "Cancel selection" },
|
||||||
{ on = [ "<Esc>" ], exec = "close", desc = "Cancel selection" },
|
{ on = [ "<C-[>" ], run = "close", desc = "Cancel selection" },
|
||||||
{ on = [ "<Enter>" ], exec = "close --submit", desc = "Submit the selection" },
|
{ on = [ "<C-q>" ], run = "close", desc = "Cancel selection" },
|
||||||
|
{ on = [ "<Enter>" ], run = "close --submit", desc = "Submit the selection" },
|
||||||
|
|
||||||
{ on = [ "k" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "k" ], run = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "j" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "j" ], run = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
||||||
{ on = [ "K" ], exec = "arrow -5", desc = "Move cursor up 5 lines" },
|
{ on = [ "K" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||||
{ on = [ "J" ], exec = "arrow 5", desc = "Move cursor down 5 lines" },
|
{ on = [ "J" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||||
|
|
||||||
{ on = [ "<Up>" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "<Up>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "<Down>" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "<Down>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
||||||
{ on = [ "<S-Up>" ], exec = "arrow -5", desc = "Move cursor up 5 lines" },
|
{ on = [ "<S-Up>" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||||
{ on = [ "<S-Down>" ], exec = "arrow 5", desc = "Move cursor down 5 lines" },
|
{ on = [ "<S-Down>" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||||
|
|
||||||
{ on = [ "~" ], exec = "help", desc = "Open help" }
|
{ on = [ "~" ], run = "help", desc = "Open help" }
|
||||||
]
|
]
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
|
|
||||||
keymap = [
|
keymap = [
|
||||||
{ on = [ "<C-q>" ], exec = "close", desc = "Cancel input" },
|
{ on = [ "<C-q>" ], run = "close", desc = "Cancel input" },
|
||||||
{ on = [ "<Enter>" ], exec = "close --submit", desc = "Submit the input" },
|
{ on = [ "<Enter>" ], run = "close --submit", desc = "Submit the input" },
|
||||||
{ on = [ "<Esc>" ], exec = "escape", desc = "Go back the normal mode, or cancel input" },
|
{ on = [ "<Esc>" ], run = "escape", desc = "Go back the normal mode, or cancel input" },
|
||||||
|
{ on = [ "<C-[>" ], run = "escape", desc = "Go back the normal mode, or cancel input" },
|
||||||
|
|
||||||
# Mode
|
# Mode
|
||||||
{ on = [ "i" ], exec = "insert", desc = "Enter insert mode" },
|
{ on = [ "i" ], run = "insert", desc = "Enter insert mode" },
|
||||||
{ on = [ "a" ], exec = "insert --append", desc = "Enter append mode" },
|
{ on = [ "a" ], run = "insert --append", desc = "Enter append mode" },
|
||||||
{ on = [ "I" ], exec = [ "move -999", "insert" ], desc = "Move to the BOL, and enter insert mode" },
|
{ on = [ "I" ], run = [ "move -999", "insert" ], desc = "Move to the BOL, and enter insert mode" },
|
||||||
{ on = [ "A" ], exec = [ "move 999", "insert --append" ], desc = "Move to the EOL, and enter append mode" },
|
{ on = [ "A" ], run = [ "move 999", "insert --append" ], desc = "Move to the EOL, and enter append mode" },
|
||||||
{ on = [ "v" ], exec = "visual", desc = "Enter visual mode" },
|
{ on = [ "v" ], run = "visual", desc = "Enter visual mode" },
|
||||||
{ on = [ "V" ], exec = [ "move -999", "visual", "move 999" ], desc = "Enter visual mode and select all" },
|
{ on = [ "V" ], run = [ "move -999", "visual", "move 999" ], desc = "Enter visual mode and select all" },
|
||||||
|
|
||||||
# Character-wise movement
|
# Character-wise movement
|
||||||
{ on = [ "h" ], exec = "move -1", desc = "Move back a character" },
|
{ on = [ "h" ], run = "move -1", desc = "Move back a character" },
|
||||||
{ on = [ "l" ], exec = "move 1", desc = "Move forward a character" },
|
{ on = [ "l" ], run = "move 1", desc = "Move forward a character" },
|
||||||
{ on = [ "<Left>" ], exec = "move -1", desc = "Move back a character" },
|
{ on = [ "<Left>" ], run = "move -1", desc = "Move back a character" },
|
||||||
{ on = [ "<Right>" ], exec = "move 1", desc = "Move forward a character" },
|
{ on = [ "<Right>" ], run = "move 1", desc = "Move forward a character" },
|
||||||
{ on = [ "<C-b>" ], exec = "move -1", desc = "Move back a character" },
|
{ on = [ "<C-b>" ], run = "move -1", desc = "Move back a character" },
|
||||||
{ on = [ "<C-f>" ], exec = "move 1", desc = "Move forward a character" },
|
{ on = [ "<C-f>" ], run = "move 1", desc = "Move forward a character" },
|
||||||
|
|
||||||
# Word-wise movement
|
# Word-wise movement
|
||||||
{ on = [ "b" ], exec = "backward", desc = "Move back to the start of the current or previous word" },
|
{ on = [ "b" ], run = "backward", desc = "Move back to the start of the current or previous word" },
|
||||||
{ on = [ "w" ], exec = "forward", desc = "Move forward to the start of the next word" },
|
{ on = [ "w" ], run = "forward", desc = "Move forward to the start of the next word" },
|
||||||
{ on = [ "e" ], exec = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
{ on = [ "e" ], run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||||
{ on = [ "<A-b>" ], exec = "backward", desc = "Move back to the start of the current or previous word" },
|
{ on = [ "<A-b>" ], run = "backward", desc = "Move back to the start of the current or previous word" },
|
||||||
{ on = [ "<A-f>" ], exec = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
{ on = [ "<A-f>" ], run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||||
|
|
||||||
# Line-wise movement
|
# Line-wise movement
|
||||||
{ on = [ "0" ], exec = "move -999", desc = "Move to the BOL" },
|
{ on = [ "0" ], run = "move -999", desc = "Move to the BOL" },
|
||||||
{ on = [ "$" ], exec = "move 999", desc = "Move to the EOL" },
|
{ on = [ "$" ], run = "move 999", desc = "Move to the EOL" },
|
||||||
{ on = [ "<C-a>" ], exec = "move -999", desc = "Move to the BOL" },
|
{ on = [ "<C-a>" ], run = "move -999", desc = "Move to the BOL" },
|
||||||
{ on = [ "<C-e>" ], exec = "move 999", desc = "Move to the EOL" },
|
{ on = [ "<C-e>" ], run = "move 999", desc = "Move to the EOL" },
|
||||||
{ on = [ "<Home>" ], exec = "move -999", desc = "Move to the BOL" },
|
{ on = [ "<Home>" ], run = "move -999", desc = "Move to the BOL" },
|
||||||
{ on = [ "<End>" ], exec = "move 999", desc = "Move to the EOL" },
|
{ on = [ "<End>" ], run = "move 999", desc = "Move to the EOL" },
|
||||||
|
|
||||||
# Delete
|
# Delete
|
||||||
{ on = [ "<Backspace>" ], exec = "backspace", desc = "Delete the character before the cursor" },
|
{ on = [ "<Backspace>" ], run = "backspace", desc = "Delete the character before the cursor" },
|
||||||
{ on = [ "<Delete>" ], exec = "backspace --under", desc = "Delete the character under the cursor" },
|
{ on = [ "<Delete>" ], run = "backspace --under", desc = "Delete the character under the cursor" },
|
||||||
{ on = [ "<C-h>" ], exec = "backspace", desc = "Delete the character before the cursor" },
|
{ on = [ "<C-h>" ], run = "backspace", desc = "Delete the character before the cursor" },
|
||||||
{ on = [ "<C-d>" ], exec = "backspace --under", desc = "Delete the character under the cursor" },
|
{ on = [ "<C-d>" ], run = "backspace --under", desc = "Delete the character under the cursor" },
|
||||||
|
|
||||||
# Kill
|
# Kill
|
||||||
{ on = [ "<C-u>" ], exec = "kill bol", desc = "Kill backwards to the BOL" },
|
{ on = [ "<C-u>" ], run = "kill bol", desc = "Kill backwards to the BOL" },
|
||||||
{ on = [ "<C-k>" ], exec = "kill eol", desc = "Kill forwards to the EOL" },
|
{ on = [ "<C-k>" ], run = "kill eol", desc = "Kill forwards to the EOL" },
|
||||||
{ on = [ "<C-w>" ], exec = "kill backward", desc = "Kill backwards to the start of the current word" },
|
{ on = [ "<C-w>" ], run = "kill backward", desc = "Kill backwards to the start of the current word" },
|
||||||
{ on = [ "<A-d>" ], exec = "kill forward", desc = "Kill forwards to the end of the current word" },
|
{ on = [ "<A-d>" ], run = "kill forward", desc = "Kill forwards to the end of the current word" },
|
||||||
|
|
||||||
# Cut/Yank/Paste
|
# Cut/Yank/Paste
|
||||||
{ on = [ "d" ], exec = "delete --cut", desc = "Cut the selected characters" },
|
{ on = [ "d" ], run = "delete --cut", desc = "Cut the selected characters" },
|
||||||
{ on = [ "D" ], exec = [ "delete --cut", "move 999" ], desc = "Cut until the EOL" },
|
{ on = [ "D" ], run = [ "delete --cut", "move 999" ], desc = "Cut until the EOL" },
|
||||||
{ on = [ "c" ], exec = "delete --cut --insert", desc = "Cut the selected characters, and enter insert mode" },
|
{ on = [ "c" ], run = "delete --cut --insert", desc = "Cut the selected characters, and enter insert mode" },
|
||||||
{ on = [ "C" ], exec = [ "delete --cut --insert", "move 999" ], desc = "Cut until the EOL, and enter insert mode" },
|
{ on = [ "C" ], run = [ "delete --cut --insert", "move 999" ], desc = "Cut until the EOL, and enter insert mode" },
|
||||||
{ on = [ "x" ], exec = [ "delete --cut", "move 1 --in-operating" ], desc = "Cut the current character" },
|
{ on = [ "x" ], run = [ "delete --cut", "move 1 --in-operating" ], desc = "Cut the current character" },
|
||||||
{ on = [ "y" ], exec = "yank", desc = "Copy the selected characters" },
|
{ on = [ "y" ], run = "yank", desc = "Copy the selected characters" },
|
||||||
{ on = [ "p" ], exec = "paste", desc = "Paste the copied characters after the cursor" },
|
{ on = [ "p" ], run = "paste", desc = "Paste the copied characters after the cursor" },
|
||||||
{ on = [ "P" ], exec = "paste --before", desc = "Paste the copied characters before the cursor" },
|
{ on = [ "P" ], run = "paste --before", desc = "Paste the copied characters before the cursor" },
|
||||||
|
|
||||||
# Undo/Redo
|
# Undo/Redo
|
||||||
{ on = [ "u" ], exec = "undo", desc = "Undo the last operation" },
|
{ on = [ "u" ], run = "undo", desc = "Undo the last operation" },
|
||||||
{ on = [ "<C-r>" ], exec = "redo", desc = "Redo the last operation" },
|
{ on = [ "<C-r>" ], run = "redo", desc = "Redo the last operation" },
|
||||||
|
|
||||||
# Help
|
# Help
|
||||||
{ on = [ "~" ], exec = "help", desc = "Open help" }
|
{ on = [ "~" ], run = "help", desc = "Open help" }
|
||||||
]
|
]
|
||||||
|
|
||||||
[completion]
|
[completion]
|
||||||
|
|
||||||
keymap = [
|
keymap = [
|
||||||
{ on = [ "<C-q>" ], exec = "close", desc = "Cancel completion" },
|
{ on = [ "<C-q>" ], run = "close", desc = "Cancel completion" },
|
||||||
{ on = [ "<Tab>" ], exec = "close --submit", desc = "Submit the completion" },
|
{ on = [ "<Tab>" ], run = "close --submit", desc = "Submit the completion" },
|
||||||
{ on = [ "<Enter>" ], exec = [ "close --submit", "close_input --submit" ], desc = "Submit the completion and input" },
|
{ on = [ "<Enter>" ], run = [ "close --submit", "close_input --submit" ], desc = "Submit the completion and input" },
|
||||||
|
|
||||||
{ on = [ "<A-k>" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "<A-k>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "<A-j>" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "<A-j>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
||||||
{ on = [ "<Up>" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "<Up>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "<Down>" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "<Down>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
||||||
{ on = [ "~" ], exec = "help", desc = "Open help" }
|
{ on = [ "~" ], run = "help", desc = "Open help" }
|
||||||
]
|
]
|
||||||
|
|
||||||
[help]
|
[help]
|
||||||
|
|
||||||
keymap = [
|
keymap = [
|
||||||
{ on = [ "<Esc>" ], exec = "escape", desc = "Clear the filter, or hide the help" },
|
{ on = [ "<Esc>" ], run = "escape", desc = "Clear the filter, or hide the help" },
|
||||||
{ on = [ "q" ], exec = "close", desc = "Exit the process" },
|
{ on = [ "<C-[>" ], run = "escape", desc = "Clear the filter, or hide the help" },
|
||||||
{ on = [ "<C-q>" ], exec = "close", desc = "Hide the help" },
|
{ on = [ "q" ], run = "close", desc = "Exit the process" },
|
||||||
|
{ on = [ "<C-q>" ], run = "close", desc = "Hide the help" },
|
||||||
|
|
||||||
# Navigation
|
# Navigation
|
||||||
{ on = [ "k" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "k" ], run = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "j" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "j" ], run = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
||||||
{ on = [ "K" ], exec = "arrow -5", desc = "Move cursor up 5 lines" },
|
{ on = [ "K" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||||
{ on = [ "J" ], exec = "arrow 5", desc = "Move cursor down 5 lines" },
|
{ on = [ "J" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||||
|
|
||||||
{ on = [ "<Up>" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "<Up>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "<Down>" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "<Down>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
||||||
{ on = [ "<S-Up>" ], exec = "arrow -5", desc = "Move cursor up 5 lines" },
|
{ on = [ "<S-Up>" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||||
{ on = [ "<S-Down>" ], exec = "arrow 5", desc = "Move cursor down 5 lines" },
|
{ on = [ "<S-Down>" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||||
|
|
||||||
# Filtering
|
# Filtering
|
||||||
{ on = [ "/" ], exec = "filter", desc = "Apply a filter for the help items" },
|
{ on = [ "/" ], run = "filter", desc = "Apply a filter for the help items" },
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,13 @@
|
||||||
|
|
||||||
# vim:fileencoding=utf-8:foldmethod=marker
|
# vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
# : Flavor {{{
|
||||||
|
|
||||||
|
[flavor]
|
||||||
|
use = ""
|
||||||
|
|
||||||
|
# : }}}
|
||||||
|
|
||||||
# : Manager {{{
|
# : Manager {{{
|
||||||
|
|
||||||
[manager]
|
[manager]
|
||||||
|
|
@ -137,7 +144,7 @@ separator_style = { fg = "darkgray" }
|
||||||
|
|
||||||
[help]
|
[help]
|
||||||
on = { fg = "magenta" }
|
on = { fg = "magenta" }
|
||||||
exec = { fg = "cyan" }
|
run = { fg = "cyan" }
|
||||||
desc = { fg = "gray" }
|
desc = { fg = "gray" }
|
||||||
hovered = { bg = "darkgray", bold = true }
|
hovered = { bg = "darkgray", bold = true }
|
||||||
footer = { fg = "black", bg = "white" }
|
footer = { fg = "black", bg = "white" }
|
||||||
|
|
@ -145,6 +152,21 @@ footer = { fg = "black", bg = "white" }
|
||||||
# : }}}
|
# : }}}
|
||||||
|
|
||||||
|
|
||||||
|
# : Notify {{{
|
||||||
|
|
||||||
|
[notify]
|
||||||
|
title_info = { fg = "green" }
|
||||||
|
title_warn = { fg = "yellow" }
|
||||||
|
title_error = { fg = "red" }
|
||||||
|
|
||||||
|
# Icons
|
||||||
|
icon_info = ""
|
||||||
|
icon_warn = ""
|
||||||
|
icon_error = ""
|
||||||
|
|
||||||
|
# : }}}
|
||||||
|
|
||||||
|
|
||||||
# : File-specific styles {{{
|
# : File-specific styles {{{
|
||||||
|
|
||||||
[filetype]
|
[filetype]
|
||||||
|
|
|
||||||
|
|
@ -26,27 +26,28 @@ ueberzug_offset = [ 0, 0, 0, 0 ]
|
||||||
|
|
||||||
[opener]
|
[opener]
|
||||||
edit = [
|
edit = [
|
||||||
{ exec = '${EDITOR:=vi} "$@"', desc = "$EDITOR", block = true, for = "unix" },
|
{ run = '${EDITOR:=vi} "$@"', desc = "$EDITOR", block = true, for = "unix" },
|
||||||
{ exec = 'code "%*"', orphan = true, for = "windows" },
|
{ run = 'code "%*"', orphan = true, desc = "code", for = "windows" },
|
||||||
|
{ run = 'code -w "%*"', block = true, desc = "code (block)", for = "windows" },
|
||||||
]
|
]
|
||||||
open = [
|
open = [
|
||||||
{ exec = 'xdg-open "$@"', desc = "Open", for = "linux" },
|
{ run = 'xdg-open "$@"', desc = "Open", for = "linux" },
|
||||||
{ exec = 'open "$@"', desc = "Open", for = "macos" },
|
{ run = 'open "$@"', desc = "Open", for = "macos" },
|
||||||
{ exec = 'start "" "%1"', orphan = true, desc = "Open", for = "windows" }
|
{ run = 'start "" "%1"', orphan = true, desc = "Open", for = "windows" },
|
||||||
]
|
]
|
||||||
reveal = [
|
reveal = [
|
||||||
{ exec = 'open -R "$1"', desc = "Reveal", for = "macos" },
|
{ run = 'open -R "$1"', desc = "Reveal", for = "macos" },
|
||||||
{ exec = 'explorer /select, "%1"', orphan = true, desc = "Reveal", for = "windows" },
|
{ run = 'explorer /select, "%1"', orphan = true, desc = "Reveal", for = "windows" },
|
||||||
{ exec = '''exiftool "$1"; echo "Press enter to exit"; read''', block = true, desc = "Show EXIF", for = "unix" },
|
{ run = '''exiftool "$1"; echo "Press enter to exit"; read _''', block = true, desc = "Show EXIF", for = "unix" },
|
||||||
]
|
]
|
||||||
extract = [
|
extract = [
|
||||||
{ exec = 'unar "$1"', desc = "Extract here", for = "unix" },
|
{ run = 'unar "$1"', desc = "Extract here", for = "unix" },
|
||||||
{ exec = 'unar "%1"', desc = "Extract here", for = "windows" },
|
{ run = 'unar "%1"', desc = "Extract here", for = "windows" },
|
||||||
]
|
]
|
||||||
play = [
|
play = [
|
||||||
{ exec = 'mpv "$@"', orphan = true, for = "unix" },
|
{ run = 'mpv "$@"', orphan = true, for = "unix" },
|
||||||
{ exec = 'mpv "%1"', orphan = true, for = "windows" },
|
{ run = 'mpv "%1"', orphan = true, for = "windows" },
|
||||||
{ exec = '''mediainfo "$1"; echo "Press enter to exit"; read''', block = true, desc = "Show media info", for = "unix" },
|
{ run = '''mediainfo "$1"; echo "Press enter to exit"; read _''', block = true, desc = "Show media info", for = "unix" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[open]
|
[open]
|
||||||
|
|
@ -85,42 +86,42 @@ suppress_preload = false
|
||||||
[plugin]
|
[plugin]
|
||||||
|
|
||||||
preloaders = [
|
preloaders = [
|
||||||
{ name = "*", cond = "!mime", exec = "mime", multi = true, prio = "high" },
|
{ name = "*", cond = "!mime", run = "mime", multi = true, prio = "high" },
|
||||||
# Image
|
# Image
|
||||||
{ mime = "image/vnd.djvu", exec = "noop" },
|
{ mime = "image/vnd.djvu", run = "noop" },
|
||||||
{ mime = "image/*", exec = "image" },
|
{ mime = "image/*", run = "image" },
|
||||||
# Video
|
# Video
|
||||||
{ mime = "video/*", exec = "video" },
|
{ mime = "video/*", run = "video" },
|
||||||
# PDF
|
# PDF
|
||||||
{ mime = "application/pdf", exec = "pdf" },
|
{ mime = "application/pdf", run = "pdf" },
|
||||||
]
|
]
|
||||||
previewers = [
|
previewers = [
|
||||||
{ name = "*/", exec = "folder", sync = true },
|
{ name = "*/", run = "folder", sync = true },
|
||||||
# Code
|
# Code
|
||||||
{ mime = "text/*", exec = "code" },
|
{ mime = "text/*", run = "code" },
|
||||||
{ mime = "*/xml", exec = "code" },
|
{ mime = "*/xml", run = "code" },
|
||||||
{ mime = "*/javascript", exec = "code" },
|
{ mime = "*/javascript", run = "code" },
|
||||||
{ mime = "*/x-wine-extension-ini", exec = "code" },
|
{ mime = "*/x-wine-extension-ini", run = "code" },
|
||||||
# JSON
|
# JSON
|
||||||
{ mime = "application/json", exec = "json" },
|
{ mime = "application/json", run = "json" },
|
||||||
# Image
|
# Image
|
||||||
{ mime = "image/vnd.djvu", exec = "noop" },
|
{ mime = "image/vnd.djvu", run = "noop" },
|
||||||
{ mime = "image/*", exec = "image" },
|
{ mime = "image/*", run = "image" },
|
||||||
# Video
|
# Video
|
||||||
{ mime = "video/*", exec = "video" },
|
{ mime = "video/*", run = "video" },
|
||||||
# PDF
|
# PDF
|
||||||
{ mime = "application/pdf", exec = "pdf" },
|
{ mime = "application/pdf", run = "pdf" },
|
||||||
# Archive
|
# Archive
|
||||||
{ mime = "application/zip", exec = "archive" },
|
{ mime = "application/zip", run = "archive" },
|
||||||
{ mime = "application/gzip", exec = "archive" },
|
{ mime = "application/gzip", run = "archive" },
|
||||||
{ mime = "application/x-tar", exec = "archive" },
|
{ mime = "application/x-tar", run = "archive" },
|
||||||
{ mime = "application/x-bzip", exec = "archive" },
|
{ mime = "application/x-bzip", run = "archive" },
|
||||||
{ mime = "application/x-bzip2", exec = "archive" },
|
{ mime = "application/x-bzip2", run = "archive" },
|
||||||
{ mime = "application/x-7z-compressed", exec = "archive" },
|
{ mime = "application/x-7z-compressed", run = "archive" },
|
||||||
{ mime = "application/x-rar", exec = "archive" },
|
{ mime = "application/x-rar", run = "archive" },
|
||||||
{ mime = "application/xz", exec = "archive" },
|
{ mime = "application/xz", run = "archive" },
|
||||||
# Fallback
|
# Fallback
|
||||||
{ name = "*", exec = "file" },
|
{ name = "*", run = "file" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,21 @@
|
||||||
use std::{borrow::Cow, collections::VecDeque, ops::Deref};
|
use std::{borrow::Cow, collections::VecDeque};
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Deserializer};
|
||||||
use yazi_shared::event::Cmd;
|
use yazi_shared::event::Cmd;
|
||||||
|
|
||||||
use super::Key;
|
use super::Key;
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Control {
|
pub struct Control {
|
||||||
pub on: Vec<Key>,
|
pub on: Vec<Key>,
|
||||||
#[serde(deserialize_with = "super::exec_deserialize")]
|
pub run: Vec<Cmd>,
|
||||||
pub exec: Vec<Cmd>,
|
|
||||||
pub desc: Option<String>,
|
pub desc: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Control {
|
impl Control {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_seq(&self) -> VecDeque<Cmd> {
|
pub fn to_seq(&self) -> VecDeque<Cmd> {
|
||||||
self.exec.iter().map(|e| e.clone_without_data()).collect()
|
self.run.iter().map(|e| e.clone_without_data()).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,58 +24,47 @@ impl Control {
|
||||||
pub fn on(&self) -> String { self.on.iter().map(ToString::to_string).collect() }
|
pub fn on(&self) -> String { self.on.iter().map(ToString::to_string).collect() }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn exec(&self) -> String {
|
pub fn run(&self) -> String {
|
||||||
self.exec.iter().map(|e| e.to_string()).collect::<Vec<_>>().join("; ")
|
self.run.iter().map(|e| e.to_string()).collect::<Vec<_>>().join("; ")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn desc_or_exec(&self) -> Cow<str> {
|
pub fn desc_or_run(&self) -> Cow<str> {
|
||||||
if let Some(ref s) = self.desc { Cow::Borrowed(s) } else { self.exec().into() }
|
if let Some(ref s) = self.desc { Cow::Borrowed(s) } else { self.run().into() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn contains(&self, s: &str) -> bool {
|
pub fn contains(&self, s: &str) -> bool {
|
||||||
let s = s.to_lowercase();
|
let s = s.to_lowercase();
|
||||||
self.desc.as_ref().map(|d| d.to_lowercase().contains(&s)) == Some(true)
|
self.desc.as_ref().map(|d| d.to_lowercase().contains(&s)) == Some(true)
|
||||||
|| self.exec().to_lowercase().contains(&s)
|
|| self.run().to_lowercase().contains(&s)
|
||||||
|| self.on().to_lowercase().contains(&s)
|
|| self.on().to_lowercase().contains(&s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
// TODO: remove this once Yazi 0.3 is released
|
||||||
pub enum ControlCow {
|
impl<'de> Deserialize<'de> for Control {
|
||||||
Owned(Control),
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
Borrowed(&'static Control),
|
where
|
||||||
}
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
impl From<&'static Control> for ControlCow {
|
#[derive(Deserialize)]
|
||||||
fn from(c: &'static Control) -> Self { Self::Borrowed(c) }
|
pub struct Shadow {
|
||||||
}
|
pub on: Vec<Key>,
|
||||||
|
pub run: Option<VecCmd>,
|
||||||
impl From<Control> for ControlCow {
|
pub exec: Option<VecCmd>,
|
||||||
fn from(c: Control) -> Self { Self::Owned(c) }
|
pub desc: Option<String>,
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for ControlCow {
|
|
||||||
type Target = Control;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
match self {
|
|
||||||
Self::Owned(c) => c,
|
|
||||||
Self::Borrowed(c) => c,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ControlCow {
|
|
||||||
fn default() -> Self { Self::Owned(Control::default()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ControlCow {
|
|
||||||
pub fn into_seq(self) -> VecDeque<Cmd> {
|
|
||||||
match self {
|
|
||||||
Self::Owned(c) => c.exec.into(),
|
|
||||||
Self::Borrowed(c) => c.to_seq(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let shadow = Shadow::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct VecCmd(#[serde(deserialize_with = "super::run_deserialize")] Vec<Cmd>);
|
||||||
|
|
||||||
|
let Some(run) = shadow.run.or(shadow.exec) else {
|
||||||
|
return Err(serde::de::Error::custom("missing field `run` within `[keymap]`"));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self { on: shadow.on, run: run.0, desc: shadow.desc })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
43
yazi-config/src/keymap/cow.rs
Normal file
43
yazi-config/src/keymap/cow.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
use std::{collections::VecDeque, ops::Deref};
|
||||||
|
|
||||||
|
use yazi_shared::event::Cmd;
|
||||||
|
|
||||||
|
use super::Control;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ControlCow {
|
||||||
|
Owned(Control),
|
||||||
|
Borrowed(&'static Control),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&'static Control> for ControlCow {
|
||||||
|
fn from(c: &'static Control) -> Self { Self::Borrowed(c) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Control> for ControlCow {
|
||||||
|
fn from(c: Control) -> Self { Self::Owned(c) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for ControlCow {
|
||||||
|
type Target = Control;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
match self {
|
||||||
|
Self::Owned(c) => c,
|
||||||
|
Self::Borrowed(c) => c,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ControlCow {
|
||||||
|
fn default() -> Self { Self::Owned(Control::default()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ControlCow {
|
||||||
|
pub fn into_seq(self) -> VecDeque<Cmd> {
|
||||||
|
match self {
|
||||||
|
Self::Owned(c) => c.run.into(),
|
||||||
|
Self::Borrowed(c) => c.to_seq(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::str::FromStr;
|
use std::{fmt::{Display, Write}, str::FromStr};
|
||||||
|
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||||
|
|
@ -132,22 +132,22 @@ impl TryFrom<String> for Key {
|
||||||
fn try_from(s: String) -> Result<Self, Self::Error> { Self::from_str(&s) }
|
fn try_from(s: String) -> Result<Self, Self::Error> { Self::from_str(&s) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for Key {
|
impl Display for Key {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
if let Some(c) = self.plain() {
|
if let Some(c) = self.plain() {
|
||||||
let c = if self.shift { c.to_ascii_uppercase() } else { c };
|
let c = if self.shift { c.to_ascii_uppercase() } else { c };
|
||||||
return if c == ' ' { "<Space>".to_string() } else { c.to_string() };
|
return if c == ' ' { write!(f, "<Space>") } else { f.write_char(c) };
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut s = "<".to_string();
|
write!(f, "<")?;
|
||||||
if self.ctrl {
|
if self.ctrl {
|
||||||
s += "C-";
|
write!(f, "C-")?;
|
||||||
}
|
}
|
||||||
if self.alt {
|
if self.alt {
|
||||||
s += "A-";
|
write!(f, "A-")?;
|
||||||
}
|
}
|
||||||
if self.shift && !matches!(self.code, KeyCode::Char(_)) {
|
if self.shift && !matches!(self.code, KeyCode::Char(_)) {
|
||||||
s += "S-";
|
write!(f, "S-")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let code = match self.code {
|
let code = match self.code {
|
||||||
|
|
@ -181,12 +181,12 @@ impl ToString for Key {
|
||||||
|
|
||||||
KeyCode::Char(' ') => "Space",
|
KeyCode::Char(' ') => "Space",
|
||||||
KeyCode::Char(c) => {
|
KeyCode::Char(c) => {
|
||||||
s.push(if self.shift { c.to_ascii_uppercase() } else { c });
|
f.write_char(if self.shift { c.to_ascii_uppercase() } else { c })?;
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
_ => "Unknown",
|
_ => "Unknown",
|
||||||
};
|
};
|
||||||
|
|
||||||
s + code + ">"
|
write!(f, "{}>", code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
mod control;
|
mod control;
|
||||||
mod exec;
|
mod cow;
|
||||||
mod key;
|
mod key;
|
||||||
mod keymap;
|
mod keymap;
|
||||||
|
mod run;
|
||||||
|
|
||||||
pub use control::*;
|
pub use control::*;
|
||||||
#[allow(unused_imports)]
|
pub use cow::*;
|
||||||
pub use exec::*;
|
|
||||||
pub use key::*;
|
pub use key::*;
|
||||||
pub use keymap::*;
|
pub use keymap::*;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
pub use run::*;
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@ use anyhow::{bail, Result};
|
||||||
use serde::{de::{self, Visitor}, Deserializer};
|
use serde::{de::{self, Visitor}, Deserializer};
|
||||||
use yazi_shared::event::Cmd;
|
use yazi_shared::event::Cmd;
|
||||||
|
|
||||||
pub(super) fn exec_deserialize<'de, D>(deserializer: D) -> Result<Vec<Cmd>, D::Error>
|
pub(super) fn run_deserialize<'de, D>(deserializer: D) -> Result<Vec<Cmd>, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
struct ExecVisitor;
|
struct RunVisitor;
|
||||||
|
|
||||||
fn parse(s: &str) -> Result<Cmd> {
|
fn parse(s: &str) -> Result<Cmd> {
|
||||||
let s = shell_words::split(s)?;
|
let s = shell_words::split(s)?;
|
||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
bail!("`exec` cannot be empty");
|
bail!("`run` cannot be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cmd = Cmd { name: s[0].clone(), ..Default::default() };
|
let mut cmd = Cmd { name: s[0].clone(), ..Default::default() };
|
||||||
|
|
@ -30,11 +30,11 @@ where
|
||||||
Ok(cmd)
|
Ok(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for ExecVisitor {
|
impl<'de> Visitor<'de> for RunVisitor {
|
||||||
type Value = Vec<Cmd>;
|
type Value = Vec<Cmd>;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
formatter.write_str("a `exec` string or array of strings within [keymap]")
|
formatter.write_str("a `run` string or array of strings within keymap.toml")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||||
|
|
@ -46,7 +46,7 @@ where
|
||||||
cmds.push(parse(value).map_err(de::Error::custom)?);
|
cmds.push(parse(value).map_err(de::Error::custom)?);
|
||||||
}
|
}
|
||||||
if cmds.is_empty() {
|
if cmds.is_empty() {
|
||||||
return Err(de::Error::custom("`exec` within [keymap] cannot be empty"));
|
return Err(de::Error::custom("`run` within keymap.toml cannot be empty"));
|
||||||
}
|
}
|
||||||
Ok(cmds)
|
Ok(cmds)
|
||||||
}
|
}
|
||||||
|
|
@ -59,5 +59,5 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.deserialize_any(ExecVisitor)
|
deserializer.deserialize_any(RunVisitor)
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(clippy::module_inception)]
|
#![allow(clippy::module_inception)]
|
||||||
|
|
||||||
use yazi_shared::RoCell;
|
use yazi_shared::{RoCell, Xdg};
|
||||||
|
|
||||||
pub mod keymap;
|
pub mod keymap;
|
||||||
mod layout;
|
mod layout;
|
||||||
|
|
@ -23,11 +23,11 @@ pub(crate) use pattern::*;
|
||||||
pub(crate) use preset::*;
|
pub(crate) use preset::*;
|
||||||
pub use priority::*;
|
pub use priority::*;
|
||||||
|
|
||||||
pub static LAYOUT: RoCell<arc_swap::ArcSwap<Layout>> = RoCell::new();
|
static MERGED_YAZI: RoCell<String> = RoCell::new();
|
||||||
|
|
||||||
static MERGED_KEYMAP: RoCell<String> = RoCell::new();
|
static MERGED_KEYMAP: RoCell<String> = RoCell::new();
|
||||||
static MERGED_THEME: RoCell<String> = RoCell::new();
|
static MERGED_THEME: RoCell<String> = RoCell::new();
|
||||||
static MERGED_YAZI: RoCell<String> = RoCell::new();
|
|
||||||
|
pub static LAYOUT: RoCell<arc_swap::ArcSwap<Layout>> = RoCell::new();
|
||||||
|
|
||||||
pub static KEYMAP: RoCell<keymap::Keymap> = RoCell::new();
|
pub static KEYMAP: RoCell<keymap::Keymap> = RoCell::new();
|
||||||
pub static LOG: RoCell<log::Log> = RoCell::new();
|
pub static LOG: RoCell<log::Log> = RoCell::new();
|
||||||
|
|
@ -42,12 +42,12 @@ pub static SELECT: RoCell<popup::Select> = RoCell::new();
|
||||||
pub static WHICH: RoCell<which::Which> = RoCell::new();
|
pub static WHICH: RoCell<which::Which> = RoCell::new();
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
LAYOUT.with(Default::default);
|
let config_dir = Xdg::config_dir();
|
||||||
|
MERGED_YAZI.init(Preset::yazi(&config_dir));
|
||||||
let config_dir = yazi_shared::Xdg::config_dir().unwrap();
|
|
||||||
MERGED_KEYMAP.init(Preset::keymap(&config_dir));
|
MERGED_KEYMAP.init(Preset::keymap(&config_dir));
|
||||||
MERGED_THEME.init(Preset::theme(&config_dir));
|
MERGED_THEME.init(Preset::theme(&config_dir));
|
||||||
MERGED_YAZI.init(Preset::yazi(&config_dir));
|
|
||||||
|
LAYOUT.with(Default::default);
|
||||||
|
|
||||||
KEYMAP.with(Default::default);
|
KEYMAP.with(Default::default);
|
||||||
LOG.with(Default::default);
|
LOG.with(Default::default);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::str::FromStr;
|
use std::{fmt::Display, str::FromStr};
|
||||||
|
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -39,9 +39,9 @@ impl TryFrom<String> for SortBy {
|
||||||
fn try_from(s: String) -> Result<Self, Self::Error> { Self::from_str(&s) }
|
fn try_from(s: String) -> Result<Self, Self::Error> { Self::from_str(&s) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for SortBy {
|
impl Display for SortBy {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
f.write_str(match self {
|
||||||
Self::None => "none",
|
Self::None => "none",
|
||||||
Self::Modified => "modified",
|
Self::Modified => "modified",
|
||||||
Self::Created => "created",
|
Self::Created => "created",
|
||||||
|
|
@ -49,7 +49,6 @@ impl ToString for SortBy {
|
||||||
Self::Alphabetical => "alphabetical",
|
Self::Alphabetical => "alphabetical",
|
||||||
Self::Natural => "natural",
|
Self::Natural => "natural",
|
||||||
Self::Size => "size",
|
Self::Size => "size",
|
||||||
}
|
})
|
||||||
.to_string()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Deserializer};
|
||||||
use yazi_shared::MIME_DIR;
|
use yazi_shared::MIME_DIR;
|
||||||
|
|
||||||
use super::Opener;
|
use super::Opener;
|
||||||
use crate::{open::OpenRule, MERGED_YAZI};
|
use crate::{open::OpenRule, Preset, MERGED_YAZI};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Open {
|
pub struct Open {
|
||||||
|
|
@ -70,15 +70,22 @@ impl<'de> Deserialize<'de> for Open {
|
||||||
}
|
}
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct OuterOpen {
|
struct OuterOpen {
|
||||||
rules: Vec<OpenRule>,
|
rules: Vec<OpenRule>,
|
||||||
|
#[serde(default)]
|
||||||
|
prepend_rules: Vec<OpenRule>,
|
||||||
|
#[serde(default)]
|
||||||
|
append_rules: Vec<OpenRule>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let outer = Outer::deserialize(deserializer)?;
|
let mut outer = Outer::deserialize(deserializer)?;
|
||||||
|
Preset::mix(&mut outer.open.rules, outer.open.prepend_rules, outer.open.append_rules);
|
||||||
|
|
||||||
let openers = outer
|
let openers = outer
|
||||||
.opener
|
.opener
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(k, v)| (k, v.into_iter().filter_map(|o| o.take()).collect::<IndexSet<_>>()))
|
.map(|(k, v)| (k, v.into_iter().filter_map(|o| o.take()).collect::<IndexSet<_>>()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Self { rules: outer.open.rules, openers })
|
Ok(Self { rules: outer.open.rules, openers })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use serde::{Deserialize, Deserializer};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Opener {
|
pub struct Opener {
|
||||||
pub exec: String,
|
pub run: String,
|
||||||
pub block: bool,
|
pub block: bool,
|
||||||
pub orphan: bool,
|
pub orphan: bool,
|
||||||
pub desc: String,
|
pub desc: String,
|
||||||
|
|
@ -32,7 +32,9 @@ impl<'de> Deserialize<'de> for Opener {
|
||||||
{
|
{
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Shadow {
|
pub struct Shadow {
|
||||||
exec: String,
|
run: Option<String>,
|
||||||
|
// TODO: remove this once Yazi 0.3 is released --
|
||||||
|
exec: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
block: bool,
|
block: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|
@ -43,22 +45,18 @@ impl<'de> Deserialize<'de> for Opener {
|
||||||
}
|
}
|
||||||
|
|
||||||
let shadow = Shadow::deserialize(deserializer)?;
|
let shadow = Shadow::deserialize(deserializer)?;
|
||||||
if shadow.exec.is_empty() {
|
|
||||||
return Err(serde::de::Error::custom("`exec` cannot be empty"));
|
// TODO: remove this once Yazi 0.3 is released --
|
||||||
|
let run = shadow.run.or(shadow.exec).unwrap_or_default();
|
||||||
|
// TODO: -- remove this once Yazi 0.3 is released
|
||||||
|
|
||||||
|
if run.is_empty() {
|
||||||
|
return Err(serde::de::Error::custom("`run` cannot be empty"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let desc =
|
let desc = shadow.desc.unwrap_or_else(|| run.split_whitespace().next().unwrap().to_string());
|
||||||
shadow.desc.unwrap_or_else(|| shadow.exec.split_whitespace().next().unwrap().to_string());
|
|
||||||
|
|
||||||
let spread =
|
let spread = run.contains("$@") || run.contains("%*") || run.contains("$*");
|
||||||
shadow.exec.contains("$@") || shadow.exec.contains("%*") || shadow.exec.contains("$*");
|
Ok(Self { run, block: shadow.block, orphan: shadow.orphan, desc, for_: shadow.for_, spread })
|
||||||
Ok(Self {
|
|
||||||
exec: shadow.exec,
|
|
||||||
block: shadow.block,
|
|
||||||
orphan: shadow.orphan,
|
|
||||||
desc,
|
|
||||||
for_: shadow.for_,
|
|
||||||
spread,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
mod exec;
|
|
||||||
mod plugin;
|
mod plugin;
|
||||||
mod props;
|
mod props;
|
||||||
|
mod rule;
|
||||||
|
mod run;
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
pub use exec::*;
|
|
||||||
pub use plugin::*;
|
pub use plugin::*;
|
||||||
pub use props::*;
|
pub use props::*;
|
||||||
|
pub use rule::*;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
pub use run::*;
|
||||||
|
|
||||||
pub const MAX_PRELOADERS: u8 = 32;
|
pub const MAX_PRELOADERS: u8 = 32;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use yazi_shared::{event::Cmd, Condition, MIME_DIR};
|
use yazi_shared::MIME_DIR;
|
||||||
|
|
||||||
use crate::{pattern::Pattern, plugin::MAX_PRELOADERS, Preset, Priority, MERGED_YAZI};
|
use super::PluginRule;
|
||||||
|
use crate::{plugin::MAX_PRELOADERS, Preset, MERGED_YAZI};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Plugin {
|
pub struct Plugin {
|
||||||
|
|
@ -86,29 +87,3 @@ impl Plugin {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct PluginRule {
|
|
||||||
#[serde(default)]
|
|
||||||
pub id: u8,
|
|
||||||
pub cond: Option<Condition>,
|
|
||||||
pub name: Option<Pattern>,
|
|
||||||
pub mime: Option<Pattern>,
|
|
||||||
#[serde(rename = "exec")]
|
|
||||||
#[serde(deserialize_with = "super::exec_deserialize")]
|
|
||||||
pub cmd: Cmd,
|
|
||||||
#[serde(default)]
|
|
||||||
pub sync: bool,
|
|
||||||
#[serde(default)]
|
|
||||||
pub multi: bool,
|
|
||||||
#[serde(default)]
|
|
||||||
pub prio: Priority,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PluginRule {
|
|
||||||
#[inline]
|
|
||||||
fn any_file(&self) -> bool { self.name.as_ref().is_some_and(|p| p.any_file()) }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn any_dir(&self) -> bool { self.name.as_ref().is_some_and(|p| p.any_dir()) }
|
|
||||||
}
|
|
||||||
|
|
|
||||||
68
yazi-config/src/plugin/rule.rs
Normal file
68
yazi-config/src/plugin/rule.rs
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
use serde::{Deserialize, Deserializer};
|
||||||
|
use yazi_shared::{event::Cmd, Condition};
|
||||||
|
|
||||||
|
use crate::{Pattern, Priority};
|
||||||
|
|
||||||
|
pub struct PluginRule {
|
||||||
|
pub id: u8,
|
||||||
|
pub cond: Option<Condition>,
|
||||||
|
pub name: Option<Pattern>,
|
||||||
|
pub mime: Option<Pattern>,
|
||||||
|
pub cmd: Cmd,
|
||||||
|
pub sync: bool,
|
||||||
|
pub multi: bool,
|
||||||
|
pub prio: Priority,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PluginRule {
|
||||||
|
#[inline]
|
||||||
|
pub fn any_file(&self) -> bool { self.name.as_ref().is_some_and(|p| p.any_file()) }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn any_dir(&self) -> bool { self.name.as_ref().is_some_and(|p| p.any_dir()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove this once Yazi 0.3 is released
|
||||||
|
impl<'de> Deserialize<'de> for PluginRule {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Shadow {
|
||||||
|
#[serde(default)]
|
||||||
|
pub id: u8,
|
||||||
|
pub cond: Option<Condition>,
|
||||||
|
pub name: Option<Pattern>,
|
||||||
|
pub mime: Option<Pattern>,
|
||||||
|
pub run: Option<WrappedCmd>,
|
||||||
|
pub exec: Option<WrappedCmd>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub sync: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
pub multi: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
pub prio: Priority,
|
||||||
|
}
|
||||||
|
|
||||||
|
let shadow = Shadow::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct WrappedCmd(#[serde(deserialize_with = "super::run_deserialize")] Cmd);
|
||||||
|
|
||||||
|
let Some(run) = shadow.run.or(shadow.exec) else {
|
||||||
|
return Err(serde::de::Error::custom("missing field `run` within `[plugin]`"));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
id: shadow.id,
|
||||||
|
cond: shadow.cond,
|
||||||
|
name: shadow.name,
|
||||||
|
mime: shadow.mime,
|
||||||
|
cmd: run.0,
|
||||||
|
sync: shadow.sync,
|
||||||
|
multi: shadow.multi,
|
||||||
|
prio: shadow.prio,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,24 +4,24 @@ use anyhow::Result;
|
||||||
use serde::{de::{self, Visitor}, Deserializer};
|
use serde::{de::{self, Visitor}, Deserializer};
|
||||||
use yazi_shared::event::Cmd;
|
use yazi_shared::event::Cmd;
|
||||||
|
|
||||||
pub(super) fn exec_deserialize<'de, D>(deserializer: D) -> Result<Cmd, D::Error>
|
pub(super) fn run_deserialize<'de, D>(deserializer: D) -> Result<Cmd, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
struct ExecVisitor;
|
struct RunVisitor;
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for ExecVisitor {
|
impl<'de> Visitor<'de> for RunVisitor {
|
||||||
type Value = Cmd;
|
type Value = Cmd;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
formatter.write_str("a `exec` string or array of strings")
|
formatter.write_str("a `run` string or array of strings")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_seq<A>(self, _: A) -> Result<Self::Value, A::Error>
|
fn visit_seq<A>(self, _: A) -> Result<Self::Value, A::Error>
|
||||||
where
|
where
|
||||||
A: de::SeqAccess<'de>,
|
A: de::SeqAccess<'de>,
|
||||||
{
|
{
|
||||||
Err(de::Error::custom("`exec` within [plugin] must be a string"))
|
Err(de::Error::custom("`run` within [plugin] must be a string"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||||
|
|
@ -29,11 +29,11 @@ where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
if value.is_empty() {
|
if value.is_empty() {
|
||||||
return Err(de::Error::custom("`exec` within [plugin] cannot be empty"));
|
return Err(de::Error::custom("`run` within [plugin] cannot be empty"));
|
||||||
}
|
}
|
||||||
Ok(Cmd { name: value.to_owned(), ..Default::default() })
|
Ok(Cmd { name: value.to_owned(), ..Default::default() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.deserialize_any(ExecVisitor)
|
deserializer.deserialize_any(RunVisitor)
|
||||||
}
|
}
|
||||||
|
|
@ -1,24 +1,63 @@
|
||||||
|
use std::{fmt::Display, str::FromStr};
|
||||||
|
|
||||||
|
use anyhow::bail;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Copy, Default, Deserialize, PartialEq, Eq)]
|
||||||
|
#[serde(try_from = "String")]
|
||||||
pub enum Origin {
|
pub enum Origin {
|
||||||
#[default]
|
#[default]
|
||||||
#[serde(rename = "top-left")]
|
|
||||||
TopLeft,
|
TopLeft,
|
||||||
#[serde(rename = "top-center")]
|
|
||||||
TopCenter,
|
TopCenter,
|
||||||
#[serde(rename = "top-right")]
|
|
||||||
TopRight,
|
TopRight,
|
||||||
|
|
||||||
#[serde(rename = "bottom-left")]
|
|
||||||
BottomLeft,
|
BottomLeft,
|
||||||
#[serde(rename = "bottom-center")]
|
|
||||||
BottomCenter,
|
BottomCenter,
|
||||||
#[serde(rename = "bottom-right")]
|
|
||||||
BottomRight,
|
BottomRight,
|
||||||
|
|
||||||
#[serde(rename = "center")]
|
|
||||||
Center,
|
Center,
|
||||||
#[serde(rename = "hovered")]
|
|
||||||
Hovered,
|
Hovered,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for Origin {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(match s {
|
||||||
|
"top-left" => Self::TopLeft,
|
||||||
|
"top-center" => Self::TopCenter,
|
||||||
|
"top-right" => Self::TopRight,
|
||||||
|
|
||||||
|
"bottom-left" => Self::BottomLeft,
|
||||||
|
"bottom-center" => Self::BottomCenter,
|
||||||
|
"bottom-right" => Self::BottomRight,
|
||||||
|
|
||||||
|
"center" => Self::Center,
|
||||||
|
"hovered" => Self::Hovered,
|
||||||
|
_ => bail!("Invalid `origin` value: {s}"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<String> for Origin {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: String) -> Result<Self, Self::Error> { Self::from_str(&value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Origin {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_str(match self {
|
||||||
|
Self::TopLeft => "top-left",
|
||||||
|
Self::TopCenter => "top-center",
|
||||||
|
Self::TopRight => "top-right",
|
||||||
|
|
||||||
|
Self::BottomLeft => "bottom-left",
|
||||||
|
Self::BottomCenter => "bottom-center",
|
||||||
|
Self::BottomRight => "bottom-right",
|
||||||
|
|
||||||
|
Self::Center => "center",
|
||||||
|
Self::Hovered => "hovered",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,35 @@
|
||||||
use std::{mem, path::{Path, PathBuf}};
|
use std::{mem, path::{Path, PathBuf}};
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
use toml::{Table, Value};
|
use toml::{Table, Value};
|
||||||
|
|
||||||
|
use crate::theme::Flavor;
|
||||||
|
|
||||||
pub(crate) struct Preset;
|
pub(crate) struct Preset;
|
||||||
|
|
||||||
impl Preset {
|
impl Preset {
|
||||||
#[inline]
|
pub(crate) fn yazi(p: &Path) -> String {
|
||||||
pub(crate) fn keymap(dir: &Path) -> String {
|
Self::merge_path(p.join("yazi.toml"), include_str!("../preset/yazi.toml"))
|
||||||
Self::merge_str(dir.join("keymap.toml"), include_str!("../preset/keymap.toml"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub(crate) fn keymap(p: &Path) -> String {
|
||||||
pub(crate) fn theme(dir: &Path) -> String {
|
Self::merge_path(p.join("keymap.toml"), include_str!("../preset/keymap.toml"))
|
||||||
Self::merge_str(dir.join("theme.toml"), include_str!("../preset/theme.toml"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub(crate) fn theme(p: &Path) -> String {
|
||||||
pub(crate) fn yazi(dir: &Path) -> String {
|
let Ok(user) = std::fs::read_to_string(p.join("theme.toml")) else {
|
||||||
Self::merge_str(dir.join("yazi.toml"), include_str!("../preset/yazi.toml"))
|
return include_str!("../preset/theme.toml").to_owned();
|
||||||
|
};
|
||||||
|
let Some(use_) = Flavor::parse_use(&user) else {
|
||||||
|
return Self::merge_str(&user, include_str!("../preset/theme.toml"));
|
||||||
|
};
|
||||||
|
|
||||||
|
let p = p.join(format!("flavors/{}.yazi/flavor.toml", use_));
|
||||||
|
let flavor = std::fs::read_to_string(&p)
|
||||||
|
.with_context(|| format!("Failed to load flavor {:?}", p))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Self::merge_str(&user, &Self::merge_str(&flavor, include_str!("../preset/theme.toml")))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -25,6 +37,24 @@ impl Preset {
|
||||||
*a = b.into_iter().chain(mem::take(a)).chain(c).collect();
|
*a = b.into_iter().chain(mem::take(a)).chain(c).collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn merge_str(user: &str, base: &str) -> String {
|
||||||
|
let mut t = user.parse().unwrap();
|
||||||
|
Self::merge(&mut t, base.parse().unwrap(), 2);
|
||||||
|
|
||||||
|
t.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn merge_path(user: PathBuf, base: &str) -> String {
|
||||||
|
let s = std::fs::read_to_string(user).unwrap_or_default();
|
||||||
|
if s.is_empty() {
|
||||||
|
return base.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::merge_str(&s, base)
|
||||||
|
}
|
||||||
|
|
||||||
fn merge(a: &mut Table, b: Table, max: u8) {
|
fn merge(a: &mut Table, b: Table, max: u8) {
|
||||||
for (k, v) in b {
|
for (k, v) in b {
|
||||||
let Some(a) = a.get_mut(&k) else {
|
let Some(a) = a.get_mut(&k) else {
|
||||||
|
|
@ -45,12 +75,4 @@ impl Preset {
|
||||||
*a = v;
|
*a = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_str(user: PathBuf, base: &str) -> String {
|
|
||||||
let mut user = std::fs::read_to_string(user).unwrap_or_default().parse::<Table>().unwrap();
|
|
||||||
let base = base.parse::<Table>().unwrap();
|
|
||||||
|
|
||||||
Self::merge(&mut user, base, 2);
|
|
||||||
user.to_string()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ use std::{fs, path::PathBuf, time::{self, SystemTime}};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
use yazi_shared::{fs::expand_path, Xdg};
|
use yazi_shared::fs::expand_path;
|
||||||
|
|
||||||
use crate::{validation::check_validation, MERGED_YAZI};
|
use crate::{validation::check_validation, Xdg, MERGED_YAZI};
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct Preview {
|
pub struct Preview {
|
||||||
|
|
|
||||||
23
yazi-config/src/theme/flavor.rs
Normal file
23
yazi-config/src/theme/flavor.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct Flavor {
|
||||||
|
#[serde(rename = "use")]
|
||||||
|
pub use_: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Flavor {
|
||||||
|
pub fn parse_use(s: &str) -> Option<String> {
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Outer {
|
||||||
|
flavor: Inner,
|
||||||
|
}
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Inner {
|
||||||
|
#[serde(rename = "use")]
|
||||||
|
pub use_: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
toml::from_str::<Outer>(s).ok().map(|o| o.flavor.use_).filter(|s| !s.is_empty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
mod color;
|
mod color;
|
||||||
mod filetype;
|
mod filetype;
|
||||||
|
mod flavor;
|
||||||
mod icon;
|
mod icon;
|
||||||
mod is;
|
mod is;
|
||||||
mod style;
|
mod style;
|
||||||
|
|
@ -7,6 +8,7 @@ mod theme;
|
||||||
|
|
||||||
pub use color::*;
|
pub use color::*;
|
||||||
pub use filetype::*;
|
pub use filetype::*;
|
||||||
|
pub use flavor::*;
|
||||||
pub use icon::*;
|
pub use icon::*;
|
||||||
pub use is::*;
|
pub use is::*;
|
||||||
pub use style::*;
|
pub use style::*;
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,49 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
use yazi_shared::fs::expand_path;
|
use yazi_shared::{fs::expand_path, Xdg};
|
||||||
|
|
||||||
use super::{Filetype, Icon, Style};
|
use super::{Filetype, Flavor, Icon, Style};
|
||||||
use crate::{validation::check_validation, MERGED_THEME};
|
use crate::{validation::check_validation, MERGED_THEME};
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct Theme {
|
||||||
|
pub flavor: Flavor,
|
||||||
|
pub manager: Manager,
|
||||||
|
status: Status,
|
||||||
|
pub input: Input,
|
||||||
|
pub select: Select,
|
||||||
|
pub completion: Completion,
|
||||||
|
pub tasks: Tasks,
|
||||||
|
pub which: Which,
|
||||||
|
pub help: Help,
|
||||||
|
pub notify: Notify,
|
||||||
|
|
||||||
|
// File-specific styles
|
||||||
|
#[serde(rename = "filetype", deserialize_with = "Filetype::deserialize", skip_serializing)]
|
||||||
|
pub filetypes: Vec<Filetype>,
|
||||||
|
#[serde(rename = "icon", deserialize_with = "Icon::deserialize", skip_serializing)]
|
||||||
|
pub icons: Vec<Icon>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Theme {
|
||||||
|
fn default() -> Self {
|
||||||
|
let mut theme: Self = toml::from_str(&MERGED_THEME).unwrap();
|
||||||
|
|
||||||
|
check_validation(theme.manager.validate());
|
||||||
|
check_validation(theme.which.validate());
|
||||||
|
|
||||||
|
if theme.flavor.use_.is_empty() {
|
||||||
|
theme.manager.syntect_theme = expand_path(&theme.manager.syntect_theme);
|
||||||
|
} else {
|
||||||
|
theme.manager.syntect_theme =
|
||||||
|
Xdg::config_dir().join(format!("flavors/{}.yazi/tmtheme.xml", theme.flavor.use_));
|
||||||
|
}
|
||||||
|
|
||||||
|
theme
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Validate)]
|
#[derive(Deserialize, Serialize, Validate)]
|
||||||
pub struct Manager {
|
pub struct Manager {
|
||||||
cwd: Style,
|
cwd: Style,
|
||||||
|
|
@ -118,7 +156,7 @@ pub struct Which {
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Help {
|
pub struct Help {
|
||||||
pub on: Style,
|
pub on: Style,
|
||||||
pub exec: Style,
|
pub run: Style,
|
||||||
pub desc: Style,
|
pub desc: Style,
|
||||||
|
|
||||||
pub hovered: Style,
|
pub hovered: Style,
|
||||||
|
|
@ -126,32 +164,12 @@ pub struct Help {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Theme {
|
pub struct Notify {
|
||||||
pub manager: Manager,
|
pub title_info: Style,
|
||||||
status: Status,
|
pub title_warn: Style,
|
||||||
pub input: Input,
|
pub title_error: Style,
|
||||||
pub select: Select,
|
|
||||||
pub completion: Completion,
|
|
||||||
pub tasks: Tasks,
|
|
||||||
pub which: Which,
|
|
||||||
pub help: Help,
|
|
||||||
|
|
||||||
// File-specific styles
|
pub icon_info: String,
|
||||||
#[serde(rename = "filetype", deserialize_with = "Filetype::deserialize", skip_serializing)]
|
pub icon_warn: String,
|
||||||
pub filetypes: Vec<Filetype>,
|
pub icon_error: String,
|
||||||
#[serde(rename = "icon", deserialize_with = "Icon::deserialize", skip_serializing)]
|
|
||||||
pub icons: Vec<Icon>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Theme {
|
|
||||||
fn default() -> Self {
|
|
||||||
let mut theme: Self = toml::from_str(&MERGED_THEME).unwrap();
|
|
||||||
|
|
||||||
check_validation(theme.manager.validate());
|
|
||||||
check_validation(theme.which.validate());
|
|
||||||
|
|
||||||
theme.manager.syntect_theme = expand_path(&theme.manager.syntect_theme);
|
|
||||||
|
|
||||||
theme
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ impl FromStr for SortBy {
|
||||||
"none" => Self::None,
|
"none" => Self::None,
|
||||||
"key" => Self::Key,
|
"key" => Self::Key,
|
||||||
"desc" => Self::Desc,
|
"desc" => Self::Desc,
|
||||||
_ => bail!("Invalid sort option: {s}"),
|
_ => bail!("Invalid `sort_by` value: {s}"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ yazi-adaptor = { path = "../yazi-adaptor", version = "0.2.3" }
|
||||||
yazi-boot = { path = "../yazi-boot", version = "0.2.3" }
|
yazi-boot = { path = "../yazi-boot", version = "0.2.3" }
|
||||||
yazi-config = { path = "../yazi-config", version = "0.2.3" }
|
yazi-config = { path = "../yazi-config", version = "0.2.3" }
|
||||||
yazi-plugin = { path = "../yazi-plugin", version = "0.2.3" }
|
yazi-plugin = { path = "../yazi-plugin", version = "0.2.3" }
|
||||||
|
yazi-proxy = { path = "../yazi-proxy", version = "0.2.3" }
|
||||||
yazi-scheduler = { path = "../yazi-scheduler", version = "0.2.3" }
|
yazi-scheduler = { path = "../yazi-scheduler", version = "0.2.3" }
|
||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.3" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.3" }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use yazi_shared::{emit, event::Cmd, render, Layer};
|
use yazi_proxy::InputProxy;
|
||||||
|
use yazi_shared::{event::Cmd, render};
|
||||||
|
|
||||||
use crate::{completion::Completion, input::Input};
|
use crate::completion::Completion;
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
submit: bool,
|
submit: bool,
|
||||||
|
|
@ -11,16 +12,11 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completion {
|
impl Completion {
|
||||||
#[inline]
|
|
||||||
pub fn _close() {
|
|
||||||
emit!(Call(Cmd::new("close"), Layer::Completion));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close(&mut self, opt: impl Into<Opt>) {
|
pub fn close(&mut self, opt: impl Into<Opt>) {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
|
|
||||||
if let Some(s) = self.selected().filter(|_| opt.submit) {
|
if let Some(s) = self.selected().filter(|_| opt.submit) {
|
||||||
Input::_complete(s, self.ticket);
|
InputProxy::complete(s, self.ticket);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.caches.clear();
|
self.caches.clear();
|
||||||
|
|
|
||||||
|
|
@ -20,14 +20,6 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completion {
|
impl Completion {
|
||||||
#[inline]
|
|
||||||
pub fn _trigger(word: &str, ticket: usize) {
|
|
||||||
emit!(Call(
|
|
||||||
Cmd::args("trigger", vec![word.to_owned()]).with("ticket", ticket),
|
|
||||||
Layer::Completion
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn trigger(&mut self, opt: impl Into<Opt>) {
|
pub fn trigger(&mut self, opt: impl Into<Opt>) {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
if opt.ticket < self.ticket {
|
if opt.ticket < self.ticket {
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ use std::{mem, time::SystemTime};
|
||||||
|
|
||||||
use ratatui::layout::Rect;
|
use ratatui::layout::Rect;
|
||||||
use yazi_config::{LAYOUT, MANAGER};
|
use yazi_config::{LAYOUT, MANAGER};
|
||||||
|
use yazi_proxy::ManagerProxy;
|
||||||
use yazi_shared::fs::{File, FilesOp, Url};
|
use yazi_shared::fs::{File, FilesOp, Url};
|
||||||
|
|
||||||
use super::FolderStage;
|
use super::FolderStage;
|
||||||
use crate::{folder::Files, manager::Manager, Step};
|
use crate::{folder::Files, Step};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Folder {
|
pub struct Folder {
|
||||||
|
|
@ -99,7 +100,7 @@ impl Folder {
|
||||||
|
|
||||||
let new = self.cursor / limit;
|
let new = self.cursor / limit;
|
||||||
if mem::replace(&mut self.page, new) != new || force {
|
if mem::replace(&mut self.page, new) != new || force {
|
||||||
Manager::_update_paged_by(new, &self.cwd);
|
ManagerProxy::update_paged_by(new, &self.cwd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
use yazi_proxy::CompletionProxy;
|
||||||
use yazi_shared::{event::Cmd, render, InputError};
|
use yazi_shared::{event::Cmd, render, InputError};
|
||||||
|
|
||||||
use crate::{completion::Completion, input::Input};
|
use crate::input::Input;
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
submit: bool,
|
submit: bool,
|
||||||
|
|
@ -18,7 +19,7 @@ impl Input {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
|
|
||||||
if self.completion {
|
if self.completion {
|
||||||
Completion::_close();
|
CompletionProxy::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(cb) = self.callback.take() {
|
if let Some(cb) = self.callback.take() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::path::MAIN_SEPARATOR;
|
use std::path::MAIN_SEPARATOR;
|
||||||
|
|
||||||
use yazi_shared::{emit, event::Cmd, render, Layer};
|
use yazi_shared::{event::Cmd, render};
|
||||||
|
|
||||||
use crate::input::Input;
|
use crate::input::Input;
|
||||||
|
|
||||||
|
|
@ -19,11 +19,6 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
#[inline]
|
|
||||||
pub fn _complete(word: &str, ticket: usize) {
|
|
||||||
emit!(Call(Cmd::args("complete", vec![word.to_owned()]).with("ticket", ticket), Layer::Input));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn complete(&mut self, opt: impl Into<Opt>) {
|
pub fn complete(&mut self, opt: impl Into<Opt>) {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
if self.ticket != opt.ticket {
|
if self.ticket != opt.ticket {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
use yazi_proxy::CompletionProxy;
|
||||||
use yazi_shared::{event::Cmd, render};
|
use yazi_shared::{event::Cmd, render};
|
||||||
|
|
||||||
use crate::{completion::Completion, input::{op::InputOp, Input, InputMode}};
|
use crate::input::{op::InputOp, Input, InputMode};
|
||||||
|
|
||||||
pub struct Opt;
|
pub struct Opt;
|
||||||
|
|
||||||
|
|
@ -26,7 +27,7 @@ impl Input {
|
||||||
self.move_(-1);
|
self.move_(-1);
|
||||||
|
|
||||||
if self.completion {
|
if self.completion {
|
||||||
Completion::_close();
|
CompletionProxy::close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,10 @@
|
||||||
use tokio::sync::mpsc;
|
use yazi_proxy::options::InputOpt;
|
||||||
use yazi_config::popup::InputCfg;
|
use yazi_shared::render;
|
||||||
use yazi_shared::{emit, event::Cmd, render, InputError, Layer};
|
|
||||||
|
|
||||||
use crate::input::Input;
|
use crate::input::Input;
|
||||||
|
|
||||||
pub struct Opt {
|
|
||||||
cfg: InputCfg,
|
|
||||||
tx: mpsc::UnboundedSender<Result<String, InputError>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<Cmd> for Opt {
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn _show(cfg: InputCfg) -> mpsc::UnboundedReceiver<Result<String, InputError>> {
|
pub fn show(&mut self, opt: impl TryInto<InputOpt>) {
|
||||||
let (tx, rx) = mpsc::unbounded_channel();
|
|
||||||
emit!(Call(Cmd::new("show").with_data(Opt { cfg, tx }), Layer::Input));
|
|
||||||
rx
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn show(&mut self, opt: impl TryInto<Opt>) {
|
|
||||||
let Ok(opt) = opt.try_into() else {
|
let Ok(opt) = opt.try_into() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,4 @@ pub mod which;
|
||||||
pub use clipboard::*;
|
pub use clipboard::*;
|
||||||
pub use step::*;
|
pub use step::*;
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() { CLIPBOARD.with(Default::default); }
|
||||||
CLIPBOARD.with(Default::default);
|
|
||||||
|
|
||||||
yazi_scheduler::init();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
use std::path::{PathBuf, MAIN_SEPARATOR};
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
use yazi_config::popup::InputCfg;
|
use yazi_config::popup::InputCfg;
|
||||||
|
use yazi_proxy::{InputProxy, ManagerProxy};
|
||||||
use yazi_shared::{event::Cmd, fs::{File, FilesOp, Url}};
|
use yazi_shared::{event::Cmd, fs::{File, FilesOp, Url}};
|
||||||
|
|
||||||
use crate::{input::Input, manager::Manager};
|
use crate::manager::Manager;
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
force: bool,
|
force: bool,
|
||||||
|
|
@ -19,20 +20,20 @@ impl Manager {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
let cwd = self.cwd().to_owned();
|
let cwd = self.cwd().to_owned();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut result = Input::_show(InputCfg::create());
|
let mut result = InputProxy::show(InputCfg::create());
|
||||||
let Some(Ok(name)) = result.recv().await else {
|
let Some(Ok(name)) = result.recv().await else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let path = cwd.join(&name);
|
let path = cwd.join(&name);
|
||||||
if !opt.force && fs::symlink_metadata(&path).await.is_ok() {
|
if !opt.force && fs::symlink_metadata(&path).await.is_ok() {
|
||||||
match Input::_show(InputCfg::overwrite()).recv().await {
|
match InputProxy::show(InputCfg::overwrite()).recv().await {
|
||||||
Some(Ok(c)) if c == "y" || c == "Y" => (),
|
Some(Ok(c)) if c == "y" || c == "Y" => (),
|
||||||
_ => return Ok(()),
|
_ => return Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if name.ends_with(MAIN_SEPARATOR) {
|
if name.ends_with('/') || name.ends_with('\\') {
|
||||||
fs::create_dir_all(&path).await?;
|
fs::create_dir_all(&path).await?;
|
||||||
} else {
|
} else {
|
||||||
fs::create_dir_all(&path.parent().unwrap()).await.ok();
|
fs::create_dir_all(&path.parent().unwrap()).await.ok();
|
||||||
|
|
@ -43,7 +44,7 @@ impl Manager {
|
||||||
Url::from(path.components().take(cwd.components().count() + 1).collect::<PathBuf>());
|
Url::from(path.components().take(cwd.components().count() + 1).collect::<PathBuf>());
|
||||||
if let Ok(f) = File::from(child.clone()).await {
|
if let Ok(f) = File::from(child.clone()).await {
|
||||||
FilesOp::Creating(cwd, vec![f]).emit();
|
FilesOp::Creating(cwd, vec![f]).emit();
|
||||||
Manager::_hover(Some(child));
|
ManagerProxy::hover(Some(child));
|
||||||
}
|
}
|
||||||
Ok::<(), anyhow::Error>(())
|
Ok::<(), anyhow::Error>(())
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use yazi_shared::{emit, event::Cmd, fs::Url, render, Layer};
|
use yazi_shared::{event::Cmd, fs::Url, render};
|
||||||
|
|
||||||
use crate::manager::Manager;
|
use crate::manager::Manager;
|
||||||
|
|
||||||
|
|
@ -16,14 +16,6 @@ impl From<Option<Url>> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
#[inline]
|
|
||||||
pub fn _hover(url: Option<Url>) {
|
|
||||||
emit!(Call(
|
|
||||||
Cmd::args("hover", url.map_or_else(Vec::new, |u| vec![u.to_string()])),
|
|
||||||
Layer::Manager
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hover(&mut self, opt: impl Into<Opt>) {
|
pub fn hover(&mut self, opt: impl Into<Opt>) {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,19 @@ use tracing::error;
|
||||||
use yazi_boot::ARGS;
|
use yazi_boot::ARGS;
|
||||||
use yazi_config::{popup::SelectCfg, OPEN};
|
use yazi_config::{popup::SelectCfg, OPEN};
|
||||||
use yazi_plugin::isolate;
|
use yazi_plugin::isolate;
|
||||||
use yazi_shared::{emit, event::{Cmd, EventQuit}, fs::{File, Url}, Layer, MIME_DIR};
|
use yazi_proxy::{options::OpenDoOpt, ManagerProxy, TasksProxy};
|
||||||
|
use yazi_shared::{emit, event::{Cmd, EventQuit}, fs::{File, Url}, MIME_DIR};
|
||||||
|
|
||||||
use crate::{folder::Folder, manager::Manager, select::Select, tasks::Tasks};
|
use crate::{folder::Folder, manager::Manager, tasks::Tasks};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
targets: Vec<(Url, String)>,
|
|
||||||
interactive: bool,
|
interactive: bool,
|
||||||
hovered: bool,
|
hovered: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Cmd> for Opt {
|
impl From<Cmd> for Opt {
|
||||||
fn from(mut c: Cmd) -> Self {
|
fn from(c: Cmd) -> Self {
|
||||||
Self {
|
Self {
|
||||||
targets: c.take_data().unwrap_or_default(),
|
|
||||||
interactive: c.named.contains_key("interactive"),
|
interactive: c.named.contains_key("interactive"),
|
||||||
hovered: c.named.contains_key("hovered"),
|
hovered: c.named.contains_key("hovered"),
|
||||||
}
|
}
|
||||||
|
|
@ -29,23 +28,19 @@ impl Manager {
|
||||||
if !self.active_mut().try_escape_visual() {
|
if !self.active_mut().try_escape_visual() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let Some(hovered) = self.hovered().map(|h| h.url()) else {
|
||||||
let mut opt = opt.into() as Opt;
|
return;
|
||||||
let selected = if opt.hovered {
|
|
||||||
self.hovered().map(|h| vec![&h.url]).unwrap_or_default()
|
|
||||||
} else {
|
|
||||||
self.selected_or_hovered()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if selected.is_empty() {
|
let opt = opt.into() as Opt;
|
||||||
return;
|
let selected = if opt.hovered { vec![&hovered] } else { self.selected_or_hovered() };
|
||||||
} else if Self::quit_with_selected(&selected) {
|
if Self::quit_with_selected(&selected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (mut done, mut todo) = (Vec::with_capacity(selected.len()), vec![]);
|
let (mut done, mut todo) = (Vec::with_capacity(selected.len()), vec![]);
|
||||||
for u in selected {
|
for u in selected {
|
||||||
if self.mimetype.get(u).is_some() {
|
if self.mimetype.contains_key(u) {
|
||||||
done.push((u.clone(), String::new()));
|
done.push((u.clone(), String::new()));
|
||||||
} else if self.guess_folder(u) {
|
} else if self.guess_folder(u) {
|
||||||
done.push((u.clone(), MIME_DIR.to_owned()));
|
done.push((u.clone(), MIME_DIR.to_owned()));
|
||||||
|
|
@ -55,8 +50,8 @@ impl Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if todo.is_empty() {
|
if todo.is_empty() {
|
||||||
opt.targets = done;
|
return self
|
||||||
return self.open_do(opt, tasks);
|
.open_do(OpenDoOpt { hovered, targets: done, interactive: opt.interactive }, tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
|
@ -69,27 +64,15 @@ impl Manager {
|
||||||
|
|
||||||
done.extend(files.iter().map(|f| (f.url(), String::new())));
|
done.extend(files.iter().map(|f| (f.url(), String::new())));
|
||||||
if let Err(e) = isolate::preload("mime", files, true).await {
|
if let Err(e) = isolate::preload("mime", files, true).await {
|
||||||
error!("preload in watcher failed: {e}");
|
error!("preload in open failed: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::_open_do(done, opt.interactive);
|
ManagerProxy::open_do(OpenDoOpt { hovered, targets: done, interactive: opt.interactive });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub fn open_do(&mut self, opt: impl Into<OpenDoOpt>, tasks: &Tasks) {
|
||||||
pub fn _open_do(targets: Vec<(Url, String)>, interactive: bool) {
|
let opt = opt.into() as OpenDoOpt;
|
||||||
emit!(Call(
|
|
||||||
Cmd::new("open_do").with_bool("interactive", interactive).with_data(targets),
|
|
||||||
Layer::Manager
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn open_do(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if opt.targets.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let targets: Vec<_> = opt
|
let targets: Vec<_> = opt
|
||||||
.targets
|
.targets
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
@ -101,8 +84,7 @@ impl Manager {
|
||||||
if targets.is_empty() {
|
if targets.is_empty() {
|
||||||
return;
|
return;
|
||||||
} else if !opt.interactive {
|
} else if !opt.interactive {
|
||||||
tasks.file_open(&targets);
|
return tasks.file_open(&opt.hovered, &targets);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let openers: Vec<_> = OPEN.common_openers(&targets).into_iter().cloned().collect();
|
let openers: Vec<_> = OPEN.common_openers(&targets).into_iter().cloned().collect();
|
||||||
|
|
@ -110,11 +92,13 @@ impl Manager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let urls = targets.into_iter().map(|(u, _)| u).collect();
|
let urls = [opt.hovered].into_iter().chain(targets.into_iter().map(|(u, _)| u)).collect();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let result = Select::_show(SelectCfg::open(openers.iter().map(|o| o.desc.clone()).collect()));
|
let result = yazi_proxy::SelectProxy::show(SelectCfg::open(
|
||||||
|
openers.iter().map(|o| o.desc.clone()).collect(),
|
||||||
|
));
|
||||||
if let Ok(choice) = result.await {
|
if let Ok(choice) = result.await {
|
||||||
Tasks::_open(urls, openers[choice].clone());
|
TasksProxy::open_with(urls, openers[choice].clone());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use yazi_shared::{emit, event::Cmd, fs::Url, render, Layer};
|
use yazi_shared::{event::Cmd, fs::Url, render};
|
||||||
|
|
||||||
use crate::manager::Manager;
|
use crate::manager::Manager;
|
||||||
|
|
||||||
|
|
@ -25,11 +25,6 @@ impl From<bool> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
#[inline]
|
|
||||||
pub fn _peek(force: bool) {
|
|
||||||
emit!(Call(Cmd::new("peek").with_bool("force", force), Layer::Manager));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn peek(&mut self, opt: impl Into<Opt>) {
|
pub fn peek(&mut self, opt: impl Into<Opt>) {
|
||||||
let Some(hovered) = self.hovered().cloned() else {
|
let Some(hovered) = self.hovered().cloned() else {
|
||||||
return render!(self.active_mut().preview.reset());
|
return render!(self.active_mut().preview.reset());
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use yazi_config::popup::InputCfg;
|
use yazi_config::popup::InputCfg;
|
||||||
|
use yazi_proxy::InputProxy;
|
||||||
use yazi_shared::{emit, event::{Cmd, EventQuit}};
|
use yazi_shared::{emit, event::{Cmd, EventQuit}};
|
||||||
|
|
||||||
use crate::{input::Input, manager::Manager, tasks::Tasks};
|
use crate::{manager::Manager, tasks::Tasks};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
|
|
@ -25,7 +26,7 @@ impl Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut result = Input::_show(InputCfg::quit(tasks));
|
let mut result = InputProxy::show(InputCfg::quit(tasks));
|
||||||
if let Some(Ok(choice)) = result.recv().await {
|
if let Some(Ok(choice)) = result.recv().await {
|
||||||
if choice == "y" || choice == "Y" {
|
if choice == "y" || choice == "Y" {
|
||||||
emit!(Quit(opt));
|
emit!(Quit(opt));
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,10 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use yazi_shared::{emit, event::Cmd, Layer};
|
use yazi_shared::event::Cmd;
|
||||||
|
|
||||||
use crate::{manager::Manager, tasks::Tasks};
|
use crate::{manager::Manager, tasks::Tasks};
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
#[inline]
|
|
||||||
pub fn _refresh() {
|
|
||||||
emit!(Call(Cmd::new("refresh"), Layer::Manager));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn refresh(&mut self, _: Cmd, tasks: &Tasks) {
|
pub fn refresh(&mut self, _: Cmd, tasks: &Tasks) {
|
||||||
env::set_current_dir(self.cwd()).ok();
|
env::set_current_dir(self.cwd()).ok();
|
||||||
env::set_var("PWD", self.cwd());
|
env::set_var("PWD", self.cwd());
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use yazi_config::popup::InputCfg;
|
use yazi_config::popup::InputCfg;
|
||||||
use yazi_shared::{emit, event::Cmd, fs::Url, Layer};
|
use yazi_proxy::{InputProxy, ManagerProxy};
|
||||||
|
use yazi_shared::{event::Cmd, fs::Url};
|
||||||
|
|
||||||
use crate::{input::Input, manager::Manager, tasks::Tasks};
|
use crate::{manager::Manager, tasks::Tasks};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
force: bool,
|
force: bool,
|
||||||
|
|
@ -33,7 +34,7 @@ impl Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut result = Input::_show(if opt.permanently {
|
let mut result = InputProxy::show(if opt.permanently {
|
||||||
InputCfg::delete(opt.targets.len())
|
InputCfg::delete(opt.targets.len())
|
||||||
} else {
|
} else {
|
||||||
InputCfg::trash(opt.targets.len())
|
InputCfg::trash(opt.targets.len())
|
||||||
|
|
@ -44,19 +45,11 @@ impl Manager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::_remove_do(opt.targets, opt.permanently);
|
ManagerProxy::remove_do(opt.targets, opt.permanently);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn _remove_do(targets: Vec<Url>, permanently: bool) {
|
|
||||||
emit!(Call(
|
|
||||||
Cmd::new("remove_do").with_bool("permanently", permanently).with_data(targets),
|
|
||||||
Layer::Manager
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_do(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
pub fn remove_do(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
for u in &opt.targets {
|
for u in &opt.targets {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
use std::{collections::BTreeMap, ffi::OsStr, io::{stdout, BufWriter, Write}, path::PathBuf};
|
use std::{collections::BTreeMap, ffi::{OsStr, OsString}, io::{stdout, BufWriter, Write}, path::PathBuf};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use tokio::{fs::{self, OpenOptions}, io::{stdin, AsyncReadExt, AsyncWriteExt}};
|
use tokio::{fs::{self, OpenOptions}, io::{stdin, AsyncReadExt, AsyncWriteExt}};
|
||||||
use yazi_config::{popup::InputCfg, OPEN, PREVIEW};
|
use yazi_config::{popup::InputCfg, OPEN, PREVIEW};
|
||||||
use yazi_plugin::external::{self, ShellOpt};
|
use yazi_plugin::external::{self, ShellOpt};
|
||||||
use yazi_scheduler::{Scheduler, BLOCKER};
|
use yazi_proxy::{AppProxy, InputProxy, ManagerProxy};
|
||||||
|
use yazi_scheduler::BLOCKER;
|
||||||
use yazi_shared::{event::Cmd, fs::{max_common_root, File, FilesOp, Url}, term::Term, Defer};
|
use yazi_shared::{event::Cmd, fs::{max_common_root, File, FilesOp, Url}, term::Term, Defer};
|
||||||
|
|
||||||
use crate::{input::Input, manager::Manager};
|
use crate::manager::Manager;
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
force: bool,
|
force: bool,
|
||||||
|
|
@ -49,7 +50,7 @@ impl Manager {
|
||||||
let file = File::from(new.clone()).await?;
|
let file = File::from(new.clone()).await?;
|
||||||
FilesOp::Deleting(file.parent().unwrap(), vec![new.clone()]).emit();
|
FilesOp::Deleting(file.parent().unwrap(), vec![new.clone()]).emit();
|
||||||
FilesOp::Upserting(file.parent().unwrap(), BTreeMap::from_iter([(old, file)])).emit();
|
FilesOp::Upserting(file.parent().unwrap(), BTreeMap::from_iter([(old, file)])).emit();
|
||||||
Ok(Self::_hover(Some(new)))
|
Ok(ManagerProxy::hover(Some(new)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename(&mut self, opt: impl Into<Opt>) {
|
pub fn rename(&mut self, opt: impl Into<Opt>) {
|
||||||
|
|
@ -77,7 +78,7 @@ impl Manager {
|
||||||
};
|
};
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut result = Input::_show(InputCfg::rename().with_value(name).with_cursor(cursor));
|
let mut result = InputProxy::show(InputCfg::rename().with_value(name).with_cursor(cursor));
|
||||||
let Some(Ok(name)) = result.recv().await else {
|
let Some(Ok(name)) = result.recv().await else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
@ -88,7 +89,7 @@ impl Manager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = Input::_show(InputCfg::overwrite());
|
let mut result = InputProxy::show(InputCfg::overwrite());
|
||||||
if let Some(Ok(choice)) = result.recv().await {
|
if let Some(Ok(choice)) = result.recv().await {
|
||||||
if choice == "y" || choice == "Y" {
|
if choice == "y" || choice == "Y" {
|
||||||
Self::rename_and_hover(hovered, Url::from(new)).await.ok();
|
Self::rename_and_hover(hovered, Url::from(new)).await.ok();
|
||||||
|
|
@ -122,14 +123,14 @@ impl Manager {
|
||||||
|
|
||||||
let _guard = BLOCKER.acquire().await.unwrap();
|
let _guard = BLOCKER.acquire().await.unwrap();
|
||||||
let _defer = Defer::new(|| {
|
let _defer = Defer::new(|| {
|
||||||
Scheduler::app_resume();
|
AppProxy::resume();
|
||||||
tokio::spawn(fs::remove_file(tmp.clone()))
|
tokio::spawn(fs::remove_file(tmp.clone()))
|
||||||
});
|
});
|
||||||
Scheduler::app_stop().await;
|
AppProxy::stop().await;
|
||||||
|
|
||||||
let mut child = external::shell(ShellOpt {
|
let mut child = external::shell(ShellOpt {
|
||||||
cmd: (*opener.exec).into(),
|
cmd: (*opener.run).into(),
|
||||||
args: vec![tmp.to_owned().into()],
|
args: vec![OsString::new(), tmp.to_owned().into()],
|
||||||
piped: false,
|
piped: false,
|
||||||
orphan: false,
|
orphan: false,
|
||||||
})?;
|
})?;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use yazi_scheduler::Scheduler;
|
use yazi_proxy::AppProxy;
|
||||||
use yazi_shared::event::Cmd;
|
use yazi_shared::event::Cmd;
|
||||||
|
|
||||||
use crate::manager::Manager;
|
use crate::manager::Manager;
|
||||||
|
|
@ -7,7 +7,7 @@ impl Manager {
|
||||||
pub fn suspend(&mut self, _: Cmd) {
|
pub fn suspend(&mut self, _: Cmd) {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
Scheduler::app_stop().await;
|
AppProxy::stop().await;
|
||||||
unsafe { libc::raise(libc::SIGTSTP) };
|
unsafe { libc::raise(libc::SIGTSTP) };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use yazi_proxy::ManagerProxy;
|
||||||
use yazi_shared::{event::Cmd, fs::FilesOp, render};
|
use yazi_shared::{event::Cmd, fs::FilesOp, render};
|
||||||
|
|
||||||
use crate::{folder::Folder, manager::Manager, tab::Tab, tasks::Tasks};
|
use crate::{folder::Folder, manager::Manager, tab::Tab, tasks::Tasks};
|
||||||
|
|
@ -56,8 +57,8 @@ impl Manager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::_hover(None); // Re-hover in next loop
|
ManagerProxy::hover(None); // Re-hover in next loop
|
||||||
Self::_update_paged(); // Update for paged files in next loop
|
ManagerProxy::update_paged(); // Update for paged files in next loop
|
||||||
if calc {
|
if calc {
|
||||||
tasks.preload_sorted(&tab.current.files);
|
tasks.preload_sorted(&tab.current.files);
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +74,7 @@ impl Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !foreign {
|
if !foreign {
|
||||||
Self::_peek(true);
|
ManagerProxy::peek(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use yazi_shared::{emit, event::Cmd, fs::Url, Layer};
|
use yazi_shared::{event::Cmd, fs::Url};
|
||||||
|
|
||||||
use crate::{manager::Manager, tasks::Tasks};
|
use crate::{manager::Manager, tasks::Tasks};
|
||||||
|
|
||||||
|
|
@ -22,19 +22,6 @@ impl From<()> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
#[inline]
|
|
||||||
pub fn _update_paged() {
|
|
||||||
emit!(Call(Cmd::new("update_paged"), Layer::Manager));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn _update_paged_by(page: usize, only_if: &Url) {
|
|
||||||
emit!(Call(
|
|
||||||
Cmd::args("update_paged", vec![page.to_string()]).with("only-if", only_if.to_string()),
|
|
||||||
Layer::Manager
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_paged(&mut self, opt: impl TryInto<Opt>, tasks: &Tasks) {
|
pub fn update_paged(&mut self, opt: impl TryInto<Opt>, tasks: &Tasks) {
|
||||||
let Ok(opt) = opt.try_into() else {
|
let Ok(opt) = opt.try_into() else {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -52,4 +52,7 @@ impl Manager {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn selected_or_hovered(&self) -> Vec<&Url> { self.tabs.active().selected_or_hovered() }
|
pub fn selected_or_hovered(&self) -> Vec<&Url> { self.tabs.active().selected_or_hovered() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn hovered_and_selected(&self) -> Vec<&Url> { self.tabs.active().hovered_and_selected() }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use yazi_boot::BOOT;
|
use yazi_boot::BOOT;
|
||||||
|
use yazi_proxy::ManagerProxy;
|
||||||
use yazi_shared::fs::Url;
|
use yazi_shared::fs::Url;
|
||||||
|
|
||||||
use crate::{manager::Manager, tab::Tab};
|
use crate::tab::Tab;
|
||||||
|
|
||||||
pub struct Tabs {
|
pub struct Tabs {
|
||||||
pub idx: usize,
|
pub idx: usize,
|
||||||
|
|
@ -17,7 +18,7 @@ impl Tabs {
|
||||||
tabs.items[0].reveal(Url::from(BOOT.cwd.join(file)));
|
tabs.items[0].reveal(Url::from(BOOT.cwd.join(file)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::_refresh();
|
ManagerProxy::refresh();
|
||||||
tabs
|
tabs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,8 +43,8 @@ impl Tabs {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.idx = idx;
|
self.idx = idx;
|
||||||
Manager::_refresh();
|
ManagerProxy::refresh();
|
||||||
Manager::_peek(true);
|
ManagerProxy::peek(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,22 +5,8 @@ use yazi_shared::{emit, event::Cmd, Layer};
|
||||||
use crate::notify::{Message, Notify};
|
use crate::notify::{Message, Notify};
|
||||||
|
|
||||||
impl Notify {
|
impl Notify {
|
||||||
#[inline]
|
pub fn push(&mut self, msg: impl Into<Message>) {
|
||||||
pub fn _push_warn(title: &str, content: &str) {
|
let mut msg = msg.into() as Message;
|
||||||
emit!(Call(
|
|
||||||
Cmd::new("notify")
|
|
||||||
.with("title", title)
|
|
||||||
.with("content", content)
|
|
||||||
.with("level", "warn")
|
|
||||||
.with("timeout", 5),
|
|
||||||
Layer::App
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, msg: impl TryInto<Message>) {
|
|
||||||
let Ok(mut msg) = msg.try_into() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let instant = Instant::now();
|
let instant = Instant::now();
|
||||||
msg.timeout += instant - self.messages.first().map_or(instant, |m| m.instant);
|
msg.timeout += instant - self.messages.first().map_or(instant, |m| m.instant);
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
pub enum Level {
|
|
||||||
Info,
|
|
||||||
Warn,
|
|
||||||
Error,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Level {
|
|
||||||
type Err = ();
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
Ok(match s {
|
|
||||||
"info" => Self::Info,
|
|
||||||
"warn" => Self::Warn,
|
|
||||||
"error" => Self::Error,
|
|
||||||
_ => return Err(()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +1,31 @@
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
use yazi_shared::event::Cmd;
|
use yazi_proxy::options::{NotifyLevel, NotifyOpt};
|
||||||
|
|
||||||
use super::{Level, NOTIFY_BORDER};
|
use super::NOTIFY_BORDER;
|
||||||
|
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub level: Level,
|
pub level: NotifyLevel,
|
||||||
|
|
||||||
pub instant: Instant,
|
|
||||||
pub timeout: Duration,
|
pub timeout: Duration,
|
||||||
|
|
||||||
|
pub instant: Instant,
|
||||||
pub percent: u8,
|
pub percent: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Cmd> for Message {
|
impl From<NotifyOpt> for Message {
|
||||||
type Error = ();
|
fn from(opt: NotifyOpt) -> Self {
|
||||||
|
Self {
|
||||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
|
title: opt.title,
|
||||||
let timeout = c.take_name("timeout").and_then(|s| s.parse::<f64>().ok()).ok_or(())?;
|
content: opt.content,
|
||||||
if timeout < 0.0 {
|
level: opt.level,
|
||||||
return Err(());
|
timeout: opt.timeout,
|
||||||
}
|
|
||||||
|
|
||||||
let content = c.take_name("content").ok_or(())?;
|
|
||||||
Ok(Self {
|
|
||||||
title: c.take_name("title").ok_or(())?,
|
|
||||||
content,
|
|
||||||
level: c.take_name("level").ok_or(())?.parse()?,
|
|
||||||
|
|
||||||
instant: Instant::now(),
|
instant: Instant::now(),
|
||||||
timeout: Duration::from_secs_f64(timeout),
|
|
||||||
|
|
||||||
percent: 0,
|
percent: 0,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
mod commands;
|
mod commands;
|
||||||
mod level;
|
|
||||||
mod message;
|
mod message;
|
||||||
mod notify;
|
mod notify;
|
||||||
|
|
||||||
pub use level::*;
|
|
||||||
pub use message::*;
|
pub use message::*;
|
||||||
pub use notify::*;
|
pub use notify::*;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,10 @@
|
||||||
use anyhow::Result;
|
use yazi_proxy::options::SelectOpt;
|
||||||
use tokio::sync::oneshot;
|
use yazi_shared::render;
|
||||||
use yazi_config::popup::SelectCfg;
|
|
||||||
use yazi_shared::{emit, event::Cmd, render, term::Term, Layer};
|
|
||||||
|
|
||||||
use crate::select::Select;
|
use crate::select::Select;
|
||||||
|
|
||||||
pub struct Opt {
|
|
||||||
cfg: SelectCfg,
|
|
||||||
tx: oneshot::Sender<Result<usize>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<Cmd> for Opt {
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Select {
|
impl Select {
|
||||||
pub async fn _show(cfg: SelectCfg) -> Result<usize> {
|
pub fn show(&mut self, opt: impl TryInto<SelectOpt>) {
|
||||||
let (tx, rx) = oneshot::channel();
|
|
||||||
emit!(Call(Cmd::new("show").with_data(Opt { cfg, tx }), Layer::Select));
|
|
||||||
rx.await.unwrap_or_else(|_| Term::goodbye(|| false))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn show(&mut self, opt: impl TryInto<Opt>) {
|
|
||||||
let Ok(opt) = opt.try_into() else {
|
let Ok(opt) = opt.try_into() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
use yazi_proxy::ManagerProxy;
|
||||||
use yazi_shared::{event::Cmd, render};
|
use yazi_shared::{event::Cmd, render};
|
||||||
|
|
||||||
use crate::{manager::Manager, tab::Tab, Step};
|
use crate::{tab::Tab, Step};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
step: Step,
|
step: Step,
|
||||||
|
|
@ -36,7 +37,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::_hover(None);
|
ManagerProxy::hover(None);
|
||||||
render!();
|
render!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ use std::{mem, time::Duration};
|
||||||
use tokio::{fs, pin};
|
use tokio::{fs, pin};
|
||||||
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||||
use yazi_config::popup::InputCfg;
|
use yazi_config::popup::InputCfg;
|
||||||
use yazi_shared::{emit, event::Cmd, fs::{expand_path, Url}, render, Debounce, InputError, Layer};
|
use yazi_proxy::{CompletionProxy, InputProxy, ManagerProxy, TabProxy};
|
||||||
|
use yazi_shared::{event::Cmd, fs::{expand_path, Url}, render, Debounce, InputError};
|
||||||
|
|
||||||
use crate::{completion::Completion, input::Input, manager::Manager, tab::Tab};
|
use crate::tab::Tab;
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
target: Url,
|
target: Url,
|
||||||
|
|
@ -27,11 +28,6 @@ impl From<Url> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
#[inline]
|
|
||||||
pub fn _cd(target: &Url) {
|
|
||||||
emit!(Call(Cmd::args("cd", vec![target.to_string()]), Layer::Manager));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cd(&mut self, opt: impl Into<Opt>) {
|
pub fn cd(&mut self, opt: impl Into<Opt>) {
|
||||||
if !self.try_escape_visual() {
|
if !self.try_escape_visual() {
|
||||||
return;
|
return;
|
||||||
|
|
@ -68,13 +64,13 @@ impl Tab {
|
||||||
self.backstack.push(opt.target.clone());
|
self.backstack.push(opt.target.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::_refresh();
|
ManagerProxy::refresh();
|
||||||
render!();
|
render!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cd_interactive(&mut self) {
|
fn cd_interactive(&mut self) {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let rx = Input::_show(InputCfg::cd());
|
let rx = InputProxy::show(InputCfg::cd());
|
||||||
|
|
||||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||||
pin!(rx);
|
pin!(rx);
|
||||||
|
|
@ -88,13 +84,13 @@ impl Tab {
|
||||||
};
|
};
|
||||||
|
|
||||||
if meta.is_dir() {
|
if meta.is_dir() {
|
||||||
Tab::_cd(&u);
|
TabProxy::cd(&u);
|
||||||
} else {
|
} else {
|
||||||
Tab::_reveal(&u);
|
TabProxy::reveal(&u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(InputError::Completed(before, ticket)) => {
|
Err(InputError::Completed(before, ticket)) => {
|
||||||
Completion::_trigger(&before, ticket);
|
CompletionProxy::trigger(&before, ticket);
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
use yazi_proxy::{AppProxy, ManagerProxy};
|
||||||
use yazi_shared::{event::Cmd, render, render_and};
|
use yazi_shared::{event::Cmd, render, render_and};
|
||||||
|
|
||||||
use crate::{manager::Manager, notify::Notify, tab::Tab};
|
use crate::tab::Tab;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct Opt: u8 {
|
pub struct Opt: u8 {
|
||||||
|
|
@ -74,7 +75,7 @@ impl Tab {
|
||||||
|
|
||||||
self.selected.clear();
|
self.selected.clear();
|
||||||
if self.current.hovered().is_some_and(|h| h.is_dir()) {
|
if self.current.hovered().is_some_and(|h| h.is_dir()) {
|
||||||
Manager::_peek(true);
|
ManagerProxy::peek(true);
|
||||||
}
|
}
|
||||||
render_and!(true)
|
render_and!(true)
|
||||||
}
|
}
|
||||||
|
|
@ -98,28 +99,26 @@ impl Tab {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_escape_visual(&mut self) -> bool {
|
pub fn try_escape_visual(&mut self) -> bool {
|
||||||
let state = self.mode.is_select();
|
let select = self.mode.is_select();
|
||||||
let Some((_, indices)) = self.mode.take_visual() else {
|
let Some((_, indices)) = self.mode.take_visual() else {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut success = true;
|
render!();
|
||||||
for f in indices.iter().filter_map(|i| self.current.files.get(*i)) {
|
let urls: Vec<_> =
|
||||||
if state {
|
indices.into_iter().filter_map(|i| self.current.files.get(i)).map(|f| &f.url).collect();
|
||||||
success &= self.selected.add(&f.url);
|
|
||||||
} else {
|
|
||||||
self.selected.remove(&f.url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !success {
|
let same = !self.current.cwd.is_search();
|
||||||
Notify::_push_warn(
|
if !select {
|
||||||
|
self.selected.remove_many(&urls, same);
|
||||||
|
} else if self.selected.add_many(&urls, same) != urls.len() {
|
||||||
|
AppProxy::notify_warn(
|
||||||
"Escape visual mode",
|
"Escape visual mode",
|
||||||
"Some files cannot be selected, due to path nesting conflict.",
|
"Some files cannot be selected, due to path nesting conflict.",
|
||||||
);
|
);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
render!();
|
true
|
||||||
success
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ use std::time::Duration;
|
||||||
use tokio::pin;
|
use tokio::pin;
|
||||||
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||||
use yazi_config::popup::InputCfg;
|
use yazi_config::popup::InputCfg;
|
||||||
|
use yazi_proxy::{InputProxy, ManagerProxy};
|
||||||
use yazi_shared::{emit, event::Cmd, render, Debounce, InputError, Layer};
|
use yazi_shared::{emit, event::Cmd, render, Debounce, InputError, Layer};
|
||||||
|
|
||||||
use crate::{folder::{Filter, FilterCase}, input::Input, manager::Manager, tab::Tab};
|
use crate::{folder::{Filter, FilterCase}, tab::Tab};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
|
|
@ -28,7 +29,7 @@ impl Tab {
|
||||||
pub fn filter(&mut self, opt: impl Into<Opt>) {
|
pub fn filter(&mut self, opt: impl Into<Opt>) {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let rx = Input::_show(InputCfg::filter());
|
let rx = InputProxy::show(InputCfg::filter());
|
||||||
|
|
||||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||||
pin!(rx);
|
pin!(rx);
|
||||||
|
|
@ -62,7 +63,7 @@ impl Tab {
|
||||||
};
|
};
|
||||||
|
|
||||||
if opt.done {
|
if opt.done {
|
||||||
Manager::_update_paged(); // Update for paged files in next loop
|
ManagerProxy::update_paged(); // Update for paged files in next loop
|
||||||
}
|
}
|
||||||
|
|
||||||
let hovered = self.current.hovered().map(|f| f.url());
|
let hovered = self.current.hovered().map(|f| f.url());
|
||||||
|
|
@ -71,7 +72,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.current.repos(hovered) {
|
if self.current.repos(hovered) {
|
||||||
Manager::_hover(None);
|
ManagerProxy::hover(None);
|
||||||
}
|
}
|
||||||
render!();
|
render!();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ use std::time::Duration;
|
||||||
use tokio::pin;
|
use tokio::pin;
|
||||||
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||||
use yazi_config::popup::InputCfg;
|
use yazi_config::popup::InputCfg;
|
||||||
|
use yazi_proxy::InputProxy;
|
||||||
use yazi_shared::{emit, event::Cmd, render, Debounce, InputError, Layer};
|
use yazi_shared::{emit, event::Cmd, render, Debounce, InputError, Layer};
|
||||||
|
|
||||||
use crate::{folder::FilterCase, input::Input, tab::{Finder, Tab}};
|
use crate::{folder::FilterCase, tab::{Finder, Tab}};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
query: Option<String>,
|
query: Option<String>,
|
||||||
|
|
@ -35,7 +36,7 @@ impl Tab {
|
||||||
pub fn find(&mut self, opt: impl Into<Opt>) {
|
pub fn find(&mut self, opt: impl Into<Opt>) {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let rx = Input::_show(InputCfg::find(opt.prev));
|
let rx = InputProxy::show(InputCfg::find(opt.prev));
|
||||||
|
|
||||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||||
pin!(rx);
|
pin!(rx);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
use yazi_proxy::ManagerProxy;
|
||||||
use yazi_shared::event::Cmd;
|
use yazi_shared::event::Cmd;
|
||||||
|
|
||||||
use crate::{manager::Manager, tab::Tab};
|
use crate::tab::Tab;
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn hidden(&mut self, c: Cmd) {
|
pub fn hidden(&mut self, c: Cmd) {
|
||||||
|
|
@ -14,10 +15,10 @@ impl Tab {
|
||||||
self.apply_files_attrs();
|
self.apply_files_attrs();
|
||||||
|
|
||||||
if hovered.as_ref() != self.current.hovered().map(|f| &f.url) {
|
if hovered.as_ref() != self.current.hovered().map(|f| &f.url) {
|
||||||
Manager::_hover(hovered);
|
ManagerProxy::hover(hovered);
|
||||||
} else if self.current.hovered().is_some_and(|f| f.is_dir()) {
|
} else if self.current.hovered().is_some_and(|f| f.is_dir()) {
|
||||||
Manager::_peek(true);
|
ManagerProxy::peek(true);
|
||||||
}
|
}
|
||||||
Manager::_update_paged();
|
ManagerProxy::update_paged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use yazi_plugin::external::{self, FzfOpt, ZoxideOpt};
|
use yazi_plugin::external::{self, FzfOpt, ZoxideOpt};
|
||||||
use yazi_scheduler::{Scheduler, BLOCKER};
|
use yazi_proxy::{AppProxy, TabProxy};
|
||||||
|
use yazi_scheduler::BLOCKER;
|
||||||
use yazi_shared::{event::Cmd, fs::ends_with_slash, Defer};
|
use yazi_shared::{event::Cmd, fs::ends_with_slash, Defer};
|
||||||
|
|
||||||
use crate::tab::Tab;
|
use crate::tab::Tab;
|
||||||
|
|
@ -37,8 +38,8 @@ impl Tab {
|
||||||
let cwd = self.current.cwd.clone();
|
let cwd = self.current.cwd.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let _guard = BLOCKER.acquire().await.unwrap();
|
let _guard = BLOCKER.acquire().await.unwrap();
|
||||||
let _defer = Defer::new(Scheduler::app_resume);
|
let _defer = Defer::new(AppProxy::resume);
|
||||||
Scheduler::app_stop().await;
|
AppProxy::stop().await;
|
||||||
|
|
||||||
let result = if opt.type_ == OptType::Fzf {
|
let result = if opt.type_ == OptType::Fzf {
|
||||||
external::fzf(FzfOpt { cwd }).await
|
external::fzf(FzfOpt { cwd }).await
|
||||||
|
|
@ -51,9 +52,9 @@ impl Tab {
|
||||||
};
|
};
|
||||||
|
|
||||||
if opt.type_ == OptType::Fzf && !ends_with_slash(&url) {
|
if opt.type_ == OptType::Fzf && !ends_with_slash(&url) {
|
||||||
Tab::_reveal(&url)
|
TabProxy::reveal(&url)
|
||||||
} else {
|
} else {
|
||||||
Tab::_cd(&url)
|
TabProxy::cd(&url)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use yazi_shared::{emit, event::Cmd, fs::{expand_path, File, FilesOp, Url}, Layer};
|
use yazi_proxy::ManagerProxy;
|
||||||
|
use yazi_shared::{event::Cmd, fs::{expand_path, File, FilesOp, Url}};
|
||||||
|
|
||||||
use crate::{manager::Manager, tab::Tab};
|
use crate::tab::Tab;
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
target: Url,
|
target: Url,
|
||||||
|
|
@ -21,11 +22,6 @@ impl From<Url> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
#[inline]
|
|
||||||
pub fn _reveal(target: &Url) {
|
|
||||||
emit!(Call(Cmd::args("reveal", vec![target.to_string()]), Layer::Manager));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reveal(&mut self, opt: impl Into<Opt>) {
|
pub fn reveal(&mut self, opt: impl Into<Opt>) {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
|
|
||||||
|
|
@ -35,6 +31,6 @@ impl Tab {
|
||||||
|
|
||||||
self.cd(parent.clone());
|
self.cd(parent.clone());
|
||||||
FilesOp::Creating(parent, vec![File::from_dummy(&opt.target)]).emit();
|
FilesOp::Creating(parent, vec![File::from_dummy(&opt.target)]).emit();
|
||||||
Manager::_hover(Some(opt.target));
|
ManagerProxy::hover(Some(opt.target));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
use std::{mem, time::Duration};
|
use std::{fmt::Display, mem, time::Duration};
|
||||||
|
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use tokio::pin;
|
use tokio::pin;
|
||||||
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||||
use yazi_config::popup::InputCfg;
|
use yazi_config::popup::InputCfg;
|
||||||
use yazi_plugin::external;
|
use yazi_plugin::external;
|
||||||
|
use yazi_proxy::{InputProxy, ManagerProxy, TabProxy};
|
||||||
use yazi_shared::{event::Cmd, fs::FilesOp, render};
|
use yazi_shared::{event::Cmd, fs::FilesOp, render};
|
||||||
|
|
||||||
use crate::{input::Input, manager::Manager, tab::Tab};
|
use crate::tab::Tab;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub enum OptType {
|
pub enum OptType {
|
||||||
|
|
@ -26,14 +27,13 @@ impl From<String> for OptType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for OptType {
|
impl Display for OptType {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
f.write_str(match self {
|
||||||
Self::Rg => "rg",
|
Self::Rg => "rg",
|
||||||
Self::Fd => "fd",
|
Self::Fd => "fd",
|
||||||
Self::None => "none",
|
Self::None => "none",
|
||||||
}
|
})
|
||||||
.to_owned()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ impl Tab {
|
||||||
let hidden = self.conf.show_hidden;
|
let hidden = self.conf.show_hidden;
|
||||||
|
|
||||||
self.search = Some(tokio::spawn(async move {
|
self.search = Some(tokio::spawn(async move {
|
||||||
let mut input = Input::_show(InputCfg::search(&opt.type_.to_string()));
|
let mut input = InputProxy::show(InputCfg::search(&opt.type_.to_string()));
|
||||||
let Some(Ok(subject)) = input.recv().await else { bail!("") };
|
let Some(Ok(subject)) = input.recv().await else { bail!("") };
|
||||||
|
|
||||||
cwd = cwd.into_search(subject.clone());
|
cwd = cwd.into_search(subject.clone());
|
||||||
|
|
@ -73,7 +73,7 @@ impl Tab {
|
||||||
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(1000, Duration::from_millis(300));
|
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(1000, Duration::from_millis(300));
|
||||||
pin!(rx);
|
pin!(rx);
|
||||||
|
|
||||||
let ((), ticket) = (Tab::_cd(&cwd), FilesOp::prepare(&cwd));
|
let ((), ticket) = (TabProxy::cd(&cwd), FilesOp::prepare(&cwd));
|
||||||
while let Some(chunk) = rx.next().await {
|
while let Some(chunk) = rx.next().await {
|
||||||
FilesOp::Part(cwd.clone(), chunk, ticket).emit();
|
FilesOp::Part(cwd.clone(), chunk, ticket).emit();
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +91,7 @@ impl Tab {
|
||||||
if self.current.cwd.is_search() {
|
if self.current.cwd.is_search() {
|
||||||
let rep = self.history_new(&self.current.cwd.to_regular());
|
let rep = self.history_new(&self.current.cwd.to_regular());
|
||||||
drop(mem::replace(&mut self.current, rep));
|
drop(mem::replace(&mut self.current, rep));
|
||||||
Manager::_refresh();
|
ManagerProxy::refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use yazi_shared::{event::Cmd, fs::Url, render};
|
use yazi_proxy::AppProxy;
|
||||||
|
use yazi_shared::{event::Cmd, fs::Url, render, render_and};
|
||||||
|
|
||||||
use crate::tab::Tab;
|
use crate::tab::Tab;
|
||||||
|
|
||||||
|
|
@ -30,10 +31,17 @@ impl<'a> Tab {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
render!(match opt.state {
|
let b = match opt.state {
|
||||||
Some(true) => self.selected.add(&url),
|
Some(true) => render_and!(self.selected.add(&url)),
|
||||||
Some(false) => self.selected.remove(&url),
|
Some(false) => render_and!(self.selected.remove(&url)) | true,
|
||||||
None => self.selected.remove(&url) || self.selected.add(&url),
|
None => render_and!(self.selected.remove(&url) || self.selected.add(&url)),
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if !b {
|
||||||
|
AppProxy::notify_warn(
|
||||||
|
"Select one",
|
||||||
|
"This file cannot be selected, due to path nesting conflict.",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use yazi_proxy::AppProxy;
|
||||||
use yazi_shared::{event::Cmd, render};
|
use yazi_shared::{event::Cmd, render};
|
||||||
|
|
||||||
use crate::tab::Tab;
|
use crate::tab::Tab;
|
||||||
|
|
@ -23,24 +24,24 @@ impl From<Option<bool>> for Opt {
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn select_all(&mut self, opt: impl Into<Opt>) {
|
pub fn select_all(&mut self, opt: impl Into<Opt>) {
|
||||||
let mut b = false;
|
let iter = self.current.files.iter().map(|f| &f.url);
|
||||||
match opt.into().state {
|
let (removal, addition): (Vec<_>, Vec<_>) = match opt.into().state {
|
||||||
Some(true) => {
|
Some(true) => (vec![], iter.collect()),
|
||||||
for f in self.current.files.iter() {
|
Some(false) => (iter.collect(), vec![]),
|
||||||
b |= self.selected.add(&f.url);
|
None => iter.partition(|&u| self.selected.contains(u)),
|
||||||
}
|
};
|
||||||
}
|
|
||||||
Some(false) => {
|
let same = !self.current.cwd.is_search();
|
||||||
for f in self.current.files.iter() {
|
render!(self.selected.remove_many(&removal, same) > 0);
|
||||||
b |= self.selected.remove(&f.url);
|
|
||||||
}
|
let added = self.selected.add_many(&addition, same);
|
||||||
}
|
render!(added > 0);
|
||||||
None => {
|
|
||||||
for f in self.current.files.iter() {
|
if added != addition.len() {
|
||||||
b |= self.selected.remove(&f.url) || self.selected.add(&f.url);
|
AppProxy::notify_warn(
|
||||||
}
|
"Select all",
|
||||||
}
|
"Some files cannot be selected, due to path nesting conflict.",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
render!(b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
use yazi_config::{open::Opener, popup::InputCfg};
|
use yazi_config::{open::Opener, popup::InputCfg};
|
||||||
|
use yazi_proxy::{InputProxy, TasksProxy};
|
||||||
use yazi_shared::event::Cmd;
|
use yazi_shared::event::Cmd;
|
||||||
|
|
||||||
use crate::{input::Input, tab::Tab, tasks::Tasks};
|
use crate::tab::Tab;
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
exec: String,
|
run: String,
|
||||||
block: bool,
|
block: bool,
|
||||||
confirm: bool,
|
confirm: bool,
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +13,7 @@ pub struct Opt {
|
||||||
impl From<Cmd> for Opt {
|
impl From<Cmd> for Opt {
|
||||||
fn from(mut c: Cmd) -> Self {
|
fn from(mut c: Cmd) -> Self {
|
||||||
Self {
|
Self {
|
||||||
exec: c.take_first().unwrap_or_default(),
|
run: c.take_first().unwrap_or_default(),
|
||||||
block: c.named.contains_key("block"),
|
block: c.named.contains_key("block"),
|
||||||
confirm: c.named.contains_key("confirm"),
|
confirm: c.named.contains_key("confirm"),
|
||||||
}
|
}
|
||||||
|
|
@ -26,19 +27,19 @@ impl Tab {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut opt = opt.into() as Opt;
|
let mut opt = opt.into() as Opt;
|
||||||
let selected: Vec<_> = self.selected_or_hovered().into_iter().cloned().collect();
|
let selected = self.hovered_and_selected().into_iter().cloned().collect();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if !opt.confirm || opt.exec.is_empty() {
|
if !opt.confirm || opt.run.is_empty() {
|
||||||
let mut result = Input::_show(InputCfg::shell(opt.block).with_value(opt.exec));
|
let mut result = InputProxy::show(InputCfg::shell(opt.block).with_value(opt.run));
|
||||||
match result.recv().await {
|
match result.recv().await {
|
||||||
Some(Ok(e)) => opt.exec = e,
|
Some(Ok(e)) => opt.run = e,
|
||||||
_ => return,
|
_ => return,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tasks::_open(selected, Opener {
|
TasksProxy::open_with(selected, Opener {
|
||||||
exec: opt.exec,
|
run: opt.run,
|
||||||
block: opt.block,
|
block: opt.block,
|
||||||
orphan: false,
|
orphan: false,
|
||||||
desc: Default::default(),
|
desc: Default::default(),
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use yazi_config::manager::SortBy;
|
use yazi_config::manager::SortBy;
|
||||||
|
use yazi_proxy::ManagerProxy;
|
||||||
use yazi_shared::event::Cmd;
|
use yazi_shared::event::Cmd;
|
||||||
|
|
||||||
use crate::{manager::Manager, tab::Tab, tasks::Tasks};
|
use crate::{tab::Tab, tasks::Tasks};
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn sort(&mut self, c: Cmd, tasks: &Tasks) {
|
pub fn sort(&mut self, c: Cmd, tasks: &Tasks) {
|
||||||
|
|
@ -15,7 +16,7 @@ impl Tab {
|
||||||
self.conf.sort_dir_first = c.named.contains_key("dir-first");
|
self.conf.sort_dir_first = c.named.contains_key("dir-first");
|
||||||
|
|
||||||
self.apply_files_attrs();
|
self.apply_files_attrs();
|
||||||
Manager::_update_paged();
|
ManagerProxy::update_paged();
|
||||||
|
|
||||||
tasks.preload_sorted(&self.current.files);
|
tasks.preload_sorted(&self.current.files);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{collections::BTreeSet, mem};
|
use std::{collections::BTreeSet, fmt::Display, mem};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
|
|
@ -37,13 +37,12 @@ impl Mode {
|
||||||
pub fn is_visual(&self) -> bool { matches!(self, Mode::Select(..) | Mode::Unset(..)) }
|
pub fn is_visual(&self) -> bool { matches!(self, Mode::Select(..) | Mode::Unset(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for Mode {
|
impl Display for Mode {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
f.write_str(match self {
|
||||||
Mode::Normal => "normal",
|
Mode::Normal => "normal",
|
||||||
Mode::Select(..) => "select",
|
Mode::Select(..) => "select",
|
||||||
Mode::Unset(..) => "unset",
|
Mode::Unset(..) => "unset",
|
||||||
}
|
})
|
||||||
.to_string()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,90 +15,86 @@ impl Deref for Selected {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Selected {
|
impl Selected {
|
||||||
pub fn add(&mut self, url: &Url) -> bool { self.add_many(&[url]) }
|
#[inline]
|
||||||
|
pub fn add(&mut self, url: &Url) -> bool { self.add_same(&[url]) == 1 }
|
||||||
|
|
||||||
/// Adds a list of URLs to the user structure.
|
pub fn add_many(&mut self, urls: &[&Url], same: bool) -> usize {
|
||||||
///
|
if same {
|
||||||
/// This method attempts to add a slice of `Url` references to the internal
|
return self.add_same(urls);
|
||||||
/// structure, ensuring that all URLs have the same parent directory. For
|
|
||||||
/// example, URLs such as `/a/b/c`, `/a/b/d`, `/a/b/e`, and `/a/b/f` are
|
|
||||||
/// acceptable, while `/a/b/c` and `/a/e/f` would not be, due to differing
|
|
||||||
/// parent directories.
|
|
||||||
///
|
|
||||||
/// The addition will fail under the following conditions:
|
|
||||||
/// - Any of the URLs already exists within the `inner` collection.
|
|
||||||
/// - The parent directory of the URLs already exists as a key in the
|
|
||||||
/// `parents` map.
|
|
||||||
///
|
|
||||||
/// When the provided list of URLs is empty, the method will return `true` as
|
|
||||||
/// there are no URLs to process, which is considered a successful operation.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `urls` - A slice of references to `Url` objects that are to be added.
|
|
||||||
/// All URLs should have the same parent path.
|
|
||||||
///
|
|
||||||
/// # Returns
|
|
||||||
///
|
|
||||||
/// Returns `true` if all URLs were successfully added, or if the input list
|
|
||||||
/// is empty. Returns `false` if any URL could not be added due to the
|
|
||||||
/// existence of its parent directory in the structure, or if the URL itself
|
|
||||||
/// is already present.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use yazi_core::tab::Selected;
|
|
||||||
/// # use yazi_shared::fs::Url;
|
|
||||||
/// let mut s = Selected::default();
|
|
||||||
///
|
|
||||||
/// let url1 = Url::from("/a/b/c");
|
|
||||||
/// let url2 = Url::from("/a/b/d");
|
|
||||||
/// assert!(s.add_many(&[&url1, &url2]));
|
|
||||||
/// ```
|
|
||||||
pub fn add_many(&mut self, urls: &[&Url]) -> bool {
|
|
||||||
if urls.is_empty() {
|
|
||||||
return true;
|
|
||||||
} else if self.parents.contains_key(urls[0]) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut grouped: HashMap<_, Vec<_>> = Default::default();
|
||||||
|
for &u in urls {
|
||||||
|
if let Some(p) = u.parent_url() {
|
||||||
|
grouped.entry(p).or_default().push(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grouped.into_values().map(|v| self.add_same(&v)).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_same(&mut self, urls: &[&Url]) -> usize {
|
||||||
|
// If it has appeared as a parent
|
||||||
|
let urls: Vec<_> = urls.iter().filter(|&&u| !self.parents.contains_key(u)).collect();
|
||||||
|
if urls.is_empty() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it has appeared as a child
|
||||||
let mut parent = urls[0].parent_url();
|
let mut parent = urls[0].parent_url();
|
||||||
let mut parents = vec![];
|
let mut parents = vec![];
|
||||||
while let Some(u) = parent {
|
while let Some(u) = parent {
|
||||||
if self.inner.contains(&u) {
|
if self.inner.contains(&u) {
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = u.parent_url();
|
parent = u.parent_url();
|
||||||
parents.push(u);
|
parents.push(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
for u in parents {
|
let len = self.inner.len();
|
||||||
*self.parents.entry(u).or_insert(0) += urls.len();
|
self.inner.extend(urls.iter().map(|&&u| u.clone()));
|
||||||
}
|
|
||||||
|
|
||||||
self.inner.extend(urls.iter().map(|&u| u.clone()));
|
for u in parents {
|
||||||
true
|
*self.parents.entry(u).or_insert(0) += self.inner.len() - len;
|
||||||
|
}
|
||||||
|
urls.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(&mut self, url: &Url) -> bool {
|
#[inline]
|
||||||
if !self.inner.remove(url) {
|
pub fn remove(&mut self, url: &Url) -> bool { self.remove_same(&[url]) == 1 }
|
||||||
return false;
|
|
||||||
|
pub fn remove_many(&mut self, urls: &[&Url], same: bool) -> usize {
|
||||||
|
if same {
|
||||||
|
return self.remove_same(urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut parent = url.parent_url();
|
let mut grouped: HashMap<_, Vec<_>> = Default::default();
|
||||||
|
for &u in urls {
|
||||||
|
if let Some(p) = u.parent_url() {
|
||||||
|
grouped.entry(p).or_default().push(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grouped.into_values().map(|v| self.remove_same(&v)).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_same(&mut self, urls: &[&Url]) -> usize {
|
||||||
|
let count = urls.iter().map(|&u| self.inner.remove(u)).filter(|&b| b).count();
|
||||||
|
if count == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut parent = urls[0].parent_url();
|
||||||
while let Some(u) = parent {
|
while let Some(u) = parent {
|
||||||
let n = self.parents.get_mut(&u).unwrap();
|
let n = self.parents.get_mut(&u).unwrap();
|
||||||
if *n == 1 {
|
|
||||||
|
*n -= count;
|
||||||
|
if *n == 0 {
|
||||||
self.parents.remove(&u);
|
self.parents.remove(&u);
|
||||||
} else {
|
|
||||||
*n -= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = u.parent_url();
|
parent = u.parent_url();
|
||||||
}
|
}
|
||||||
true
|
count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
|
|
@ -153,11 +149,14 @@ mod tests {
|
||||||
fn insert_many_success() {
|
fn insert_many_success() {
|
||||||
let mut s = Selected::default();
|
let mut s = Selected::default();
|
||||||
|
|
||||||
assert!(s.add_many(&[
|
assert_eq!(
|
||||||
&Url::from("/parent/child1"),
|
3,
|
||||||
&Url::from("/parent/child2"),
|
s.add_same(&[
|
||||||
&Url::from("/parent/child3")
|
&Url::from("/parent/child1"),
|
||||||
]));
|
&Url::from("/parent/child2"),
|
||||||
|
&Url::from("/parent/child3")
|
||||||
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -165,7 +164,7 @@ mod tests {
|
||||||
let mut s = Selected::default();
|
let mut s = Selected::default();
|
||||||
|
|
||||||
s.add(&Url::from("/parent"));
|
s.add(&Url::from("/parent"));
|
||||||
assert!(!s.add_many(&[&Url::from("/parent/child1"), &Url::from("/parent/child2"),]));
|
assert_eq!(0, s.add_same(&[&Url::from("/parent/child1"), &Url::from("/parent/child2")]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -173,14 +172,14 @@ mod tests {
|
||||||
let mut s = Selected::default();
|
let mut s = Selected::default();
|
||||||
|
|
||||||
s.add(&Url::from("/parent/child1"));
|
s.add(&Url::from("/parent/child1"));
|
||||||
assert!(s.add_many(&[&Url::from("/parent/child1"), &Url::from("/parent/child2")]));
|
assert_eq!(2, s.add_same(&[&Url::from("/parent/child1"), &Url::from("/parent/child2")]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_many_empty_urls_list() {
|
fn insert_many_empty_urls_list() {
|
||||||
let mut s = Selected::default();
|
let mut s = Selected::default();
|
||||||
|
|
||||||
assert!(s.add_many(&[]));
|
assert_eq!(0, s.add_same(&[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -188,14 +187,17 @@ mod tests {
|
||||||
let mut s = Selected::default();
|
let mut s = Selected::default();
|
||||||
|
|
||||||
s.add(&Url::from("/parent/child"));
|
s.add(&Url::from("/parent/child"));
|
||||||
assert!(!s.add_many(&[&Url::from("/parent/child/child1"), &Url::from("/parent/child/child2")]));
|
assert_eq!(
|
||||||
|
0,
|
||||||
|
s.add_same(&[&Url::from("/parent/child/child1"), &Url::from("/parent/child/child2")])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_many_with_direct_parent_fails() {
|
fn insert_many_with_direct_parent_fails() {
|
||||||
let mut s = Selected::default();
|
let mut s = Selected::default();
|
||||||
|
|
||||||
s.add(&Url::from("/a"));
|
s.add(&Url::from("/a"));
|
||||||
assert!(!s.add_many(&[&Url::from("/a/b")]));
|
assert_eq!(0, s.add_same(&[&Url::from("/a/b")]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -203,14 +205,15 @@ mod tests {
|
||||||
let mut s = Selected::default();
|
let mut s = Selected::default();
|
||||||
|
|
||||||
s.add(&Url::from("/a/b"));
|
s.add(&Url::from("/a/b"));
|
||||||
assert!(!s.add_many(&[&Url::from("/a")]));
|
assert_eq!(0, s.add_same(&[&Url::from("/a")]));
|
||||||
|
assert_eq!(1, s.add_same(&[&Url::from("/b"), &Url::from("/a")]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_many_sibling_directories_success() {
|
fn insert_many_sibling_directories_success() {
|
||||||
let mut s = Selected::default();
|
let mut s = Selected::default();
|
||||||
|
|
||||||
assert!(s.add_many(&[&Url::from("/a/b"), &Url::from("/a/c")]));
|
assert_eq!(2, s.add_same(&[&Url::from("/a/b"), &Url::from("/a/c")]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -218,7 +221,7 @@ mod tests {
|
||||||
let mut s = Selected::default();
|
let mut s = Selected::default();
|
||||||
|
|
||||||
s.add(&Url::from("/a/b"));
|
s.add(&Url::from("/a/b"));
|
||||||
assert!(!s.add_many(&[&Url::from("/a/b/c")]));
|
assert_eq!(0, s.add_same(&[&Url::from("/a/b/c")]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -228,7 +231,7 @@ mod tests {
|
||||||
let child1 = Url::from("/parent/child1");
|
let child1 = Url::from("/parent/child1");
|
||||||
let child2 = Url::from("/parent/child2");
|
let child2 = Url::from("/parent/child2");
|
||||||
let child3 = Url::from("/parent/child3");
|
let child3 = Url::from("/parent/child3");
|
||||||
assert!(s.add_many(&[&child1, &child2, &child3]));
|
assert_eq!(3, s.add_same(&[&child1, &child2, &child3]));
|
||||||
|
|
||||||
assert!(s.remove(&child1));
|
assert!(s.remove(&child1));
|
||||||
assert_eq!(s.inner.len(), 2);
|
assert_eq!(s.inner.len(), 2);
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,18 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hovered_and_selected(&self) -> Vec<&Url> {
|
||||||
|
let Some(h) = self.current.hovered() else {
|
||||||
|
return vec![];
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.selected.is_empty() {
|
||||||
|
vec![&h.url, &h.url]
|
||||||
|
} else {
|
||||||
|
[&h.url].into_iter().chain(self.selected.iter()).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- History
|
// --- History
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn history_new(&mut self, url: &Url) -> Folder {
|
pub fn history_new(&mut self, url: &Url) -> Folder {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ use std::io::{stdout, Write};
|
||||||
|
|
||||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||||
use tokio::{io::{stdin, AsyncReadExt}, select, sync::mpsc, time};
|
use tokio::{io::{stdin, AsyncReadExt}, select, sync::mpsc, time};
|
||||||
use yazi_scheduler::{Scheduler, BLOCKER};
|
use yazi_proxy::AppProxy;
|
||||||
|
use yazi_scheduler::BLOCKER;
|
||||||
use yazi_shared::{event::Cmd, term::Term, Defer};
|
use yazi_shared::{event::Cmd, term::Term, Defer};
|
||||||
|
|
||||||
use crate::tasks::Tasks;
|
use crate::tasks::Tasks;
|
||||||
|
|
@ -26,10 +27,10 @@ impl Tasks {
|
||||||
task.logs.clone()
|
task.logs.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
Scheduler::app_stop().await;
|
AppProxy::stop().await;
|
||||||
let _defer = Defer::new(|| {
|
let _defer = Defer::new(|| {
|
||||||
disable_raw_mode().ok();
|
disable_raw_mode().ok();
|
||||||
Scheduler::app_resume();
|
AppProxy::resume();
|
||||||
});
|
});
|
||||||
|
|
||||||
Term::clear(&mut stdout()).ok();
|
Term::clear(&mut stdout()).ok();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
mod arrow;
|
mod arrow;
|
||||||
mod cancel;
|
mod cancel;
|
||||||
mod inspect;
|
mod inspect;
|
||||||
mod open;
|
mod open_with;
|
||||||
mod toggle;
|
mod toggle;
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
use yazi_config::open::Opener;
|
|
||||||
use yazi_shared::{emit, event::Cmd, fs::Url, Layer};
|
|
||||||
|
|
||||||
use crate::tasks::Tasks;
|
|
||||||
|
|
||||||
pub struct Opt {
|
|
||||||
targets: Vec<Url>,
|
|
||||||
opener: Opener,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<Cmd> for Opt {
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Tasks {
|
|
||||||
pub fn _open(targets: Vec<Url>, opener: Opener) {
|
|
||||||
emit!(Call(Cmd::new("open").with_data(Opt { targets, opener }), Layer::Tasks));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn open(&mut self, opt: impl TryInto<Opt>) {
|
|
||||||
if let Ok(opt) = opt.try_into() {
|
|
||||||
self.file_open_with(&opt.opener, &opt.targets);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
yazi-core/src/tasks/commands/open_with.rs
Normal file
11
yazi-core/src/tasks/commands/open_with.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
use yazi_proxy::options::OpenWithOpt;
|
||||||
|
|
||||||
|
use crate::tasks::Tasks;
|
||||||
|
|
||||||
|
impl Tasks {
|
||||||
|
pub fn open_with(&mut self, opt: impl TryInto<OpenWithOpt>) {
|
||||||
|
if let Ok(opt) = opt.try_into() {
|
||||||
|
self.file_open_with(&opt.opener, &opt.targets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, mem, path::Path, sync::Arc, time::Duration};
|
use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, mem, sync::Arc, time::Duration};
|
||||||
|
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
@ -56,28 +56,26 @@ impl Tasks {
|
||||||
running.values().take(Self::limit()).map(Into::into).collect()
|
running.values().take(Self::limit()).map(Into::into).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_open(&self, targets: &[(impl AsRef<Path>, impl AsRef<str>)]) -> bool {
|
pub fn file_open(&self, hovered: &Url, targets: &[(Url, String)]) {
|
||||||
let mut openers = BTreeMap::new();
|
let mut openers = BTreeMap::new();
|
||||||
for (path, mime) in targets {
|
for (url, mime) in targets {
|
||||||
if let Some(opener) = OPEN.openers(path, mime).and_then(|o| o.first().copied()) {
|
if let Some(opener) = OPEN.openers(url, mime).and_then(|o| o.first().copied()) {
|
||||||
openers.entry(opener).or_insert_with(Vec::new).push(path.as_ref().as_os_str());
|
openers.entry(opener).or_insert_with(|| vec![hovered]).push(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (opener, args) in openers {
|
for (opener, args) in openers {
|
||||||
self.file_open_with(opener, &args);
|
self.file_open_with(opener, &args);
|
||||||
}
|
}
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_open_with(&self, opener: &Opener, args: &[impl AsRef<OsStr>]) -> bool {
|
pub fn file_open_with(&self, opener: &Opener, args: &[impl AsRef<OsStr>]) {
|
||||||
if opener.spread {
|
if opener.spread {
|
||||||
self.scheduler.process_open(opener, args);
|
self.scheduler.process_open(opener, args);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
for target in args {
|
for target in args.iter().skip(1) {
|
||||||
self.scheduler.process_open(opener, &[target]);
|
self.scheduler.process_open(opener, &[&args[0], target]);
|
||||||
}
|
}
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_cut(&self, src: &HashSet<Url>, dest: &Url, force: bool) {
|
pub fn file_cut(&self, src: &HashSet<Url>, dest: &Url, force: bool) {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ impl WhichSorter {
|
||||||
entities.push(match self.by {
|
entities.push(match self.by {
|
||||||
SortBy::None => unreachable!(),
|
SortBy::None => unreachable!(),
|
||||||
SortBy::Key => Cow::Owned(ctrl.on()),
|
SortBy::Key => Cow::Owned(ctrl.on()),
|
||||||
SortBy::Desc => ctrl.desc_or_exec(),
|
SortBy::Desc => ctrl.desc_or_run(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ yazi-boot = { path = "../yazi-boot", version = "0.2.3" }
|
||||||
yazi-config = { path = "../yazi-config", version = "0.2.3" }
|
yazi-config = { path = "../yazi-config", version = "0.2.3" }
|
||||||
yazi-core = { path = "../yazi-core", version = "0.2.3" }
|
yazi-core = { path = "../yazi-core", version = "0.2.3" }
|
||||||
yazi-plugin = { path = "../yazi-plugin", version = "0.2.3" }
|
yazi-plugin = { path = "../yazi-plugin", version = "0.2.3" }
|
||||||
|
yazi-proxy = { path = "../yazi-proxy", version = "0.2.3" }
|
||||||
yazi-scheduler = { path = "../yazi-scheduler", version = "0.2.3" }
|
yazi-scheduler = { path = "../yazi-scheduler", version = "0.2.3" }
|
||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.3" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.3" }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ pub(crate) struct App {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub(crate) async fn run() -> Result<()> {
|
pub(crate) async fn serve() -> Result<()> {
|
||||||
let term = Term::start()?;
|
let term = Term::start()?;
|
||||||
let signals = Signals::start()?;
|
let signals = Signals::start()?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
use yazi_core::notify::Message;
|
use yazi_proxy::options::NotifyOpt;
|
||||||
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub(crate) fn notify(&mut self, msg: impl TryInto<Message>) { self.cx.notify.push(msg); }
|
pub(crate) fn notify(&mut self, opt: impl TryInto<NotifyOpt>) {
|
||||||
|
let Ok(opt) = opt.try_into() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.cx.notify.push(opt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -151,11 +151,11 @@ impl<'a> Executor<'a> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
on!(open);
|
|
||||||
on!(toggle, "close");
|
on!(toggle, "close");
|
||||||
on!(arrow);
|
on!(arrow);
|
||||||
on!(inspect);
|
on!(inspect);
|
||||||
on!(cancel);
|
on!(cancel);
|
||||||
|
on!(open_with);
|
||||||
|
|
||||||
#[allow(clippy::single_match)]
|
#[allow(clippy::single_match)]
|
||||||
match cmd.name.as_str() {
|
match cmd.name.as_str() {
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,9 @@ impl Widget for Bindings<'_> {
|
||||||
let col1: Vec<_> =
|
let col1: Vec<_> =
|
||||||
bindings.iter().map(|c| ListItem::new(c.on()).style(THEME.help.on)).collect();
|
bindings.iter().map(|c| ListItem::new(c.on()).style(THEME.help.on)).collect();
|
||||||
|
|
||||||
// Exec
|
// Run
|
||||||
let col2: Vec<_> =
|
let col2: Vec<_> =
|
||||||
bindings.iter().map(|c| ListItem::new(c.exec()).style(THEME.help.exec)).collect();
|
bindings.iter().map(|c| ListItem::new(c.run()).style(THEME.help.run)).collect();
|
||||||
|
|
||||||
// Desc
|
// Desc
|
||||||
let col3: Vec<_> = bindings
|
let col3: Vec<_> = bindings
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ impl<'a> Widget for Layout<'a> {
|
||||||
|
|
||||||
let chunks = layout::Layout::vertical([Constraint::Fill(1), Constraint::Length(1)]).split(area);
|
let chunks = layout::Layout::vertical([Constraint::Fill(1), Constraint::Length(1)]).split(area);
|
||||||
Line::styled(
|
Line::styled(
|
||||||
help.keyword().unwrap_or_else(|| format!("{}.help", help.layer.to_string())),
|
help.keyword().unwrap_or_else(|| format!("{}.help", help.layer)),
|
||||||
THEME.help.footer,
|
THEME.help.footer,
|
||||||
)
|
)
|
||||||
.render(chunks[1], buf);
|
.render(chunks[1], buf);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use mlua::{Scope, Table};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
use yazi_config::LAYOUT;
|
use yazi_config::LAYOUT;
|
||||||
use yazi_plugin::{elements::RectRef, LUA};
|
use yazi_plugin::{elements::RectRef, LUA};
|
||||||
use yazi_shared::RoCell;
|
use yazi_shared::{Defer, RoCell};
|
||||||
|
|
||||||
use crate::Ctx;
|
use crate::Ctx;
|
||||||
|
|
||||||
|
|
@ -34,6 +34,7 @@ impl Lives {
|
||||||
f: impl FnOnce(&Scope<'a, 'a>) -> mlua::Result<T>,
|
f: impl FnOnce(&Scope<'a, 'a>) -> mlua::Result<T>,
|
||||||
) -> mlua::Result<T> {
|
) -> mlua::Result<T> {
|
||||||
let result = LUA.scope(|scope| {
|
let result = LUA.scope(|scope| {
|
||||||
|
let _defer = Defer::new(|| SCOPE.drop());
|
||||||
SCOPE.init(unsafe { mem::transmute(scope) });
|
SCOPE.init(unsafe { mem::transmute(scope) });
|
||||||
LUA.set_named_registry_value("cx", scope.create_any_userdata_ref(cx)?)?;
|
LUA.set_named_registry_value("cx", scope.create_any_userdata_ref(cx)?)?;
|
||||||
|
|
||||||
|
|
@ -58,7 +59,6 @@ impl Lives {
|
||||||
status: *globals.raw_get::<_, Table>("Status")?.raw_get::<_, RectRef>("area")?,
|
status: *globals.raw_get::<_, Table>("Status")?.raw_get::<_, RectRef>("area")?,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
SCOPE.drop();
|
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,10 @@ pub(super) struct Logs;
|
||||||
|
|
||||||
impl Logs {
|
impl Logs {
|
||||||
pub(super) fn start() {
|
pub(super) fn start() {
|
||||||
let appender = tracing_appender::rolling::never(Xdg::state_dir().unwrap(), "yazi.log");
|
let state_dir = Xdg::state_dir();
|
||||||
|
std::fs::create_dir_all(&state_dir).expect("Failed to create state directory");
|
||||||
|
|
||||||
|
let appender = tracing_appender::rolling::never(state_dir, "yazi.log");
|
||||||
let (handle, guard) = tracing_appender::non_blocking(appender);
|
let (handle, guard) = tracing_appender::non_blocking(appender);
|
||||||
|
|
||||||
// let filter = EnvFilter::from_default_env();
|
// let filter = EnvFilter::from_default_env();
|
||||||
|
|
|
||||||
|
|
@ -52,5 +52,5 @@ async fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
yazi_core::init();
|
yazi_core::init();
|
||||||
|
|
||||||
app::App::run().await
|
app::App::serve().await
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use ratatui::{buffer::Buffer, layout::{self, Constraint, Offset, Rect}, style::{Style, Stylize}, widgets::{Block, BorderType, Paragraph, Widget, Wrap}};
|
use ratatui::{buffer::Buffer, layout::{self, Constraint, Offset, Rect}, widgets::{Block, BorderType, Paragraph, Widget, Wrap}};
|
||||||
use yazi_core::notify::{Level, Message};
|
use yazi_config::THEME;
|
||||||
|
use yazi_core::notify::Message;
|
||||||
|
use yazi_proxy::options::NotifyLevel;
|
||||||
|
|
||||||
use crate::{widgets::Clear, Ctx};
|
use crate::{widgets::Clear, Ctx};
|
||||||
|
|
||||||
|
|
@ -42,9 +44,9 @@ impl<'a> Widget for Layout<'a> {
|
||||||
|
|
||||||
for (i, m) in notify.messages.iter().enumerate().take(limit) {
|
for (i, m) in notify.messages.iter().enumerate().take(limit) {
|
||||||
let (icon, style) = match m.level {
|
let (icon, style) = match m.level {
|
||||||
Level::Info => ("", Style::default().green()),
|
NotifyLevel::Info => (&THEME.notify.icon_info, THEME.notify.title_info),
|
||||||
Level::Warn => ("", Style::default().yellow()),
|
NotifyLevel::Warn => (&THEME.notify.icon_warn, THEME.notify.title_warn),
|
||||||
Level::Error => ("", Style::default().red()),
|
NotifyLevel::Error => (&THEME.notify.icon_error, THEME.notify.title_error),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut rect =
|
let mut rect =
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ impl Signals {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn spawn_system_task(&self) -> Result<JoinHandle<()>> {
|
fn spawn_system_task(&self) -> Result<JoinHandle<()>> {
|
||||||
use libc::{SIGCONT, SIGHUP, SIGINT, SIGQUIT, SIGTERM};
|
use libc::{SIGCONT, SIGHUP, SIGINT, SIGQUIT, SIGTERM};
|
||||||
use yazi_scheduler::{Scheduler, BLOCKER};
|
use yazi_proxy::AppProxy;
|
||||||
|
use yazi_scheduler::BLOCKER;
|
||||||
|
|
||||||
let mut signals = signal_hook_tokio::Signals::new([
|
let mut signals = signal_hook_tokio::Signals::new([
|
||||||
// Terminating signals
|
// Terminating signals
|
||||||
|
|
@ -65,7 +66,7 @@ impl Signals {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SIGCONT => Scheduler::app_resume(),
|
SIGCONT => AppProxy::resume(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ impl Widget for Cand<'_> {
|
||||||
spans.push(Span::styled(&THEME.which.separator, THEME.which.separator_style));
|
spans.push(Span::styled(&THEME.which.separator, THEME.which.separator_style));
|
||||||
|
|
||||||
// Description
|
// Description
|
||||||
spans.push(Span::styled(self.cand.desc_or_exec(), THEME.which.desc));
|
spans.push(Span::styled(self.cand.desc_or_run(), THEME.which.desc));
|
||||||
|
|
||||||
Line::from(spans).render(area, buf);
|
Line::from(spans).render(area, buf);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ repository = "https://github.com/sxyazi/yazi"
|
||||||
yazi-adaptor = { path = "../yazi-adaptor", version = "0.2.3" }
|
yazi-adaptor = { path = "../yazi-adaptor", version = "0.2.3" }
|
||||||
yazi-boot = { path = "../yazi-boot", version = "0.2.3" }
|
yazi-boot = { path = "../yazi-boot", version = "0.2.3" }
|
||||||
yazi-config = { path = "../yazi-config", version = "0.2.3" }
|
yazi-config = { path = "../yazi-config", version = "0.2.3" }
|
||||||
|
yazi-proxy = { path = "../yazi-proxy", version = "0.2.3" }
|
||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.3" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.3" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ local M = {}
|
||||||
function M:peek()
|
function M:peek()
|
||||||
local _, bound = ya.preview_archive(self)
|
local _, bound = ya.preview_archive(self)
|
||||||
if bound then
|
if bound then
|
||||||
ya.manager_emit("peek", { tostring(bound), only_if = tostring(self.file.url), upper_bound = "" })
|
ya.manager_emit("peek", { bound, only_if = tostring(self.file.url), upper_bound = true })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ function M:seek(units)
|
||||||
if h and h.url == self.file.url then
|
if h and h.url == self.file.url then
|
||||||
local step = math.floor(units * self.area.h / 10)
|
local step = math.floor(units * self.area.h / 10)
|
||||||
ya.manager_emit("peek", {
|
ya.manager_emit("peek", {
|
||||||
tostring(math.max(0, cx.active.preview.skip + step)),
|
math.max(0, cx.active.preview.skip + step),
|
||||||
only_if = tostring(self.file.url),
|
only_if = tostring(self.file.url),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ local M = {}
|
||||||
function M:peek()
|
function M:peek()
|
||||||
local _, bound = ya.preview_code(self)
|
local _, bound = ya.preview_code(self)
|
||||||
if bound then
|
if bound then
|
||||||
ya.manager_emit("peek", { tostring(bound), only_if = tostring(self.file.url), upper_bound = "" })
|
ya.manager_emit("peek", { bound, only_if = tostring(self.file.url), upper_bound = true })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ function M:seek(units)
|
||||||
if h and h.url == self.file.url then
|
if h and h.url == self.file.url then
|
||||||
local step = math.floor(units * self.area.h / 10)
|
local step = math.floor(units * self.area.h / 10)
|
||||||
ya.manager_emit("peek", {
|
ya.manager_emit("peek", {
|
||||||
tostring(math.max(0, cx.active.preview.skip + step)),
|
math.max(0, cx.active.preview.skip + step),
|
||||||
only_if = tostring(self.file.url),
|
only_if = tostring(self.file.url),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ function M:peek()
|
||||||
|
|
||||||
local bound = math.max(0, #folder.files - self.area.h)
|
local bound = math.max(0, #folder.files - self.area.h)
|
||||||
if self.skip > bound then
|
if self.skip > bound then
|
||||||
ya.manager_emit("peek", { tostring(bound), only_if = tostring(self.file.url), upper_bound = "" })
|
ya.manager_emit("peek", { bound, only_if = tostring(self.file.url), upper_bound = true })
|
||||||
end
|
end
|
||||||
|
|
||||||
local items, markers = {}, {}
|
local items, markers = {}, {}
|
||||||
|
|
@ -37,7 +37,7 @@ function M:seek(units)
|
||||||
local step = math.floor(units * self.area.h / 10)
|
local step = math.floor(units * self.area.h / 10)
|
||||||
local bound = math.max(0, #folder.files - self.area.h)
|
local bound = math.max(0, #folder.files - self.area.h)
|
||||||
ya.manager_emit("peek", {
|
ya.manager_emit("peek", {
|
||||||
tostring(ya.clamp(0, cx.active.preview.skip + step, bound)),
|
ya.clamp(0, cx.active.preview.skip + step, bound),
|
||||||
only_if = tostring(self.file.url),
|
only_if = tostring(self.file.url),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ function M:peek()
|
||||||
|
|
||||||
child:start_kill()
|
child:start_kill()
|
||||||
if self.skip > 0 and i < self.skip + limit then
|
if self.skip > 0 and i < self.skip + limit then
|
||||||
ya.manager_emit("peek", { tostring(math.max(0, i - limit)), only_if = tostring(self.file.url), upper_bound = "" })
|
ya.manager_emit("peek", { math.max(0, i - limit), only_if = tostring(self.file.url), upper_bound = true })
|
||||||
else
|
else
|
||||||
lines = lines:gsub("\t", string.rep(" ", PREVIEW.tab_size))
|
lines = lines:gsub("\t", string.rep(" ", PREVIEW.tab_size))
|
||||||
ya.preview_widgets(self, { ui.Paragraph.parse(self.area, lines) })
|
ya.preview_widgets(self, { ui.Paragraph.parse(self.area, lines) })
|
||||||
|
|
@ -46,7 +46,7 @@ function M:seek(units)
|
||||||
if h and h.url == self.file.url then
|
if h and h.url == self.file.url then
|
||||||
local step = math.floor(units * self.area.h / 10)
|
local step = math.floor(units * self.area.h / 10)
|
||||||
ya.manager_emit("peek", {
|
ya.manager_emit("peek", {
|
||||||
tostring(math.max(0, cx.active.preview.skip + step)),
|
math.max(0, cx.active.preview.skip + step),
|
||||||
only_if = tostring(self.file.url),
|
only_if = tostring(self.file.url),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
@ -55,7 +55,7 @@ end
|
||||||
function M:fallback_to_builtin()
|
function M:fallback_to_builtin()
|
||||||
local _, bound = ya.preview_code(self)
|
local _, bound = ya.preview_code(self)
|
||||||
if bound then
|
if bound then
|
||||||
ya.manager_emit("peek", { tostring(bound), only_if = tostring(self.file.url), upper_bound = "" })
|
ya.manager_emit("peek", { bound, only_if = tostring(self.file.url), upper_bound = true })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,10 @@ function M:preload()
|
||||||
urls[#urls + 1] = tostring(file.url)
|
urls[#urls + 1] = tostring(file.url)
|
||||||
end
|
end
|
||||||
|
|
||||||
local child, code = Command("file"):args({ "-bL", "--mime-type" }):args(urls):stdout(Command.PIPED):spawn()
|
local cmd = os.getenv("YAZI_FILE_ONE") or "file"
|
||||||
|
local child, code = Command(cmd):args({ "-bL", "--mime-type" }):args(urls):stdout(Command.PIPED):spawn()
|
||||||
if not child then
|
if not child then
|
||||||
ya.err("spawn `file` command returns " .. tostring(code))
|
ya.err(string.format("spawn `%s` command returns %s", cmd, code))
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ function M:seek(units)
|
||||||
local h = cx.active.current.hovered
|
local h = cx.active.current.hovered
|
||||||
if h and h.url == self.file.url then
|
if h and h.url == self.file.url then
|
||||||
local step = ya.clamp(-1, units, 1)
|
local step = ya.clamp(-1, units, 1)
|
||||||
ya.manager_emit("peek", { tostring(math.max(0, cx.active.preview.skip + step)), only_if = tostring(self.file.url) })
|
ya.manager_emit("peek", { math.max(0, cx.active.preview.skip + step), only_if = tostring(self.file.url) })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -37,7 +37,7 @@ function M:preload()
|
||||||
elseif not output.status:success() then
|
elseif not output.status:success() then
|
||||||
local pages = tonumber(output.stderr:match("the last page %((%d+)%)")) or 0
|
local pages = tonumber(output.stderr:match("the last page %((%d+)%)")) or 0
|
||||||
if self.skip > 0 and pages > 0 then
|
if self.skip > 0 and pages > 0 then
|
||||||
ya.manager_emit("peek", { tostring(math.max(0, pages - 1)), only_if = tostring(self.file.url), upper_bound = "" })
|
ya.manager_emit("peek", { math.max(0, pages - 1), only_if = tostring(self.file.url), upper_bound = true })
|
||||||
end
|
end
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue