diff --git a/.github/workflows/cachix.yml b/.github/workflows/cachix.yml index 2d1c89e3..193cbf3d 100644 --- a/.github/workflows/cachix.yml +++ b/.github/workflows/cachix.yml @@ -4,6 +4,9 @@ on: push: branches: [main] +permissions: + contents: read + jobs: publish: name: Publish Flake @@ -12,7 +15,7 @@ jobs: os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install Nix uses: cachix/install-nix-action@v31 diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 56e8e14d..3d363578 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -10,11 +10,14 @@ env: SCCACHE_GHA_ENABLED: true RUSTC_WRAPPER: sccache +permissions: + contents: read + jobs: clippy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Setup Rust toolchain run: | @@ -31,7 +34,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup Rust toolchain run: | @@ -47,7 +50,7 @@ jobs: stylua: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: JohnnyMorganz/stylua-action@v4 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/draft.yml b/.github/workflows/draft.yml index 15f6a43d..4df42b5b 100644 --- a/.github/workflows/draft.yml +++ b/.github/workflows/draft.yml @@ -9,6 +9,9 @@ on: env: SCCACHE_GHA_ENABLED: true +permissions: + contents: read + jobs: build-unix: strategy: @@ -39,7 +42,7 @@ jobs: CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_LINKER: sparc64-linux-gnu-gcc steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install gcc if: matrix.gcc != '' @@ -56,7 +59,7 @@ jobs: run: ./scripts/build.sh ${{ matrix.target }} - name: Upload artifact - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: ${{ matrix.target }} path: | @@ -78,7 +81,7 @@ jobs: CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER: lld-link.exe CARGO_TARGET_AARCH64_PC_WINDOWS_MSVC_LINKER: lld-link.exe steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: @@ -102,7 +105,7 @@ jobs: Compress-Archive -Path ${env:TARGET_NAME} -DestinationPath "${env:TARGET_NAME}.zip" - name: Upload artifact - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: ${{ matrix.target }} path: yazi-${{ matrix.target }}.zip @@ -117,7 +120,7 @@ jobs: container: image: docker://ghcr.io/cross-rs/${{ matrix.target }}:edge steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: @@ -130,7 +133,7 @@ jobs: run: ./scripts/build.sh ${{ matrix.target }} - name: Upload artifact - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: ${{ matrix.target }} path: | @@ -147,12 +150,12 @@ jobs: arch: arm64 runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Setup LXD - uses: canonical/setup-lxd@v0.1.3 + uses: canonical/setup-lxd@v1 - name: Setup snapcraft run: sudo snap install --classic snapcraft @@ -164,7 +167,7 @@ jobs: run: mv yazi_*.snap yazi-${{ matrix.arch }}.snap - name: Upload artifact - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: snap-${{ matrix.arch }} path: yazi-${{ matrix.arch }}.snap @@ -173,7 +176,7 @@ jobs: runs-on: ubuntu-latest needs: [build-snap] steps: - - uses: actions/download-artifact@v6 + - uses: actions/download-artifact@v7 with: pattern: snap-* merge-multiple: true @@ -202,7 +205,7 @@ jobs: runs-on: ubuntu-latest needs: [build-unix, build-windows, build-musl, build-snap] steps: - - uses: actions/download-artifact@v6 + - uses: actions/download-artifact@v7 with: merge-multiple: true @@ -227,11 +230,12 @@ jobs: echo 'NIGHTLY_BODY<> $GITHUB_ENV echo "From commit: ${GITHUB_SHA:0:8}" >> $GITHUB_ENV echo "Generated on: $(date -u +"%Y-%m-%d %H:%M") UTC" >> $GITHUB_ENV + echo "Nightly changelog: https://github.com/sxyazi/yazi/blob/main/CHANGELOG.md#unreleased" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - - uses: actions/download-artifact@v6 + - uses: actions/download-artifact@v7 with: merge-multiple: true diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 9d0819fe..a5a69e25 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -16,7 +16,7 @@ jobs: pull-requests: write discussions: write steps: - - uses: dessant/lock-threads@v5 + - uses: dessant/lock-threads@v6 with: issue-inactive-days: "30" issue-comment: > diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f7776fd3..624175c0 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,11 +4,14 @@ on: release: types: [published] +permissions: + contents: read + jobs: winget: runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v6 + - uses: actions/download-artifact@v7 with: merge-multiple: true @@ -19,6 +22,13 @@ jobs: installers-regex: 'yazi-(x86_64|aarch64)-pc-windows-msvc\.zip$' token: ${{ secrets.WINGET_TOKEN }} + snapcraft: + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v7 + with: + merge-multiple: true + - name: Promote snap to stable env: SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e524a55a..5072fb74 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,6 +11,9 @@ env: RUSTC_WRAPPER: sccache CARGO_TERM_COLOR: always +permissions: + contents: read + jobs: test: strategy: @@ -18,7 +21,7 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Setup Rust toolchain run: rustup toolchain install stable --profile minimal diff --git a/.github/workflows/validate-form.yml b/.github/workflows/validate-form.yml index 2d48f16a..b9416d4b 100644 --- a/.github/workflows/validate-form.yml +++ b/.github/workflows/validate-form.yml @@ -12,7 +12,7 @@ jobs: permissions: issues: write steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Setup Node.js uses: actions/setup-node@v6 diff --git a/CHANGELOG.md b/CHANGELOG.md index 28c2366d..84dfe251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,16 +12,33 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): ## [Unreleased] +## [v26.1.4] + ### Added -- Remote file management ([#3166], [#3170], [#3172], [#3198], [#3201], [#3243], [#3264], [#3268]) +- Support VFS for preset previewers that rely on external commands ([#3477]) +- Support 8-bit images in RGB, CIELAB, and GRAY color spaces ([#3358]) + +### Fixed + +- `ya pkg` fails to write `package.toml` when the config directory does not exist ([#3482]) +- A race condition generating unique filenames for concurrent file operations ([#3494]) + +## [v25.12.29] + +### Added + +- Remote file management ([#3396]) - Virtual file system ([#3034], [#3035], [#3094], [#3108], [#3187], [#3203]) - Shell formatting ([#3232]) - Multi-entry support for plugin system ([#3154]) - Zoom in or out of the preview image ([#2864]) - Improve the UX of the pick and input components ([#2906], [#2935]) - Show progress of each task in task manager ([#3121], [#3131], [#3134]) +- New `fs.copy()` and `fs.rename()` APIs ([#3467]) +- New experimental `ya.async()` API ([#3422]) - New `overall` option to set the overall background color ([#3317]) +- Rounded corners for indicator bar ([#3419]) - New `bulk_rename` command always renames files with the editor ([#2984]) - `key-*` DDS events to allow changing or canceling user key events ([#3005], [#3037]) - New `--bg` specifying image background color in the preset SVG and ImageMagick previewers ([#3189]) @@ -30,12 +47,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): - Allow dynamic adjustment of layout ratio via `rt.mgr.ratio` ([#2964]) - Support `.deb` packages ([#2807], [#3128], [#3209]) - Port several widespread GUI keys to the input component ([#2849]) -- Support invalid UTF-8 paths throughout the codebase ([#2884], [#2889], [#2890], [#2895], [#3023], [#3290]) +- Support invalid UTF-8 paths throughout the codebase ([#2884], [#2889], [#2890], [#2895], [#3023], [#3290], [#3369]) - Allow upgrading only specific packages with `ya pkg` ([#2841]) - Respect the user's `image_filter` setting in the preset ImageMagick previewer ([#3286]) +- New `duplicate` DDS event for copying files ([#3456]) +- New `ind-sort` and `key-sort` DDS events to change sorting in Lua ([#3391]) - Allow custom mouse click behavior for individual files ([#2925]) - Display newlines in input as spaces to improve readability ([#2932]) -- Fill in error messages if preview fails ([#2917]) +- Fill in error messages if preview fails ([#2917], [#3383], [#3387]) - Search view shares file selection and yank state ([#2855]) - Offload mimetype fetching on opening files to the task scheduler ([#3141]) - Increase terminal response timeout to better tolerate slow SSH network environments ([#2843]) @@ -44,7 +63,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): - Rename `name` to `url` for open, fetchers, spotters, preloaders, previewers, filetype, and `globs` icon rules to support virtual file system ([#3034]) - Rename `mime` fetcher to `mime.local`, and introduce `mime.dir` fetcher to support folder MIME types ([#3222]) +- Reclassify `hovered` and `preview_hovered` under `[mgr]` of `theme.toml` into `[indicator]` as `current` and `preview`, respectively ([#3419]) - Remove `$0` parameter in opener rules to make the `open` command work under empty directories ([#3226]) +- Return `Path` instead of `Url` from `Url:strip_prefix()` and `File.link_to` to enforce type safety ([#3361], [#3385]) - Use `body` instead of the term `content` in confirmations ([#2921]) - Use `u16` instead of `u32` as the type of `max_width` and `max_height` options to avoid memory exhaustion ([#3313]) - Implement `__pairs` metamethod instead of `__index` for the callback argument of the `@yank` DDS event ([#2997]) @@ -60,6 +81,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): ### Fixed +- User-prepended open rules do not override presets ([#3360]) - Respect user's system media opener instead of hardcoding `mpv` ([#2959]) - Incorrect `$0` and `$@` parameters in `shell` command under empty directories ([#3225]) - Avoid appending a newline when reading clipboard contents ([#3059]) @@ -71,14 +93,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): - Force Git checkout for plugin cache repositories ([#3169]) - Check compatibility when reusing previewer bytecode cache ([#3190]) - Disable kitty keyboard protocol on Windows due to `crossterm` inability to handle it ([#3250]) +- Prevent quotes in file(1) arguments from being stripped under MSYS2 ([#3364]) - Expose `ya` CLI in the Snap build ([#2904]) - Fallback to `PollWatcher` for file changes watching on NetBSD ([#2941]) - Generate unique image IDs for Kgp to tolerate tmux ([#3038]) ### Improved +- Make copy, cut, delete, link, hardlink, download, and upload tasks immediately cancellable ([#3429]) - Make preload tasks discardable ([#2875]) - Reduce file change event frequency ([#2820]) +- Upload and download of a single file over SFTP in chunks concurrently ([#3393]) - Do not listen for file changes in inactive tabs ([#2958]) - Switch to a higher-performance hash algorithm ([#3083]) - Sequence-based rendering merge strategy ([#2861]) @@ -776,7 +801,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): - Show keywords when in search mode ([#152]) - Tab switch wraparound ([#160]) - Highlight matched keywords in find mode ([#211]) -- Customable main UI border styles ([#278]) +- Customizable main UI border styles ([#278]) - `` key notion ([#209]) - Use of environment variables in `cd` paths ([#241]) - Nix Flakes package ([#205]) @@ -962,6 +987,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): [v25.4.8]: https://github.com/sxyazi/yazi/compare/v25.3.2...v25.4.8 [v25.5.28]: https://github.com/sxyazi/yazi/compare/v25.4.8...v25.5.28 [v25.5.31]: https://github.com/sxyazi/yazi/compare/v25.5.28...v25.5.31 +[v25.12.29]: https://github.com/sxyazi/yazi/compare/v25.5.31...v25.12.29 +[v26.1.4]: https://github.com/sxyazi/yazi/compare/v25.12.29...v26.1.4 [#4]: https://github.com/sxyazi/yazi/pull/4 [#5]: https://github.com/sxyazi/yazi/pull/5 [#6]: https://github.com/sxyazi/yazi/pull/6 @@ -1537,3 +1564,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): [#3290]: https://github.com/sxyazi/yazi/pull/3290 [#3313]: https://github.com/sxyazi/yazi/pull/3313 [#3317]: https://github.com/sxyazi/yazi/pull/3317 +[#3358]: https://github.com/sxyazi/yazi/pull/3358 +[#3360]: https://github.com/sxyazi/yazi/pull/3360 +[#3361]: https://github.com/sxyazi/yazi/pull/3361 +[#3364]: https://github.com/sxyazi/yazi/pull/3364 +[#3369]: https://github.com/sxyazi/yazi/pull/3369 +[#3383]: https://github.com/sxyazi/yazi/pull/3383 +[#3385]: https://github.com/sxyazi/yazi/pull/3385 +[#3387]: https://github.com/sxyazi/yazi/pull/3387 +[#3391]: https://github.com/sxyazi/yazi/pull/3391 +[#3393]: https://github.com/sxyazi/yazi/pull/3393 +[#3396]: https://github.com/sxyazi/yazi/pull/3396 +[#3419]: https://github.com/sxyazi/yazi/pull/3419 +[#3422]: https://github.com/sxyazi/yazi/pull/3422 +[#3429]: https://github.com/sxyazi/yazi/pull/3429 +[#3456]: https://github.com/sxyazi/yazi/pull/3456 +[#3467]: https://github.com/sxyazi/yazi/pull/3467 +[#3477]: https://github.com/sxyazi/yazi/pull/3477 +[#3482]: https://github.com/sxyazi/yazi/pull/3482 +[#3494]: https://github.com/sxyazi/yazi/pull/3494 diff --git a/Cargo.lock b/Cargo.lock index 21bc9c78..b0184377 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,8 +23,8 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", - "generic-array", + "crypto-common 0.1.7", + "generic-array 0.14.7", ] [[package]] @@ -61,6 +61,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + [[package]] name = "aligned-vec" version = "0.6.4" @@ -87,15 +96,15 @@ dependencies = [ [[package]] name = "ansi-to-tui" -version = "7.0.0" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67555e1f1ece39d737e28c8a017721287753af3f93225e4a445b29ccb0f5912c" +checksum = "fdfd3cbf4843347ca072771a797484f1c3434a14d57f39d31c92dfb93a8799a8" dependencies = [ - "nom 7.1.3", - "ratatui", + "nom 8.0.0", + "ratatui-core", "simdutf8", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.17", ] [[package]] @@ -130,22 +139,22 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -154,15 +163,6 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - [[package]] name = "arbitrary" version = "1.4.2" @@ -171,9 +171,12 @@ checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" [[package]] name = "arc-swap" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +checksum = "51d03449bb8ca2cc2ef70869af31463d1ae5ccc8fa3e334b307203fbf815207e" +dependencies = [ + "rustversion", +] [[package]] name = "arg_enum_proc_macro" @@ -183,7 +186,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -204,6 +207,15 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "async-priority-channel" version = "0.2.0" @@ -213,12 +225,41 @@ dependencies = [ "event-listener", ] +[[package]] +name = "atomic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +dependencies = [ + "bytemuck", +] + [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.17", + "v_frame", + "y4m", +] + [[package]] name = "av1-grain" version = "0.2.5" @@ -254,7 +295,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -263,6 +304,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base16ct" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" + [[package]] name = "base64" version = "0.22.1" @@ -271,9 +318,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "7d809780667f4410e7c41b07f52439b94d2bdf8528eeedc287fa38d3b7f95d82" [[package]] name = "bcrypt-pbkdf" @@ -283,7 +330,7 @@ checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2" dependencies = [ "blowfish", "pbkdf2", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -305,6 +352,21 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bit_field" version = "0.10.3" @@ -328,9 +390,12 @@ dependencies = [ [[package]] name = "bitstream-io" -version = "2.6.0" +version = "4.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" +checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" +dependencies = [ + "core2", +] [[package]] name = "bitvec" @@ -350,7 +415,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -359,7 +424,16 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", +] + +[[package]] +name = "block-buffer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96eb4cdd6cf1b31d671e9efe75c5d1ec614776856cefbe109ca373554a6d514f" +dependencies = [ + "hybrid-array", ] [[package]] @@ -368,7 +442,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -393,15 +467,15 @@ dependencies = [ [[package]] name = "built" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "by_address" @@ -414,6 +488,20 @@ name = "bytemuck" version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", +] [[package]] name = "byteorder" @@ -429,15 +517,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" - -[[package]] -name = "cassowary" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "castaway" @@ -459,9 +541,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.44" +version = "1.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" +checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" dependencies = [ "find-msvc-tools", "jobserver", @@ -469,16 +551,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", -] - [[package]] name = "cfg-if" version = "1.0.4" @@ -512,7 +584,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -521,15 +593,15 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "inout", ] [[package]] name = "clap" -version = "4.5.51" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -537,9 +609,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.51" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -549,9 +621,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.60" +version = "4.5.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e602857739c5a4291dfa33b5a298aeac9006185229a700e5810a3ef7272d971" +checksum = "4c0da80818b2d95eca9aa614a30783e42f62bf5fdfee24e68cfb960b071ba8d1" dependencies = [ "clap", ] @@ -585,7 +657,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -603,6 +675,12 @@ dependencies = [ "error-code", ] +[[package]] +name = "cmov" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11ed919bd3bae4af5ab56372b627dfc32622aba6cec36906e8ab46746037c9d" + [[package]] name = "color_quant" version = "1.1.0" @@ -617,15 +695,16 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "compact_str" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32" +checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" dependencies = [ "castaway", "cfg-if", "itoa", "rustversion", "ryu", + "serde", "static_assertions", ] @@ -657,10 +736,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] -name = "convert_case" -version = "0.7.1" +name = "const-oid" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ "unicode-segmentation", ] @@ -673,15 +758,24 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-models" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94950e87ea550d6d68f1993f3e7bebc8cb7235157bff84337d46195c3aa0b3f0" +checksum = "0940496e5c83c54f3b753d5317daec82e8edac71c33aaa1f666d76f518de2444" dependencies = [ "hax-lib", "pastey", "rand 0.9.2", ] +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -745,7 +839,8 @@ dependencies = [ "mio", "parking_lot", "rustix 0.38.44", - "signal-hook", + "serde", + "signal-hook 0.3.18", "signal-hook-mio", "winapi", ] @@ -765,8 +860,9 @@ dependencies = [ "libc", "mio", "parking_lot", - "rustix 1.1.2", - "signal-hook", + "rustix 1.1.3", + "serde", + "signal-hook 0.3.18", "signal-hook-mio", "winapi", ] @@ -792,22 +888,65 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core 0.6.4", "subtle", "zeroize", ] [[package]] -name = "crypto-common" -version = "0.1.6" +name = "crypto-bigint" +version = "0.7.0-rc.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "b2bb4138de6db76c8155b4423e967049fbef2cf84ad6af7f552f73a161941b72" dependencies = [ - "generic-array", + "ctutils", + "num-traits", + "rand_core 0.10.0-rc-3", + "serdect", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array 0.14.7", "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.0-rc.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6165b8029cdc3e765b74d3548f85999ee799d5124877ce45c2c85ca78e4d4aa" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "crypto-primes" +version = "0.7.0-pre.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0b07a7a616370e8b6efca0c6a25e5f4c6d02fde11f3d570e4af64d8ed7e2e9" +dependencies = [ + "crypto-bigint 0.7.0-rc.13", + "libm", + "rand_core 0.10.0-rc-3", +] + +[[package]] +name = "csscolorparser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" +dependencies = [ + "lab", + "phf", +] + [[package]] name = "ctr" version = "0.9.2" @@ -817,6 +956,15 @@ dependencies = [ "cipher", ] +[[package]] +name = "ctutils" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c67c81499f542d1dd38c6a2a2fe825f4dd4bca5162965dd2eea0c8119873d3c" +dependencies = [ + "cmov", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -826,7 +974,7 @@ dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "digest", + "digest 0.10.7", "fiat-crypto", "rustc_version", "subtle", @@ -841,7 +989,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -850,8 +998,18 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] @@ -865,7 +1023,20 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.113", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.113", ] [[package]] @@ -874,9 +1045,20 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core", + "darling_core 0.20.11", "quote", - "syn", + "syn 2.0.113", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", + "quote", + "syn 2.0.113", ] [[package]] @@ -908,23 +1090,40 @@ dependencies = [ [[package]] name = "delegate" -version = "0.13.4" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6178a82cf56c836a3ba61a7935cdb1c49bfaa6fa4327cd5bf554a503087de26b" +checksum = "780eb241654bf097afb00fc5f054a09b687dad862e485fdcf8399bb056565370" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] +[[package]] +name = "deltae" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" + [[package]] name = "der" version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid", - "pem-rfc7468", + "const-oid 0.9.6", + "pem-rfc7468 0.7.0", + "zeroize", +] + +[[package]] +name = "der" +version = "0.8.0-rc.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c1d73e9668ea6b6a28172aa55f3ebec38507131ce179051c8033b5c6037653" +dependencies = [ + "const-oid 0.10.1", + "pem-rfc7468 1.0.0", "zeroize", ] @@ -952,10 +1151,10 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ - "darling", + "darling 0.20.11", "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -965,28 +1164,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn", + "syn 2.0.113", ] [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", "quote", - "syn", + "rustc_version", + "syn 2.0.113", ] [[package]] @@ -995,12 +1195,23 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", + "block-buffer 0.10.4", + "const-oid 0.9.6", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "digest" +version = "0.11.0-rc.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebf9423bafb058e4142194330c52273c343f8a5beb7176d052f0e73b17dd35b9" +dependencies = [ + "block-buffer 0.11.0", + "const-oid 0.10.1", + "crypto-common 0.2.0-rc.8", +] + [[package]] name = "dirs" version = "6.0.0" @@ -1037,12 +1248,12 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der", - "digest", + "der 0.7.10", + "digest 0.10.7", "elliptic-curve", "rfc6979", - "signature", - "spki", + "signature 2.2.0", + "spki 0.7.3", ] [[package]] @@ -1051,8 +1262,8 @@ version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "pkcs8", - "signature", + "pkcs8 0.10.2", + "signature 2.2.0", ] [[package]] @@ -1065,7 +1276,7 @@ dependencies = [ "ed25519", "rand_core 0.6.4", "serde", - "sha2", + "sha2 0.10.9", "subtle", "zeroize", ] @@ -1082,15 +1293,15 @@ version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base16ct", - "crypto-bigint", - "digest", + "base16ct 0.2.0", + "crypto-bigint 0.5.5", + "digest 0.10.7", "ff", - "generic-array", + "generic-array 0.14.7", "group", "hkdf", - "pem-rfc7468", - "pkcs8", + "pem-rfc7468 0.7.0", + "pkcs8 0.10.2", "rand_core 0.6.4", "sec1", "subtle", @@ -1112,7 +1323,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -1138,7 +1349,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -1149,9 +1360,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" +checksum = "89e8918065695684b2b0702da20382d5ae6065cf3327bc2d6436bd49a71ce9f3" dependencies = [ "serde", "serde_core", @@ -1174,6 +1385,15 @@ version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" +[[package]] +name = "euclid" +version = "0.22.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +dependencies = [ + "num-traits", +] + [[package]] name = "event-listener" version = "4.0.3" @@ -1187,19 +1407,28 @@ dependencies = [ [[package]] name = "exr" -version = "1.73.0" +version = "1.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" dependencies = [ "bit_field", "half", "lebe", "miniz_oxide", - "rayon-core", "smallvec", "zune-inflate", ] +[[package]] +name = "fancy-regex" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set", + "regex", +] + [[package]] name = "fast-srgb8" version = "1.0.0" @@ -1254,9 +1483,21 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" +checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" + +[[package]] +name = "finl_unicode" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9844ddc3a6e533d62bba727eb6c28b5d360921d5175e9ff0f1e621a5c590a4d5" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" @@ -1274,12 +1515,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "foldhash" version = "0.2.0" @@ -1357,7 +1592,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -1392,15 +1627,26 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.9" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", "zeroize", ] +[[package]] +name = "generic-array" +version = "1.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf57c49a95fd1fe24b90b3033bee6dc7e8f1288d51494cb44e627c295e38542" +dependencies = [ + "generic-array 0.14.7", + "rustversion", + "typenum", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -1438,9 +1684,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.13.3" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" +checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e" dependencies = [ "color_quant", "weezl", @@ -1489,25 +1735,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash 0.1.5", -] - -[[package]] -name = "hashbrown" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", + "foldhash", "serde", + "serde_core", ] [[package]] @@ -1531,7 +1767,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -1586,7 +1822,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -1598,6 +1834,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "hybrid-array" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +dependencies = [ + "typenum", +] + [[package]] name = "iana-time-zone" version = "0.1.64" @@ -1630,9 +1875,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "image" -version = "0.25.8" +version = "0.25.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" +checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" dependencies = [ "bytemuck", "byteorder-lite", @@ -1668,12 +1913,12 @@ checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" [[package]] name = "indexmap" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", - "hashbrown 0.16.0", + "hashbrown", "serde", "serde_core", ] @@ -1714,30 +1959,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "block-padding", - "generic-array", + "generic-array 0.14.7", ] [[package]] name = "instability" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435d80800b936787d62688c927b6490e887c7ef5ff9ce922c6c6050fca75eb9a" +checksum = "357b7205c6cd18dd2c86ed312d1e70add149aea98e7ef72b9fdf0270e555c11d" dependencies = [ - "darling", + "darling 0.23.0", "indoc", "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] name = "internal-russh-forked-ssh-key" -version = "0.6.11+upstream-0.6.7" +version = "0.6.16+upstream-0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a77eae781ed6a7709fb15b64862fcca13d886b07c7e2786f5ed34e5e2b9187" +checksum = "fe44f2bbd99fcb302e246e2d6bcf51aeda346d02a365f80296a07a8c711b6da6" dependencies = [ "argon2", "bcrypt-pbkdf", + "digest 0.11.0-rc.5", "ecdsa", "ed25519-dalek", "hex", @@ -1749,9 +1995,11 @@ dependencies = [ "rand_core 0.6.4", "rsa", "sec1", - "sha1", - "sha2", - "signature", + "sha1 0.10.6", + "sha1 0.11.0-rc.3", + "sha2 0.10.9", + "signature 2.2.0", + "signature 3.0.0-rc.6", "ssh-cipher", "ssh-encoding", "subtle", @@ -1766,7 +2014,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -1775,15 +2023,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -1804,9 +2043,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jobserver" @@ -1820,14 +2059,25 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.82" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", ] +[[package]] +name = "kasuari" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fe90c1150662e858c7d5f945089b7517b0a80d8bf7ba4b1b5ffc984e7230a5b" +dependencies = [ + "hashbrown", + "portable-atomic", + "thiserror 2.0.17", +] + [[package]] name = "kqueue" version = "1.1.1" @@ -1848,6 +2098,12 @@ dependencies = [ "libc", ] +[[package]] +name = "lab" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" + [[package]] name = "lazy_static" version = "1.5.0" @@ -1865,15 +2121,15 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" -version = "0.2.177" +version = "0.2.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" [[package]] name = "libcrux-intrinsics" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3b41dcbc21a5fb7efbbb5af7405b2e79c4bfe443924e90b13afc0080318d31" +checksum = "bc9ee7ef66569dd7516454fe26de4e401c0c62073929803486b96744594b9632" dependencies = [ "core-models", "hax-lib", @@ -1881,16 +2137,18 @@ dependencies = [ [[package]] name = "libcrux-ml-kem" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d368d3e8d6a74e277178d54921eca112a1e6b7837d7d8bc555091acb5d817f5" +checksum = "4bb6a88086bf11bd2ec90926c749c4a427f2e59841437dbdede8cde8a96334ab" dependencies = [ "hax-lib", "libcrux-intrinsics", "libcrux-platform", "libcrux-secrets", "libcrux-sha3", + "libcrux-traits", "rand 0.9.2", + "tls_codec", ] [[package]] @@ -1904,22 +2162,33 @@ dependencies = [ [[package]] name = "libcrux-secrets" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332737e629fe6ba7547f5c0f90559eac865d5dbecf98138ffae8f16ab8cbe33f" +checksum = "6e4dbbf6bc9f2bc0f20dc3bea3e5c99adff3bdccf6d2a40488963da69e2ec307" dependencies = [ "hax-lib", ] [[package]] name = "libcrux-sha3" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d95de4257eafdfaf3bffecadb615219b0ca920c553722b3646d32dde76c797" +checksum = "2400bec764d1c75b8a496d5747cffe32f1fb864a12577f0aca2f55a92021c962" dependencies = [ "hax-lib", "libcrux-intrinsics", "libcrux-platform", + "libcrux-traits", +] + +[[package]] +name = "libcrux-traits" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9adfd58e79d860f6b9e40e35127bfae9e5bd3ade33201d1347459011a2add034" +dependencies = [ + "libcrux-secrets", + "rand 0.9.2", ] [[package]] @@ -1940,14 +2209,23 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags 2.10.0", "libc", ] +[[package]] +name = "line-clipping" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4de44e98ddbf09375cbf4d17714d18f39195f4f4894e8524501726fd9a8a4a" +dependencies = [ + "bitflags 2.10.0", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -1977,9 +2255,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "loop9" @@ -1990,22 +2268,13 @@ dependencies = [ "imgref", ] -[[package]] -name = "lru" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" -dependencies = [ - "hashbrown 0.15.5", -] - [[package]] name = "lru" version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" dependencies = [ - "hashbrown 0.16.0", + "hashbrown", ] [[package]] @@ -2019,14 +2288,24 @@ dependencies = [ [[package]] name = "luajit-src" -version = "210.6.2+25a61a1" +version = "210.6.5+7152e15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b3e51e810ed7940b3d057d4cb63ef5faa8261fc8f46fb1905947a22f1c89ec" +checksum = "29e64ac463f01a02ee793423f9b351369cf244c5ee8bb9e2729a75b2eb404181" dependencies = [ "cc", "which", ] +[[package]] +name = "mac_address" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303" +dependencies = [ + "nix", + "winapi", +] + [[package]] name = "matchers" version = "0.2.0" @@ -2057,6 +2336,21 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +[[package]] +name = "memmem" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -2075,9 +2369,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "log", @@ -2087,15 +2381,16 @@ dependencies = [ [[package]] name = "mlua" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be1c2bfc684b8a228fbaebf954af7a47a98ec27721986654a4cc2c40a20cc7e" +checksum = "935ac67539907efcd7198137eb7358e052555f77fe1b2916600a2249351f2b33" dependencies = [ "anyhow", "bstr", "either", "erased-serde", "futures-util", + "libc", "mlua-sys", "mlua_derive", "num-traits", @@ -2108,9 +2403,9 @@ dependencies = [ [[package]] name = "mlua-sys" -version = "0.8.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4dc9cfc5a7698899802e97480617d9726f7da78c910db989d4d0fd4991d900" +checksum = "8c968af21bf6b19fc9ca8e7b85ee16f86e4c9e3d0591de101a5608086bda0ad8" dependencies = [ "cc", "cfg-if", @@ -2131,14 +2426,14 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn", + "syn 2.0.113", ] [[package]] name = "moxcms" -version = "0.7.9" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fbdd3d7436f8b5e892b8b7ea114271ff0fa00bc5acae845d53b07d498616ef6" +checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" dependencies = [ "num-traits", "pxfm", @@ -2160,6 +2455,7 @@ dependencies = [ "cfg-if", "cfg_aliases", "libc", + "memoffset", ] [[package]] @@ -2233,9 +2529,9 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c79c15c05d4bf82b6f5ef163104cc81a760d8e874d38ac50ab67c8877b647b" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" dependencies = [ "lazy_static", "libm", @@ -2243,8 +2539,8 @@ dependencies = [ "num-iter", "num-traits", "rand 0.8.5", + "serde", "smallvec", - "zeroize", ] [[package]] @@ -2261,7 +2557,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -2324,6 +2620,12 @@ dependencies = [ "libc", ] +[[package]] +name = "numtoa" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f" + [[package]] name = "objc2" version = "0.6.3" @@ -2442,7 +2744,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -2454,7 +2756,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -2463,19 +2765,19 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" dependencies = [ - "base16ct", + "base16ct 0.2.0", "ecdsa", "elliptic-curve", "primeorder", "rand_core 0.6.4", - "sha2", + "sha2 0.10.9", ] [[package]] name = "pageant" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb28bd89a207e5cad59072ac4b364b08459d05f90ccfbcdaa920a95857d94430" +checksum = "1b537f975f6d8dcf48db368d7ec209d583b015713b5df0f5d92d2631e4ff5595" dependencies = [ "byteorder", "bytes", @@ -2483,9 +2785,11 @@ dependencies = [ "futures", "log", "rand 0.8.5", + "sha2 0.10.9", "thiserror 1.0.69", "tokio", - "windows 0.59.0", + "windows 0.62.2", + "windows-strings", ] [[package]] @@ -2494,8 +2798,9 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" dependencies = [ - "approx", + "bytemuck", "fast-srgb8", + "libm", "palette_derive", ] @@ -2508,7 +2813,7 @@ dependencies = [ "by_address", "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -2537,7 +2842,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -2569,7 +2874,7 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ - "digest", + "digest 0.10.7", "hmac", ] @@ -2582,12 +2887,116 @@ dependencies = [ "base64ct", ] +[[package]] +name = "pem-rfc7468" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] +name = "pest_meta" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365" +dependencies = [ + "pest", + "sha2 0.10.9", +] + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -2602,13 +3011,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs1" -version = "0.7.5" +version = "0.8.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +checksum = "986d2e952779af96ea048f160fd9194e1751b4faea78bcf3ceb456efe008088e" dependencies = [ - "der", - "pkcs8", - "spki", + "der 0.8.0-rc.10", + "spki 0.8.0-rc.4", ] [[package]] @@ -2619,11 +3027,11 @@ checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" dependencies = [ "aes", "cbc", - "der", + "der 0.7.10", "pbkdf2", "scrypt", - "sha2", - "spki", + "sha2 0.10.9", + "spki 0.7.3", ] [[package]] @@ -2632,10 +3040,20 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der", + "der 0.7.10", "pkcs5", "rand_core 0.6.4", - "spki", + "spki 0.7.3", +] + +[[package]] +name = "pkcs8" +version = "0.11.0-rc.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77089aec8290d0b7bb01b671b091095cf1937670725af4fd73d47249f03b12c0" +dependencies = [ + "der 0.8.0-rc.10", + "spki 0.8.0-rc.4", ] [[package]] @@ -2693,6 +3111,12 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" + [[package]] name = "powerfmt" version = "0.2.0" @@ -2736,14 +3160,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" dependencies = [ "unicode-ident", ] @@ -2764,14 +3188,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" dependencies = [ "quote", - "syn", + "syn 2.0.113", ] [[package]] name = "pxfm" -version = "0.1.25" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cbdf373972bf78df4d3b518d07003938e2c7d1fb5891e55f9cb6df57009d84" +checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8" dependencies = [ "num-traits", ] @@ -2787,14 +3211,17 @@ dependencies = [ [[package]] name = "quantette" -version = "0.3.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3ba8b34ab55d43cea1f7c183ef3c124cb96fe935c6ec5c6d97127ee340c96e" +checksum = "c98fecda8b16396ff9adac67644a523dd1778c42b58606a29df5c31ca925d174" dependencies = [ "bitvec", + "bytemuck", + "libm", "num-traits", - "ordered-float 4.6.0", + "ordered-float 5.1.0", "palette", + "ref-cast", "wide", ] @@ -2806,18 +3233,18 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.38.3" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -2896,41 +3323,129 @@ dependencies = [ ] [[package]] -name = "ratatui" -version = "0.29.0" +name = "rand_core" +version = "0.10.0-rc-3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" +checksum = "f66ee92bc15280519ef199a274fe0cafff4245d31bc39aaa31c011ad56cb1f05" + +[[package]] +name = "ratatui" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc" +dependencies = [ + "instability", + "ratatui-core", + "ratatui-crossterm", + "ratatui-macros", + "ratatui-termion", + "ratatui-termwiz", + "ratatui-widgets", + "serde", +] + +[[package]] +name = "ratatui-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" dependencies = [ "bitflags 2.10.0", - "cassowary", "compact_str", - "crossterm 0.28.1", + "hashbrown", "indoc", - "instability", - "itertools 0.13.0", - "lru 0.12.5", - "paste", + "itertools 0.14.0", + "kasuari", + "lru", + "serde", "strum", + "thiserror 2.0.17", "unicode-segmentation", "unicode-truncate", - "unicode-width 0.2.0", + "unicode-width", +] + +[[package]] +name = "ratatui-crossterm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" +dependencies = [ + "cfg-if", + "crossterm 0.28.1", + "crossterm 0.29.0", + "instability", + "ratatui-core", +] + +[[package]] +name = "ratatui-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7f1342a13e83e4bb9d0b793d0ea762be633f9582048c892ae9041ef39c936f4" +dependencies = [ + "ratatui-core", + "ratatui-widgets", +] + +[[package]] +name = "ratatui-termion" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cade85a8591fbc911e147951422f0d6fd40f4948b271b6216c7dc01838996f8" +dependencies = [ + "instability", + "ratatui-core", + "termion", +] + +[[package]] +name = "ratatui-termwiz" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f76fe0bd0ed4295f0321b1676732e2454024c15a35d01904ddb315afd3d545c" +dependencies = [ + "ratatui-core", + "termwiz", +] + +[[package]] +name = "ratatui-widgets" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" +dependencies = [ + "bitflags 2.10.0", + "hashbrown", + "indoc", + "instability", + "itertools 0.14.0", + "line-clipping", + "ratatui-core", + "serde", + "strum", + "time", + "unicode-segmentation", + "unicode-width", ] [[package]] name = "rav1e" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" dependencies = [ + "aligned-vec", "arbitrary", "arg_enum_proc_macro", "arrayvec", + "av-scenechange", "av1-grain", "bitstream-io", "built", "cfg-if", "interpolate_name", - "itertools 0.12.1", + "itertools 0.14.0", "libc", "libfuzzer-sys", "log", @@ -2939,23 +3454,21 @@ dependencies = [ "noop_proc_macro", "num-derive", "num-traits", - "once_cell", "paste", "profiling", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand 0.9.2", + "rand_chacha 0.9.0", "simd_helpers", - "system-deps", - "thiserror 1.0.69", + "thiserror 2.0.17", "v_frame", "wasm-bindgen", ] [[package]] name = "ravif" -version = "0.11.20" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" +checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285" dependencies = [ "avif-serialize", "imgref", @@ -2965,6 +3478,16 @@ dependencies = [ "rgb", ] +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + [[package]] name = "rayon-core" version = "1.13.0" @@ -2995,6 +3518,26 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", +] + [[package]] name = "regex" version = "1.12.2" @@ -3056,33 +3599,30 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.8" +version = "0.10.0-rc.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +checksum = "d27d813937fdf8e9ad15e3e422a55da4021d29639000139ca19d99f3949060da" dependencies = [ - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-traits", + "const-oid 0.10.1", + "crypto-bigint 0.7.0-rc.13", + "crypto-primes", + "digest 0.11.0-rc.5", "pkcs1", - "pkcs8", - "rand_core 0.6.4", - "sha2", - "signature", - "spki", - "subtle", + "pkcs8 0.11.0-rc.8", + "rand_core 0.10.0-rc-3", + "sha2 0.11.0-rc.3", + "signature 3.0.0-rc.6", + "spki 0.8.0-rc.4", "zeroize", ] [[package]] name = "russh" -version = "0.54.6" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ca8e9091b72afdc9979bddcd1988ad898fa7bc0b85c8da8c154c29d44319eb" +checksum = "bdbb7dcdd62c17ac911307ff693f55b3ec6712004d2d66ffdb8c0fa00269fd66" dependencies = [ "aes", - "base64ct", "bitflags 2.10.0", "block-padding", "byteorder", @@ -3092,14 +3632,14 @@ dependencies = [ "curve25519-dalek", "data-encoding", "delegate", - "der", - "digest", + "der 0.7.10", + "digest 0.10.7", "ecdsa", "ed25519-dalek", "elliptic-curve", "enum_dispatch", "futures", - "generic-array", + "generic-array 1.3.5", "getrandom 0.2.16", "hex-literal", "hmac", @@ -3110,7 +3650,6 @@ dependencies = [ "log", "md5", "num-bigint", - "once_cell", "p256", "p384", "p521", @@ -3118,7 +3657,7 @@ dependencies = [ "pbkdf2", "pkcs1", "pkcs5", - "pkcs8", + "pkcs8 0.10.2", "rand 0.8.5", "rand_core 0.6.4", "ring", @@ -3126,10 +3665,10 @@ dependencies = [ "russh-cryptovec", "russh-util", "sec1", - "sha1", - "sha2", - "signature", - "spki", + "sha1 0.10.6", + "sha2 0.10.9", + "signature 2.2.0", + "spki 0.7.3", "ssh-encoding", "subtle", "thiserror 1.0.69", @@ -3199,9 +3738,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags 2.10.0", "errno", @@ -3218,15 +3757,15 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "safe_arch" -version = "0.7.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +checksum = "629516c85c29fe757770fa03f2074cf1eac43d44c02a3de9fc2ef7b0e207dfdd" dependencies = [ "bytemuck", ] @@ -3263,7 +3802,7 @@ checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" dependencies = [ "pbkdf2", "salsa20", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -3272,10 +3811,10 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", + "base16ct 0.2.0", + "der 0.7.10", + "generic-array 0.14.7", + "pkcs8 0.10.2", "subtle", "zeroize", ] @@ -3323,38 +3862,39 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] name = "serde_spanned" -version = "0.6.9" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" dependencies = [ - "serde", + "serde_core", ] [[package]] -name = "serde_spanned" -version = "1.0.3" +name = "serdect" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +checksum = "9af4a3e75ebd5599b30d4de5768e00b5095d518a79fefc3ecbaf77e665d1ec06" dependencies = [ - "serde_core", + "base16ct 1.0.0", + "serde", ] [[package]] @@ -3365,7 +3905,18 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha1" +version = "0.11.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa1ae819b9870cadc959a052363de870944a1646932d274a4e270f64bf79e5ef" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.11.0-rc.5", ] [[package]] @@ -3376,7 +3927,18 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.11.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d43dc0354d88b791216bb5c1bfbb60c0814460cc653ae0ebd71f286d0bd927" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.11.0-rc.5", ] [[package]] @@ -3404,6 +3966,16 @@ dependencies = [ "signal-hook-registry", ] +[[package]] +name = "signal-hook" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a37d01603c37b5466f808de79f845c7116049b0579adb70a6b7d47c1fa3a952" +dependencies = [ + "libc", + "signal-hook-registry", +] + [[package]] name = "signal-hook-mio" version = "0.2.5" @@ -3412,27 +3984,28 @@ checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", "mio", - "signal-hook", + "signal-hook 0.3.18", ] [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] [[package]] name = "signal-hook-tokio" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213241f76fb1e37e27de3b6aa1b068a2c333233b59cca6634f634b80a27ecf1e" +checksum = "e513e435a8898a0002270f29d0a708b7879708fb5c4d00e46983ca2d2d378cf0" dependencies = [ "futures-core", "libc", - "signal-hook", + "signal-hook 0.4.1", "tokio", ] @@ -3442,15 +4015,25 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", + "digest 0.10.7", "rand_core 0.6.4", ] [[package]] -name = "simd-adler32" -version = "0.3.7" +name = "signature" +version = "3.0.0-rc.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "597a96996ccff7dfa16f052bd995b4cecc72af22c35138738dc029f0ead6608d" +dependencies = [ + "digest 0.11.0-rc.5", + "rand_core 0.10.0-rc-3", +] + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] name = "simd_helpers" @@ -3467,6 +4050,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.11" @@ -3502,7 +4091,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der", + "der 0.7.10", +] + +[[package]] +name = "spki" +version = "0.8.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" +dependencies = [ + "base64ct", + "der 0.8.0-rc.10", ] [[package]] @@ -3530,10 +4129,16 @@ checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" dependencies = [ "base64ct", "bytes", - "pem-rfc7468", - "sha2", + "pem-rfc7468 0.7.0", + "sha2 0.10.9", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "static_assertions" version = "1.1.0" @@ -3548,24 +4153,23 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.3" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.4" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ "heck", "proc-macro2", "quote", - "rustversion", - "syn", + "syn 2.0.113", ] [[package]] @@ -3576,9 +4180,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.108" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" dependencies = [ "proc-macro2", "quote", @@ -3605,19 +4220,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck", - "pkg-config", - "toml 0.8.23", - "version-compare", -] - [[package]] name = "tap" version = "1.0.1" @@ -3625,10 +4227,79 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] -name = "target-lexicon" -version = "0.12.16" +name = "terminfo" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" +dependencies = [ + "fnv", + "nom 7.1.3", + "phf", + "phf_codegen", +] + +[[package]] +name = "termion" +version = "4.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f44138a9ae08f0f502f24104d82517ef4da7330c35acd638f1f29d3cd5475ecb" +dependencies = [ + "libc", + "numtoa", + "serde", +] + +[[package]] +name = "termios" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" +dependencies = [ + "libc", +] + +[[package]] +name = "termwiz" +version = "0.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" +dependencies = [ + "anyhow", + "base64", + "bitflags 2.10.0", + "fancy-regex", + "filedescriptor", + "finl_unicode", + "fixedbitset", + "hex", + "lazy_static", + "libc", + "log", + "memmem", + "nix", + "num-derive", + "num-traits", + "ordered-float 4.6.0", + "pest", + "pest_derive", + "phf", + "serde", + "sha2 0.10.9", + "signal-hook 0.3.18", + "siphasher", + "terminfo", + "termios", + "thiserror 1.0.69", + "ucd-trie", + "unicode-segmentation", + "vtparse", + "wezterm-bidi", + "wezterm-blob-leases", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-input-types", + "winapi", +] [[package]] name = "thiserror" @@ -3656,7 +4327,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -3667,7 +4338,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -3733,10 +4404,31 @@ dependencies = [ ] [[package]] -name = "tokio" -version = "1.48.0" +name = "tls_codec" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" +dependencies = [ + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] +name = "tokio" +version = "1.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", @@ -3757,7 +4449,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -3786,26 +4478,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.23" +version = "0.9.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_edit", -] - -[[package]] -name = "toml" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" dependencies = [ "indexmap", "serde_core", - "serde_spanned 1.0.3", - "toml_datetime 0.7.3", + "serde_spanned", + "toml_datetime", "toml_parser", "toml_writer", "winnow", @@ -3813,55 +4493,33 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.11" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_datetime" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ "serde_core", ] -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap", - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "winnow", -] - [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.0.4" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -3870,32 +4528,32 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf" dependencies = [ "crossbeam-channel", - "thiserror 1.0.69", + "thiserror 2.0.17", "time", "tracing-subscriber", ] [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -3914,9 +4572,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "matchers", "nu-ansi-term", @@ -3957,6 +4615,12 @@ dependencies = [ "rand 0.9.2", ] +[[package]] +name = "typed-path" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7922f2cdc51280d47b491af9eafc41eb0cdab85eabcb390c854412fcbf26dbe8" + [[package]] name = "typeid" version = "1.0.3" @@ -3969,6 +4633,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "unicode-ident" version = "1.0.22" @@ -3983,26 +4653,20 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-truncate" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" +checksum = "8fbf03860ff438702f3910ca5f28f8dac63c1c11e7efb5012b8b175493606330" dependencies = [ "itertools 0.13.0", "unicode-segmentation", - "unicode-width 0.1.14", + "unicode-width", ] [[package]] name = "unicode-width" -version = "0.1.14" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "unicode-width" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "universal-hash" @@ -4010,7 +4674,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "subtle", ] @@ -4034,20 +4698,22 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" dependencies = [ + "atomic", "getrandom 0.3.4", "js-sys", + "serde_core", "wasm-bindgen", ] [[package]] name = "uzers" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df81ff504e7d82ad53e95ed1ad5b72103c11253f39238bcc0235b90768a97dd" +checksum = "0b8275fb1afee25b4111d2dc8b5c505dbbc4afd0b990cb96deb2d88bff8be18d" dependencies = [ "libc", "log", @@ -4109,18 +4775,21 @@ dependencies = [ "rustversion", ] -[[package]] -name = "version-compare" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" - [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vtparse" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9b2acfb050df409c972a37d3b8e08cdea3bddb0c09db9d53137e504cfabed0" +dependencies = [ + "utf8parse", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -4148,9 +4817,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", @@ -4161,9 +4830,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.55" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", @@ -4174,9 +4843,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4184,31 +4853,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.113", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.82" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -4216,9 +4885,83 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "wezterm-bidi" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0a6e355560527dd2d1cf7890652f4f09bb3433b6aadade4c9b5ed76de5f3ec" +dependencies = [ + "log", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-blob-leases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692daff6d93d94e29e4114544ef6d5c942a7ed998b37abdc19b17136ea428eb7" +dependencies = [ + "getrandom 0.3.4", + "mac_address", + "serde", + "sha2 0.10.9", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "wezterm-color-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de81ef35c9010270d63772bebef2f2d6d1f2d20a983d27505ac850b8c4b4296" +dependencies = [ + "csscolorparser", + "deltae", + "lazy_static", + "serde", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-dynamic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2ab60e120fd6eaa68d9567f3226e876684639d22a4219b313ff69ec0ccd5ac" +dependencies = [ + "log", + "ordered-float 4.6.0", + "strsim", + "thiserror 1.0.69", + "wezterm-dynamic-derive", +] + +[[package]] +name = "wezterm-dynamic-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c0cf2d539c645b448eaffec9ec494b8b19bd5077d9e58cb1ae7efece8d575b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wezterm-input-types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7012add459f951456ec9d6c7e6fc340b1ce15d6fc9629f8c42853412c029e57e" +dependencies = [ + "bitflags 1.3.2", + "euclid", + "lazy_static", + "serde", + "wezterm-dynamic", +] [[package]] name = "which" @@ -4227,15 +4970,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" dependencies = [ "env_home", - "rustix 1.1.2", + "rustix 1.1.3", "winsafe", ] [[package]] name = "wide" -version = "0.7.33" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" +checksum = "13ca908d26e4786149c48efcf6c0ea09ab0e06d1fe3c17dc1b4b0f1ca4a7e788" dependencies = [ "bytemuck", "safe_arch", @@ -4284,12 +5027,23 @@ dependencies = [ [[package]] name = "windows" -version = "0.59.0" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "windows-core 0.59.0", - "windows-targets 0.53.5", + "windows-collections", + "windows-core 0.62.2", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core 0.62.2", ] [[package]] @@ -4304,19 +5058,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-core" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce" -dependencies = [ - "windows-implement 0.59.0", - "windows-interface 0.59.3", - "windows-result 0.3.4", - "windows-strings 0.3.1", - "windows-targets 0.53.5", -] - [[package]] name = "windows-core" version = "0.62.2" @@ -4325,9 +5066,20 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement 0.60.2", "windows-interface 0.59.3", - "windows-link 0.2.1", + "windows-link", "windows-result 0.4.1", - "windows-strings 0.5.1", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link", + "windows-threading", ] [[package]] @@ -4338,18 +5090,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "windows-implement" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -4360,7 +5101,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -4371,7 +5112,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -4382,21 +5123,25 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core 0.62.2", + "windows-link", +] + [[package]] name = "windows-result" version = "0.1.2" @@ -4406,31 +5151,13 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows-result" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -4439,7 +5166,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -4475,7 +5202,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -4500,7 +5227,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.2.1", + "windows-link", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -4511,6 +5238,15 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -4609,12 +5345,9 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" -dependencies = [ - "memchr", -] +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" [[package]] name = "winsafe" @@ -4637,15 +5370,21 @@ dependencies = [ "tap", ] +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + [[package]] name = "yazi-actor" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "crossterm 0.29.0", "futures", "globset", - "hashbrown 0.16.0", + "hashbrown", "libc", "mlua", "paste", @@ -4673,13 +5412,14 @@ dependencies = [ [[package]] name = "yazi-adapter" -version = "25.9.15" +version = "26.1.4" dependencies = [ "ansi-to-tui", "anyhow", "base64", "crossterm 0.29.0", "image", + "moxcms", "palette", "quantette", "ratatui", @@ -4695,17 +5435,18 @@ dependencies = [ [[package]] name = "yazi-binding" -version = "25.9.15" +version = "26.1.4" dependencies = [ "ansi-to-tui", - "hashbrown 0.16.0", + "futures", + "hashbrown", "mlua", "paste", "ratatui", "serde_json", "tokio", "tracing", - "unicode-width 0.2.0", + "unicode-width", "yazi-adapter", "yazi-config", "yazi-fs", @@ -4715,16 +5456,15 @@ dependencies = [ [[package]] name = "yazi-boot" -version = "25.9.15" +version = "26.1.4" dependencies = [ "clap", "clap_complete", "clap_complete_fig", "clap_complete_nushell", "futures", - "hashbrown 0.16.0", + "hashbrown", "regex", - "serde", "vergen-gitcl", "yazi-adapter", "yazi-config", @@ -4736,14 +5476,14 @@ dependencies = [ [[package]] name = "yazi-build" -version = "25.9.15" +version = "26.1.4" dependencies = [ "yazi-term", ] [[package]] name = "yazi-cli" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "clap", @@ -4754,7 +5494,7 @@ dependencies = [ "serde", "serde_json", "tokio", - "toml 0.9.8", + "toml", "twox-hash", "vergen-gitcl", "yazi-boot", @@ -4766,28 +5506,28 @@ dependencies = [ [[package]] name = "yazi-codegen" -version = "25.9.15" +version = "26.1.4" dependencies = [ "quote", - "syn", + "syn 2.0.113", ] [[package]] name = "yazi-config" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "bitflags 2.10.0", "crossterm 0.29.0", "dirs", "globset", - "hashbrown 0.16.0", + "hashbrown", "indexmap", "ratatui", "regex", "serde", "tokio", - "toml 0.9.8", + "toml", "tracing", "yazi-codegen", "yazi-fs", @@ -4798,11 +5538,11 @@ dependencies = [ [[package]] name = "yazi-core" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "crossterm 0.29.0", - "hashbrown 0.16.0", + "hashbrown", "indexmap", "parking_lot", "ratatui", @@ -4810,7 +5550,7 @@ dependencies = [ "tokio-stream", "tokio-util", "tracing", - "unicode-width 0.2.0", + "unicode-width", "yazi-adapter", "yazi-config", "yazi-dds", @@ -4828,10 +5568,10 @@ dependencies = [ [[package]] name = "yazi-dds" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", - "hashbrown 0.16.0", + "hashbrown", "mlua", "ordered-float 5.1.0", "parking_lot", @@ -4840,7 +5580,6 @@ dependencies = [ "serde_json", "tokio", "tokio-stream", - "tokio-util", "tracing", "uzers", "vergen-gitcl", @@ -4854,7 +5593,7 @@ dependencies = [ [[package]] name = "yazi-ffi" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "core-foundation-sys", @@ -4865,7 +5604,7 @@ dependencies = [ [[package]] name = "yazi-fm" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "better-panic", @@ -4905,25 +5644,27 @@ dependencies = [ [[package]] name = "yazi-fs" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "arc-swap", "bitflags 2.10.0", "core-foundation-sys", "dirs", - "foldhash 0.2.0", - "hashbrown 0.16.0", + "foldhash", + "hashbrown", "libc", "objc2", "parking_lot", "percent-encoding", + "rand 0.9.2", "regex", "scopeguard", "serde", "tokio", "tracing", "trash", + "typed-path", "uzers", "windows-sys 0.61.2", "yazi-ffi", @@ -4934,20 +5675,20 @@ dependencies = [ [[package]] name = "yazi-macro" -version = "25.9.15" +version = "26.1.4" [[package]] name = "yazi-packing" -version = "25.9.15" +version = "26.1.4" [[package]] name = "yazi-parser" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "bitflags 2.10.0", "crossterm 0.29.0", - "hashbrown 0.16.0", + "hashbrown", "mlua", "ordered-float 5.1.0", "serde", @@ -4958,16 +5699,17 @@ dependencies = [ "yazi-fs", "yazi-macro", "yazi-shared", + "yazi-vfs", ] [[package]] name = "yazi-plugin" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "crossterm 0.29.0", "futures", - "hashbrown 0.16.0", + "hashbrown", "libc", "mlua", "parking_lot", @@ -4980,7 +5722,7 @@ dependencies = [ "tokio-util", "tracing", "twox-hash", - "unicode-width 0.2.0", + "unicode-width", "uzers", "windows-sys 0.61.2", "yazi-adapter", @@ -5007,7 +5749,7 @@ checksum = "33232d9116df6415ddfcdf72701b1b7439ce87f240a14723e8dd5d17e7ed5f98" [[package]] name = "yazi-proxy" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "tokio", @@ -5019,23 +5761,22 @@ dependencies = [ [[package]] name = "yazi-scheduler" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "async-priority-channel", - "foldhash 0.2.0", - "futures", - "hashbrown 0.16.0", + "foldhash", + "hashbrown", "libc", - "lru 0.16.2", + "lru", "mlua", "ordered-float 5.1.0", "parking_lot", - "scopeguard", "serde", "tokio", "tokio-util", "tracing", + "yazi-binding", "yazi-config", "yazi-dds", "yazi-fs", @@ -5049,31 +5790,34 @@ dependencies = [ [[package]] name = "yazi-sftp" -version = "0.1.0" +version = "26.1.4" dependencies = [ "bitflags 2.10.0", "parking_lot", "russh", "serde", "tokio", + "typed-path", ] [[package]] name = "yazi-shared" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "crossterm 0.29.0", - "foldhash 0.2.0", + "foldhash", "futures", - "hashbrown 0.16.0", + "hashbrown", "libc", "memchr", "ordered-float 5.1.0", "parking_lot", "percent-encoding", "serde", + "thiserror 2.0.17", "tokio", + "typed-path", "uzers", "windows-sys 0.61.2", "yazi-macro", @@ -5081,7 +5825,7 @@ dependencies = [ [[package]] name = "yazi-shim" -version = "25.9.15" +version = "26.1.4" dependencies = [ "twox-hash", "yazi-macro", @@ -5089,7 +5833,7 @@ dependencies = [ [[package]] name = "yazi-term" -version = "25.9.15" +version = "26.1.4" dependencies = [ "crossterm 0.29.0", "libc", @@ -5102,16 +5846,17 @@ dependencies = [ [[package]] name = "yazi-vfs" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "deadpool", "futures", - "hashbrown 0.16.0", + "hashbrown", "parking_lot", "russh", "tokio", "tracing", + "typed-path", "yazi-config", "yazi-fs", "yazi-macro", @@ -5121,10 +5866,10 @@ dependencies = [ [[package]] name = "yazi-watcher" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", - "hashbrown 0.16.0", + "hashbrown", "notify", "parking_lot", "percent-encoding", @@ -5142,7 +5887,7 @@ dependencies = [ [[package]] name = "yazi-widgets" -version = "25.9.15" +version = "26.1.4" dependencies = [ "anyhow", "base64", @@ -5152,7 +5897,7 @@ dependencies = [ "parking_lot", "ratatui", "tokio", - "unicode-width 0.2.0", + "unicode-width", "yazi-binding", "yazi-config", "yazi-macro", @@ -5163,22 +5908,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.113", ] [[package]] @@ -5186,12 +5931,32 @@ name = "zeroize" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] +name = "zmij" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee2a72b10d087f75fb2e1c2c7343e308fe6970527c22a41caf8372e165ff5c1" [[package]] name = "zune-core" -version = "0.4.12" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +checksum = "111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773" [[package]] name = "zune-inflate" @@ -5204,9 +5969,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.21" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" +checksum = "e35aee689668bf9bd6f6f3a6c60bb29ba1244b3b43adfd50edd554a371da37d5" dependencies = [ "zune-core", ] diff --git a/Cargo.toml b/Cargo.toml index 55fb0ce3..90cb3cc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,9 @@ resolver = "2" members = [ "yazi-*" ] default-members = [ "yazi-fm", "yazi-cli" ] +[profile.dev] +debug = "line-tables-only" + [profile.release] codegen-units = 1 lto = true @@ -19,46 +22,57 @@ codegen-units = 256 incremental = true lto = false +[profile.dev.package."*"] +debug = false + [workspace.dependencies] -ansi-to-tui = "7.0.0" +ansi-to-tui = "8.0.0" anyhow = "1.0.100" base64 = "0.22.1" bitflags = { version = "2.10.0", features = [ "serde" ] } -clap = { version = "4.5.51", features = [ "derive" ] } +clap = { version = "4.5.54", features = [ "derive" ] } core-foundation-sys = "0.8.7" crossterm = { version = "0.29.0", features = [ "event-stream" ] } dirs = "6.0.0" foldhash = "0.2.0" futures = "0.3.31" globset = "0.4.18" -hashbrown = { version = "0.16.0", features = [ "serde" ] } -indexmap = { version = "2.12.0", features = [ "serde" ] } -libc = "0.2.177" +hashbrown = { version = "0.16.1", features = [ "serde" ] } +indexmap = { version = "2.12.1", features = [ "serde" ] } +libc = "0.2.179" lru = "0.16.2" -mlua = { version = "0.11.4", features = [ "anyhow", "async", "error-send", "lua54", "macros", "serde" ] } +mlua = { version = "0.11.5", features = [ "anyhow", "async", "error-send", "lua54", "macros", "serde" ] } objc2 = "0.6.3" ordered-float = { version = "5.1.0", features = [ "serde" ] } parking_lot = "0.12.5" paste = "1.0.15" percent-encoding = "2.3.2" -ratatui = { version = "0.29.0", features = [ "unstable-rendered-line-info", "unstable-widget-ref" ] } +rand = { version = "0.9.2", default-features = false, features = [ "os_rng", "small_rng", "std" ] } +ratatui = { version = "0.30.0", features = [ "serde", "unstable-rendered-line-info", "unstable-widget-ref" ] } regex = "1.12.2" -russh = { version = "0.54.6", default-features = false, features = [ "ring", "rsa" ] } +russh = { version = "0.56.0", default-features = false, features = [ "ring", "rsa" ] } scopeguard = "1.2.0" serde = { version = "1.0.228", features = [ "derive" ] } -serde_json = "1.0.145" +serde_json = "1.0.148" syntect = { version = "5.3.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] } -tokio = { version = "1.48.0", features = [ "full" ] } +thiserror = "2.0.17" +tokio = { version = "1.49.0", features = [ "full" ] } tokio-stream = "0.1.17" tokio-util = "0.7.17" -toml = { version = "0.9.8" } -tracing = { version = "0.1.41", features = [ "max_level_debug", "release_max_level_debug" ] } +toml = { version = "0.9.10" } +tracing = { version = "0.1.44", features = [ "max_level_debug", "release_max_level_debug" ] } twox-hash = { version = "2.1.2", default-features = false, features = [ "std", "random", "xxhash3_128" ] } -unicode-width = { version = "0.2.0", default-features = false } -uzers = "0.12.1" +typed-path = "0.12.0" +unicode-width = { version = "0.2.2", default-features = false } +uzers = "0.12.2" [workspace.lints.clippy] -format_push_string = "warn" -implicit_clone = "warn" -module_inception = "allow" -use_self = "warn" +format_push_string = "warn" +if_same_then_else = "allow" +implicit_clone = "warn" +len_without_is_empty = "allow" +missing_safety_doc = "allow" +module_inception = "allow" +option_map_unit_fn = "allow" +unit_arg = "allow" +use_self = "warn" diff --git a/README.md b/README.md index 96f0ef51..2d6dfff5 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,14 @@ Yazi (means "duck") is a terminal file manager written in Rust, based on non-blo - 🖼️ **Built-in Support for Multiple Image Protocols**: Also integrated with Überzug++ and Chafa, covering almost all terminals. - 🌟 **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, custom previewer/preloader/spotter/fetcher; Just some pieces of Lua. +- ☁️ **Virtual Filesystem**: Remote file management, custom search engines. - 📡 **Data Distribution Service**: Built on a client-server architecture (no additional server process required), integrated with a Lua-based publish-subscribe model, achieving cross-instance communication and state persistence. - 📦 **Package Manager**: Install plugins and themes with one command, keeping them up-to-date, or pin them to a specific version. - 🧰 Integration with ripgrep, fd, fzf, zoxide - 💫 Vim-like input/pick/confirm/which/notify component, auto-completion for cd paths - 🏷️ Multi-Tab Support, Cross-directory selection, Scrollable Preview (for videos, PDFs, archives, code, directories, etc.) - 🔄 Bulk Renaming, Archive Extraction, Visual Mode, File Chooser, [Git Integration](https://github.com/yazi-rs/plugins/tree/main/git.yazi), [Mount Manager](https://github.com/yazi-rs/plugins/tree/main/mount.yazi) -- 🎨 Theme System, Mouse Support, Trash Bin, Custom Layouts, Virtual Filesystem, CSI u, OSC 52 +- 🎨 Theme System, Mouse Support, Trash Bin, Custom Layouts, CSI u, OSC 52 - ... and more! https://github.com/sxyazi/yazi/assets/17523360/92ff23fa-0cd5-4f04-b387-894c12265cc7 diff --git a/cspell.json b/cspell.json index c55d3a1a..d70d4760 100644 --- a/cspell.json +++ b/cspell.json @@ -1 +1 @@ -{"language":"en","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition","resvg","foldhash","tilded","futs","chdir","hashbrown","JEMALLOC","RUSTFLAGS","RDONLY","GETPATH","fcntl","casefold","inodes","Splatable","casefied"],"version":"0.2"} \ No newline at end of file +{"flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition","resvg","foldhash","tilded","futs","chdir","hashbrown","JEMALLOC","RUSTFLAGS","RDONLY","GETPATH","fcntl","casefold","inodes","Splatable","casefied","thiserror","memchr","memmem","russh","deadpool","keepalive","nodelay","publickey","deadpool","initing"],"version":"0.2","language":"en"} \ No newline at end of file diff --git a/flake.lock b/flake.lock index a69f3da9..509429d9 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1762286042, - "narHash": "sha256-OD5HsZ+sN7VvNucbrjiCz7CHF5zf9gP51YVJvPwYIH8=", + "lastModified": 1763806073, + "narHash": "sha256-FHsEKDvfWpzdADWj99z7vBk4D716Ujdyveo5+A048aI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "12c1f0253aa9a54fdf8ec8aecaafada64a111e24", + "rev": "878e468e02bfabeda08c79250f7ad583037f2227", "type": "github" }, "original": { @@ -48,11 +48,11 @@ ] }, "locked": { - "lastModified": 1762396738, - "narHash": "sha256-BarSecuxtzp1boERdABLkkoxQTi6s/V33lJwUbWLrLY=", + "lastModified": 1763952169, + "narHash": "sha256-+PeDBD8P+NKauH+w7eO/QWCIp8Cx4mCfWnh9sJmy9CM=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "c63598992afd54d215d54f2b764adc0484c2b159", + "rev": "ab726555a9a72e6dc80649809147823a813fa95b", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 07fb4afb..7c10f7c7 100644 --- a/flake.nix +++ b/flake.nix @@ -52,10 +52,13 @@ }; devShells = { - default = pkgs.callPackage ./nix/shell.nix { }; + default = pkgs.callPackage ./nix/shell.nix { + inherit toolchain; + inherit (self.packages.${system}) yazi yazi-unwrapped; + }; }; - formatter = pkgs.nixfmt-rfc-style; + formatter = pkgs.nixfmt-tree; } ) // { diff --git a/nix/shell.nix b/nix/shell.nix index f39538dc..3207d8e3 100644 --- a/nix/shell.nix +++ b/nix/shell.nix @@ -1,14 +1,14 @@ { - callPackage, - rust-bin, + mkShell, + yazi, + toolchain, nodePackages, + yazi-unwrapped, }: -let - mainPkg = callPackage ./yazi.nix { }; -in -mainPkg.overrideAttrs (oa: { - nativeBuildInputs = [ - (rust-bin.nightly.latest.default.override { + +mkShell { + packages = yazi.passthru.runtimePaths ++ [ + (toolchain.override { extensions = [ "rust-src" "rustfmt" @@ -16,10 +16,10 @@ mainPkg.overrideAttrs (oa: { "clippy" ]; }) - nodePackages.cspell - ] - ++ (oa.nativeBuildInputs or [ ]); + ]; + + inputsFrom = [ yazi-unwrapped ]; env.RUST_BACKTRACE = "1"; -}) +} diff --git a/nix/yazi-unwrapped.nix b/nix/yazi-unwrapped.nix index eb4d0cdf..3601b485 100644 --- a/nix/yazi-unwrapped.nix +++ b/nix/yazi-unwrapped.nix @@ -6,7 +6,7 @@ lib, installShellFiles, - stdenv, + fetchFromGitHub, rust-jemalloc-sys, imagemagick, @@ -22,7 +22,7 @@ let ]; }; in -rustPlatform.buildRustPackage rec { +rustPlatform.buildRustPackage (finalAttrs: { pname = "yazi"; inherit version src; @@ -60,14 +60,27 @@ rustPlatform.buildRustPackage rec { magick assets/logo.png -resize "$RES"x"$RES" $out/share/icons/hicolor/"$RES"x"$RES"/apps/yazi.png done + installManPage ${finalAttrs.passthru.srcs.man_src}/yazi{.1,-config.5} + mkdir -p $out/share/applications install -m644 assets/yazi.desktop $out/share/applications/ ''; + passthru.srcs = { + man_src = fetchFromGitHub { + name = "manpages"; # needed to ensure name is unique + owner = "yazi-rs"; + repo = "manpages"; + rev = "8950e968f4a1ad0b83d5836ec54a070855068dbf"; + hash = "sha256-kEVXejDg4ChFoMNBvKlwdFEyUuTcY2VuK9j0PdafKus="; + }; + }; + + meta = { description = "Blazing fast terminal file manager written in Rust, based on async I/O"; homepage = "https://github.com/sxyazi/yazi"; license = lib.licenses.mit; mainProgram = "yazi"; }; -} +}) diff --git a/nix/yazi.nix b/nix/yazi.nix index 1eacd22c..5bac0fc7 100644 --- a/nix/yazi.nix +++ b/nix/yazi.nix @@ -96,6 +96,8 @@ runCommand yazi-unwrapped.name inherit (yazi-unwrapped) pname version meta; nativeBuildInputs = [ makeWrapper ]; + + passthru.runtimePaths = runtimePaths; } '' mkdir -p $out/bin diff --git a/scripts/bump.sh b/scripts/bump.sh index efbfd1c8..08062ea7 100755 --- a/scripts/bump.sh +++ b/scripts/bump.sh @@ -7,7 +7,14 @@ cd "$SCRIPT_DIR/.." echo "Bumping version: $1" TOML_FILES="$(git ls-files '*Cargo.toml')" -perl -pi -e "s/^version .*= .*\$/version = \"$1\"/" -- $TOML_FILES -perl -pi -e "s/^(yazi-[a-z]+)\\s*=\\s*{.*\$/\\1 = { path = \"..\/\\1\", version = \"$1\" }/" -- $TOML_FILES +perl -pi -e 's/^version .*= .*$/version = "'"$1"'"/' -- $TOML_FILES +perl -pi -e 's/^(yazi-[a-z]+)\s*=\s*{.*$/\1 = { path = "..\/\1", version = "'"$1"'" }/' -- $TOML_FILES + +# Insert "## [v$1]" after "## [Unreleased]" +perl -0777 -pe "s/^(## \[Unreleased\]\s*)/\\1## [v$1]\n\n/m" -i CHANGELOG.md +# Determine previous version and append compare link +prev_ver=$(grep -oE '^\[v[0-9][^]]+\]' CHANGELOG.md | tail -n1 | tr -d '[]') +link="\[v$1\]: https://github.com/sxyazi/yazi/compare/$prev_ver...v$1" +perl -pi -e 's{(\['"$prev_ver"'\]:[^\n]+\n)}{$1'"$link"'\n}s' CHANGELOG.md ESLINT_USE_FLAT_CONFIG=true eslint -c ~/.config/rules/eslint/eslint.config.cjs --fix -- $TOML_FILES diff --git a/scripts/publish.sh b/scripts/publish.sh deleted file mode 100755 index aa863625..00000000 --- a/scripts/publish.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -cargo publish -p yazi-macro && sleep 30 -cargo publish -p yazi-codegen && sleep 30 -cargo publish -p yazi-shared && sleep 30 -cargo publish -p yazi-ffi && sleep 30 -cargo publish -p yazi-fs && sleep 30 -cargo publish -p yazi-term && sleep 30 -cargo publish -p yazi-config && sleep 30 -cargo publish -p yazi-proxy && sleep 30 -cargo publish -p yazi-adapter && sleep 30 -cargo publish -p yazi-boot && sleep 30 -cargo publish -p yazi-binding && sleep 30 -cargo publish -p yazi-dds && sleep 30 -cargo publish -p yazi-scheduler && sleep 30 -cargo publish -p yazi-plugin && sleep 30 -cargo publish -p yazi-widgets && sleep 30 -cargo publish -p yazi-core && sleep 30 -cargo publish -p yazi-fm && sleep 30 -cargo publish -p yazi-cli diff --git a/scripts/validate-form/package-lock.json b/scripts/validate-form/package-lock.json index 4b3846c7..77bf7f59 100644 --- a/scripts/validate-form/package-lock.json +++ b/scripts/validate-form/package-lock.json @@ -8,27 +8,37 @@ "name": "validate-form", "version": "1.0.0", "dependencies": { - "@actions/core": "^1.10.1", + "@actions/core": "^2.0.1", "@actions/github": "^6.0.0" } }, "node_modules/@actions/core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", - "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-2.0.1.tgz", + "integrity": "sha512-oBfqT3GwkvLlo1fjvhQLQxuwZCGTarTE5OuZ2Wg10hvhBj7LRIlF611WT4aZS6fDhO5ZKlY7lCAZTlpmyaHaeg==", "license": "MIT", "dependencies": { - "@actions/exec": "^1.1.1", - "@actions/http-client": "^2.0.1" + "@actions/exec": "^2.0.0", + "@actions/http-client": "^3.0.0" + } + }, + "node_modules/@actions/core/node_modules/@actions/http-client": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.0.tgz", + "integrity": "sha512-1s3tXAfVMSz9a4ZEBkXXRQD4QhY3+GAsWSbaYpeknPOKEeyRiU3lH+bHiLMZdo2x/fIeQ/hscL1wCkDLVM2DZQ==", + "license": "MIT", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.28.5" } }, "node_modules/@actions/exec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", - "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-2.0.0.tgz", + "integrity": "sha512-k8ngrX2voJ/RIN6r9xB82NVqKpnMRtxDoiO+g3olkIUpQNqjArXrCQceduQZCQj3P3xm32pChRLqRrtXTlqhIw==", "license": "MIT", "dependencies": { - "@actions/io": "^1.0.1" + "@actions/io": "^2.0.0" } }, "node_modules/@actions/github": { @@ -57,9 +67,9 @@ } }, "node_modules/@actions/io": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", - "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-2.0.0.tgz", + "integrity": "sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg==", "license": "MIT" }, "node_modules/@fastify/busboy": { @@ -85,6 +95,7 @@ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.1.tgz", "integrity": "sha512-dKYCMuPO1bmrpuogcjQ8z7ICCH3FP6WmxpwC03yjzGfZhj9fTJg6+bS1+UAplekbN2C+M61UNllGOOoAfGCrdQ==", "license": "MIT", + "peer": true, "dependencies": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.1.0", diff --git a/scripts/validate-form/package.json b/scripts/validate-form/package.json index 18ee8bec..aee804a4 100644 --- a/scripts/validate-form/package.json +++ b/scripts/validate-form/package.json @@ -6,7 +6,7 @@ }, "private": true, "dependencies": { - "@actions/core": "^1.10.1", + "@actions/core": "^2.0.1", "@actions/github": "^6.0.0" } } diff --git a/yazi-actor/Cargo.toml b/yazi-actor/Cargo.toml index e07c6841..7f942d45 100644 --- a/yazi-actor/Cargo.toml +++ b/yazi-actor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-actor" -version = "25.9.15" +version = "26.1.4" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -8,27 +8,30 @@ description = "Yazi actor model" homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" +[lints] +workspace = true + [features] default = [ "vendored-lua" ] vendored-lua = [ "mlua/vendored" ] [dependencies] -yazi-binding = { path = "../yazi-binding", version = "25.9.15" } -yazi-boot = { path = "../yazi-boot", version = "25.9.15" } -yazi-config = { path = "../yazi-config", version = "25.9.15" } -yazi-core = { path = "../yazi-core", version = "25.9.15" } -yazi-dds = { path = "../yazi-dds", version = "25.9.15" } -yazi-fs = { path = "../yazi-fs", version = "25.9.15" } -yazi-macro = { path = "../yazi-macro", version = "25.9.15" } -yazi-parser = { path = "../yazi-parser", version = "25.9.15" } -yazi-plugin = { path = "../yazi-plugin", version = "25.9.15" } -yazi-proxy = { path = "../yazi-proxy", version = "25.9.15" } -yazi-scheduler = { path = "../yazi-scheduler", version = "25.9.15" } -yazi-shared = { path = "../yazi-shared", version = "25.9.15" } -yazi-term = { path = "../yazi-term", version = "25.9.15" } -yazi-vfs = { path = "../yazi-vfs", version = "25.9.15" } -yazi-watcher = { path = "../yazi-watcher", version = "25.9.15" } -yazi-widgets = { path = "../yazi-widgets", version = "25.9.15" } +yazi-binding = { path = "../yazi-binding", version = "26.1.4" } +yazi-boot = { path = "../yazi-boot", version = "26.1.4" } +yazi-config = { path = "../yazi-config", version = "26.1.4" } +yazi-core = { path = "../yazi-core", version = "26.1.4" } +yazi-dds = { path = "../yazi-dds", version = "26.1.4" } +yazi-fs = { path = "../yazi-fs", version = "26.1.4" } +yazi-macro = { path = "../yazi-macro", version = "26.1.4" } +yazi-parser = { path = "../yazi-parser", version = "26.1.4" } +yazi-plugin = { path = "../yazi-plugin", version = "26.1.4" } +yazi-proxy = { path = "../yazi-proxy", version = "26.1.4" } +yazi-scheduler = { path = "../yazi-scheduler", version = "26.1.4" } +yazi-shared = { path = "../yazi-shared", version = "26.1.4" } +yazi-term = { path = "../yazi-term", version = "26.1.4" } +yazi-vfs = { path = "../yazi-vfs", version = "26.1.4" } +yazi-watcher = { path = "../yazi-watcher", version = "26.1.4" } +yazi-widgets = { path = "../yazi-widgets", version = "26.1.4" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-actor/README.md b/yazi-actor/README.md new file mode 100644 index 00000000..d768a010 --- /dev/null +++ b/yazi-actor/README.md @@ -0,0 +1,5 @@ +# yazi-actor + +This crate is part of [Yazi][source], and it is not supposed to be used outside, as there are no guarantees about the stability of its API. + +[source]: https://github.com/sxyazi/yazi diff --git a/yazi-actor/src/cmp/close.rs b/yazi-actor/src/cmp/close.rs index a6c179c3..4f68dc1c 100644 --- a/yazi-actor/src/cmp/close.rs +++ b/yazi-actor/src/cmp/close.rs @@ -17,10 +17,11 @@ impl Actor for Close { fn act(cx: &mut Ctx, opt: Self::Options) -> Result { let cmp = &mut cx.core.cmp; if let Some(item) = cmp.selected().filter(|_| opt.submit).cloned() { - return act!(complete, cx.core.input, CompleteOpt { item, _ticket: cmp.ticket }); + return act!(input:complete, cx, CompleteOpt { item, ticket: cmp.ticket }); } cmp.caches.clear(); + cmp.ticket = Default::default(); succ!(render!(mem::replace(&mut cmp.visible, false))); } } diff --git a/yazi-actor/src/cmp/show.rs b/yazi-actor/src/cmp/show.rs index 99645d87..585b9e03 100644 --- a/yazi-actor/src/cmp/show.rs +++ b/yazi-actor/src/cmp/show.rs @@ -1,9 +1,9 @@ -use std::{ffi::OsStr, mem, ops::ControlFlow}; +use std::{mem, ops::ControlFlow}; use anyhow::Result; use yazi_macro::{render, succ}; use yazi_parser::cmp::{CmpItem, ShowOpt}; -use yazi_shared::{data::Data, osstr_contains, osstr_starts_with}; +use yazi_shared::{data::Data, path::{AsPath, PathDyn}, strand::StrandLike}; use crate::{Actor, Ctx}; @@ -29,8 +29,7 @@ impl Actor for Show { succ!(); }; - cmp.ticket = opt.ticket; - cmp.cands = Self::match_candidates(opt.word.as_os_str(), cache); + cmp.cands = Self::match_candidates(opt.word.as_path(), cache); if cmp.cands.is_empty() { succ!(render!(mem::replace(&mut cmp.visible, false))); } @@ -43,16 +42,19 @@ impl Actor for Show { } impl Show { - fn match_candidates(word: &OsStr, cache: &[CmpItem]) -> Vec { - let smart = !word.as_encoded_bytes().iter().any(|c| c.is_ascii_uppercase()); + fn match_candidates(word: PathDyn, cache: &[CmpItem]) -> Vec { + let smart = !word.encoded_bytes().iter().any(|&b| b.is_ascii_uppercase()); let flow = cache.iter().try_fold((Vec::new(), Vec::new()), |(mut exact, mut fuzzy), item| { - if osstr_starts_with(&item.name, word, smart) { + let starts_with = + if smart { item.name.eq_ignore_ascii_case(word) } else { item.name.starts_with(word) }; + + if starts_with { exact.push(item); if exact.len() >= LIMIT { return ControlFlow::Break((exact, fuzzy)); } - } else if fuzzy.len() < LIMIT - exact.len() && osstr_contains(&item.name, word) { + } else if fuzzy.len() < LIMIT - exact.len() && item.name.contains(word) { // Here we don't break the control flow, since we want more exact matching. fuzzy.push(item) } diff --git a/yazi-actor/src/cmp/trigger.rs b/yazi-actor/src/cmp/trigger.rs index a5ac077d..bbe88617 100644 --- a/yazi-actor/src/cmp/trigger.rs +++ b/yazi-actor/src/cmp/trigger.rs @@ -1,11 +1,11 @@ -use std::{ffi::OsString, mem, path::{MAIN_SEPARATOR_STR, PathBuf}}; +use std::mem; use anyhow::Result; -use yazi_fs::{CWD, path::expand_url, provider::{DirReader, FileHolder}}; +use yazi_fs::{path::clean_url, provider::{DirReader, FileHolder}}; use yazi_macro::{act, render, succ}; use yazi_parser::cmp::{CmpItem, ShowOpt, TriggerOpt}; use yazi_proxy::CmpProxy; -use yazi_shared::{OsStrSplit, data::Data, natsort, scheme::SchemeLike, url::{UrlBuf, UrlCow}}; +use yazi_shared::{AnyAsciiChar, BytePredictor, data::Data, natsort, path::{AsPath, PathBufDyn, PathLike}, scheme::{SchemeCow, SchemeLike}, strand::{AsStrand, StrandLike}, url::{UrlBuf, UrlCow, UrlLike}}; use yazi_vfs::provider; use crate::{Actor, Ctx}; @@ -32,7 +32,7 @@ impl Actor for Trigger { if cmp.caches.contains_key(&parent) { let ticket = cmp.ticket; - return act!(cmp:show, cx, ShowOpt { cache_name: parent, word, ticket, ..Default::default() }); + return act!(cmp:show, cx, ShowOpt { cache: vec![], cache_name: parent, word, ticket }); } let ticket = cmp.ticket; @@ -42,8 +42,8 @@ impl Actor for Trigger { // "/" is both a directory separator and the root directory per se // As there's no parent directory for the FS root, it is a special case - if parent.loc.as_os_str() == "/" { - cache.push(CmpItem { name: OsString::new(), is_dir: true }); + if parent.loc() == "/" { + cache.push(CmpItem { name: Default::default(), is_dir: true }); } while let Ok(Some(ent)) = dir.next().await { @@ -53,9 +53,8 @@ impl Actor for Trigger { } if !cache.is_empty() { - cache.sort_unstable_by(|a, b| { - natsort(a.name.as_encoded_bytes(), b.name.as_encoded_bytes(), false) - }); + cache + .sort_unstable_by(|a, b| natsort(a.name.encoded_bytes(), b.name.encoded_bytes(), false)); CmpProxy::show(ShowOpt { cache, cache_name: parent, word, ticket }); } @@ -67,38 +66,47 @@ impl Actor for Trigger { } impl Trigger { - fn split_url(s: &str) -> Option<(UrlBuf, PathBuf)> { - let (scheme, path, ..) = UrlCow::parse(s.as_bytes()).ok()?; + fn split_url(s: &str) -> Option<(UrlBuf, PathBufDyn)> { + let sep = if cfg!(windows) { + AnyAsciiChar::new(b"/\\").unwrap() + } else { + AnyAsciiChar::new(b"/").unwrap() + }; - if scheme.is_local() && path.as_os_str() == "~" { - return None; // We don't autocomplete a `~`, but `~/` + let (scheme, path) = SchemeCow::parse(s.as_bytes()).ok()?; + if path.is_empty() && !sep.predicate(s.bytes().last()?) { + return None; // We don't complete a `sftp://test`, but `sftp://test/` } - #[cfg(windows)] - const SEP: &[char] = &['/', '\\']; - #[cfg(not(windows))] - const SEP: char = std::path::MAIN_SEPARATOR; + // Scheme + let scheme = scheme.zeroed(); + if scheme.is_local() && path.as_strand() == "~" { + return None; // We don't complete a `~`, but `~/` + } - Some(match path.as_os_str().rsplit_once(SEP) { - Some((p, c)) if p.is_empty() => { - (UrlBuf { loc: MAIN_SEPARATOR_STR.into(), scheme: scheme.into() }, c.into()) - } - Some((p, c)) => (expand_url(UrlBuf { loc: p.into(), scheme: scheme.into() }), c.into()), - None => (CWD.load().as_ref().clone(), path.into()), - }) + // Child + let child = path.rsplit_pred(sep).map_or(path.as_path(), |(_, c)| c).to_owned(); + + // Parent + let url = UrlCow::try_from((scheme.clone().zeroed(), path)).ok()?; + let abs = if let Some(u) = provider::try_absolute(&url) { u } else { url }; + let parent = abs.loc().try_strip_suffix(&child).ok()?; + + Some((clean_url(UrlCow::try_from((scheme, parent)).ok()?), child)) } } #[cfg(test)] mod tests { + use yazi_fs::CWD; use yazi_shared::url::UrlLike; use super::*; fn compare(s: &str, parent: &str, child: &str) { let (mut p, c) = Trigger::split_url(s).unwrap(); - if let Some(u) = p.strip_prefix(yazi_fs::CWD.load().as_ref()) { - p = UrlBuf::from(u); + if let Ok(u) = p.try_strip_prefix(yazi_fs::CWD.load().as_ref()) { + p = UrlBuf::Regular(u.as_os().unwrap().into()); } assert_eq!((p, c.to_str().unwrap()), (parent.parse().unwrap(), child)); } @@ -106,14 +114,31 @@ mod tests { #[cfg(unix)] #[test] fn test_split() { + yazi_shared::init_tests(); yazi_fs::init(); - compare("", "", ""); + + assert_eq!(Trigger::split_url(""), None); + assert_eq!(Trigger::split_url("sftp://test"), None); compare(" ", "", " "); + compare("/", "/", ""); - compare("//", "//", ""); + compare("//", "/", ""); + compare("///", "/", ""); + compare("/foo", "/", "foo"); + compare("//foo", "/", "foo"); + compare("///foo", "/", "foo"); + compare("/foo/", "/foo/", ""); + compare("//foo/", "/foo/", ""); compare("/foo/bar", "/foo/", "bar"); + compare("///foo/bar", "/foo/", "bar"); + + CWD.set(&"sftp://test".parse::().unwrap(), || {}); + compare("sftp://test/a", "sftp://test/.", "a"); + compare("sftp://test//a", "sftp://test//", "a"); + compare("sftp://test2/a", "sftp://test2/.", "a"); + compare("sftp://test2//a", "sftp://test2//", "a"); } #[cfg(windows)] @@ -121,9 +146,11 @@ mod tests { fn test_split() { yazi_fs::init(); compare("foo", "", "foo"); + compare(r"foo\", r"foo\", ""); compare(r"foo\bar", r"foo\", "bar"); compare(r"foo\bar\", r"foo\bar\", ""); + compare(r"C:\", r"C:\", ""); compare(r"C:\foo", r"C:\", "foo"); compare(r"C:\foo\", r"C:\foo\", ""); diff --git a/yazi-actor/src/context.rs b/yazi-actor/src/context.rs index 9361ae92..259c3160 100644 --- a/yazi-actor/src/context.rs +++ b/yazi-actor/src/context.rs @@ -118,13 +118,5 @@ impl<'a> Ctx<'a> { pub fn tasks(&self) -> &Tasks { &self.tasks } #[inline] - pub fn source(&self) -> Source { - use Source::*; - match self.source { - Key if self.level != 1 => Ind, - Emit if self.level != 1 => EmitInd, - Relay if self.level != 1 => RelayInd, - s => s, - } - } + pub fn source(&self) -> Source { if self.level != 1 { Source::Ind } else { self.source } } } diff --git a/yazi-actor/src/core/preflight.rs b/yazi-actor/src/core/preflight.rs index fbd2aac3..1c46a51c 100644 --- a/yazi-actor/src/core/preflight.rs +++ b/yazi-actor/src/core/preflight.rs @@ -1,5 +1,3 @@ -use std::marker::PhantomData; - use anyhow::Result; use mlua::{ErrorContext, ExternalError, IntoLua, Value}; use yazi_binding::runtime_mut; @@ -8,12 +6,10 @@ use yazi_plugin::LUA; use crate::{Ctx, lives::Lives}; -pub struct Preflight<'a> { - _lifetime: PhantomData<&'a ()>, -} +pub struct Preflight; -impl<'a> Preflight<'a> { - pub fn act(cx: &mut Ctx, opt: (SparkKind, Spark<'a>)) -> Result> { +impl Preflight { + pub fn act<'a>(cx: &mut Ctx, opt: (SparkKind, Spark<'a>)) -> Result> { let kind = opt.0; let Some(handlers) = LOCAL.read().get(kind.as_ref()).filter(|&m| !m.is_empty()).cloned() else { return Ok(opt.1); @@ -27,10 +23,9 @@ impl<'a> Preflight<'a> { runtime_mut!(LUA)?.pop(); match result { - Ok(Value::Nil) => Err( - format!("Cancelled by `{kind}` event handler in `{id}` plugin on preflight") - .into_lua_err(), - )?, + Ok(Value::Nil) => { + Err(format!("`{kind}` event cancelled by `{id}` plugin on preflight").into_lua_err())? + } Ok(v) => body = v, Err(e) => Err( format!("Failed to run `{kind}` event handler in `{id}` plugin: {e}").into_lua_err(), diff --git a/yazi-actor/src/input/complete.rs b/yazi-actor/src/input/complete.rs new file mode 100644 index 00000000..e5c40a3b --- /dev/null +++ b/yazi-actor/src/input/complete.rs @@ -0,0 +1,23 @@ +use anyhow::Result; +use yazi_macro::{act, succ}; +use yazi_parser::input::CompleteOpt; +use yazi_shared::data::Data; + +use crate::{Actor, Ctx}; + +pub struct Complete; + +impl Actor for Complete { + type Options = CompleteOpt; + + const NAME: &str = "complete"; + + fn act(cx: &mut Ctx, opt: Self::Options) -> Result { + let input = &mut cx.input; + if !input.visible || input.ticket.current() != opt.ticket { + succ!(); + } + + act!(complete, input, opt) + } +} diff --git a/yazi-actor/src/input/mod.rs b/yazi-actor/src/input/mod.rs index d23f3447..16e44b0e 100644 --- a/yazi-actor/src/input/mod.rs +++ b/yazi-actor/src/input/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(close escape show); +yazi_macro::mod_flat!(close complete escape show); diff --git a/yazi-actor/src/lib.rs b/yazi-actor/src/lib.rs index def17563..95950dad 100644 --- a/yazi-actor/src/lib.rs +++ b/yazi-actor/src/lib.rs @@ -1,5 +1,3 @@ -#![allow(clippy::if_same_then_else, clippy::option_map_unit_fn)] - extern crate self as yazi_actor; yazi_macro::mod_pub!(cmp confirm core help input lives mgr pick spot tasks which); diff --git a/yazi-actor/src/lives/core.rs b/yazi-actor/src/lives/core.rs index d7860c01..a0341054 100644 --- a/yazi-actor/src/lives/core.rs +++ b/yazi-actor/src/lives/core.rs @@ -50,7 +50,7 @@ impl UserData for Core { } }; } - Ok(match key.as_bytes().as_ref() { + Ok(match &*key.as_bytes() { b"active" => reuse!(active, super::Tab::make(me.active())), b"tabs" => reuse!(tabs, super::Tabs::make(&me.mgr.tabs)), b"tasks" => reuse!(tasks, super::Tasks::make(&me.tasks)), diff --git a/yazi-actor/src/lives/file.rs b/yazi-actor/src/lives/file.rs index aeca4b56..3a41f6bc 100644 --- a/yazi-actor/src/lives/file.rs +++ b/yazi-actor/src/lives/file.rs @@ -1,10 +1,10 @@ -use std::ops::Deref; +use std::{ops::Deref, ptr}; use mlua::{AnyUserData, IntoLua, UserData, UserDataFields, UserDataMethods, Value}; -use yazi_binding::Style; +use yazi_binding::{Style, cached_field}; use yazi_config::THEME; use yazi_plugin::bindings::Range; -use yazi_shared::url::UrlLike; +use yazi_shared::{path::AsPath, url::UrlLike}; use super::Lives; use crate::lives::PtrCell; @@ -19,7 +19,10 @@ pub(super) struct File { v_link_to: Option, v_name: Option, + v_path: Option, v_cache: Option, + + v_bare: Option, } impl Deref for File { @@ -53,7 +56,10 @@ impl File { v_link_to: None, v_name: None, + v_path: None, v_cache: None, + + v_bare: None, })?; ve.insert(ud.clone()); ud @@ -65,11 +71,13 @@ impl File { impl UserData for File { fn add_fields>(fields: &mut F) { yazi_binding::impl_file_fields!(fields); + cached_field!(fields, bare, |_, me| Ok(yazi_binding::File::new(&**me))); fields.add_field_method_get("idx", |_, me| Ok(me.idx + 1)); fields.add_field_method_get("is_hovered", |_, me| Ok(me.idx == me.folder.cursor)); + fields.add_field_method_get("in_current", |_, me| Ok(ptr::eq(&*me.folder, &me.tab.current))); fields.add_field_method_get("in_preview", |_, me| { - Ok(me.tab.hovered().is_some_and(|f| f.url == me.folder.url)) + Ok(me.idx == me.folder.cursor && me.tab.hovered().is_some_and(|f| f.url == me.folder.url)) }); } @@ -88,13 +96,10 @@ impl UserData for File { if !me.url.has_trail() { return Ok(None); } - let Some(path) = me.url.as_path() else { - return Ok(None); - }; - let mut comp = path.strip_prefix(me.url.loc.trail()).unwrap_or(path).components(); + let mut comp = me.url.try_strip_prefix(me.url.trail()).unwrap_or(me.url.loc()).components(); comp.next_back(); - Some(lua.create_string(comp.as_path().as_os_str().as_encoded_bytes())).transpose() + Some(lua.create_string(comp.as_path().encoded_bytes())).transpose() }); methods.add_method("style", |lua, me, ()| { lua.named_registry_value::("cx")?.borrow_scoped(|core: &yazi_core::Core| { diff --git a/yazi-actor/src/lives/folder.rs b/yazi-actor/src/lives/folder.rs index 3ff86e7c..ab4ed872 100644 --- a/yazi-actor/src/lives/folder.rs +++ b/yazi-actor/src/lives/folder.rs @@ -54,7 +54,7 @@ impl Folder { impl UserData for Folder { fn add_fields>(fields: &mut F) { - cached_field!(fields, cwd, |_, me| Ok(Url::new(me.url.to_owned()))); + cached_field!(fields, cwd, |_, me| Ok(Url::new(&me.url))); cached_field!(fields, files, |_, me| Files::make(0..me.files.len(), me, &me.tab)); cached_field!(fields, stage, |_, me| Ok(FolderStage::new(me.stage.clone()))); cached_field!(fields, window, |_, me| Files::make(me.window.clone(), me, &me.tab)); diff --git a/yazi-actor/src/lives/preference.rs b/yazi-actor/src/lives/preference.rs index f77a30b5..a7236363 100644 --- a/yazi-actor/src/lives/preference.rs +++ b/yazi-actor/src/lives/preference.rs @@ -32,7 +32,7 @@ impl UserData for Preference { fields.add_field_method_get("sort_dir_first", |_, me| Ok(me.sort_dir_first)); fields.add_field_method_get("sort_translit", |_, me| Ok(me.sort_translit)); - cached_field!(fields, linemode, |_, me| Ok(me.linemode.to_string())); + cached_field!(fields, linemode, |lua, me| lua.create_string(&me.linemode)); fields.add_field_method_get("show_hidden", |_, me| Ok(me.show_hidden)); } } diff --git a/yazi-actor/src/lives/selected.rs b/yazi-actor/src/lives/selected.rs index b3569b96..2956dd37 100644 --- a/yazi-actor/src/lives/selected.rs +++ b/yazi-actor/src/lives/selected.rs @@ -11,7 +11,7 @@ impl Selected { let inner = PtrCell::from(inner); Lives::scoped_userdata(yazi_binding::Iter::new( - inner.as_static().values().cloned().map(yazi_binding::Url::new), + inner.as_static().values().map(yazi_binding::Url::new), Some(inner.len()), )) } diff --git a/yazi-actor/src/lives/tab.rs b/yazi-actor/src/lives/tab.rs index 6c97fbb3..1c4ab5dd 100644 --- a/yazi-actor/src/lives/tab.rs +++ b/yazi-actor/src/lives/tab.rs @@ -47,7 +47,7 @@ impl UserData for Tab { fields.add_field_method_get("id", |_, me| Ok(Id(me.id))); cached_field!(fields, name, |lua, me| { let url = &me.current.url; - lua.create_string(url.name().unwrap_or(url.loc.as_os_str()).as_encoded_bytes()) + lua.create_string(url.name().map_or_else(|| url.loc().encoded_bytes(), |n| n.encoded_bytes())) }); cached_field!(fields, mode, |_, me| Mode::make(&me.mode)); diff --git a/yazi-actor/src/lives/task.rs b/yazi-actor/src/lives/task.rs index 9003c252..7d63b7b5 100644 --- a/yazi-actor/src/lives/task.rs +++ b/yazi-actor/src/lives/task.rs @@ -1,8 +1,7 @@ use std::ops::Deref; use mlua::{AnyUserData, LuaSerdeExt, UserData, UserDataFields, Value}; -use yazi_binding::cached_field; -use yazi_plugin::runtime::SER_OPT; +use yazi_binding::{SER_OPT, cached_field}; use super::{Lives, PtrCell}; @@ -30,6 +29,7 @@ impl UserData for TaskSnap { cached_field!(fields, name, |lua, me| lua.create_string(&me.name)); cached_field!(fields, prog, |lua, me| lua.to_value_with(&me.prog, SER_OPT)); + fields.add_field_method_get("cooked", |_, me| Ok(me.prog.cooked())); fields.add_field_method_get("running", |_, me| Ok(me.prog.running())); fields.add_field_method_get("success", |_, me| Ok(me.prog.success())); fields.add_field_method_get("failed", |_, me| Ok(me.prog.failed())); diff --git a/yazi-actor/src/lives/tasks.rs b/yazi-actor/src/lives/tasks.rs index 9d264484..e39129cc 100644 --- a/yazi-actor/src/lives/tasks.rs +++ b/yazi-actor/src/lives/tasks.rs @@ -1,8 +1,7 @@ use std::ops::Deref; use mlua::{AnyUserData, LuaSerdeExt, UserData, UserDataFields, Value}; -use yazi_binding::{cached_field, deprecate}; -use yazi_plugin::runtime::SER_OPT; +use yazi_binding::{SER_OPT, cached_field, deprecate}; use super::{Lives, PtrCell}; use crate::lives::TaskSnap; diff --git a/yazi-actor/src/lives/yanked.rs b/yazi-actor/src/lives/yanked.rs index 8854936d..d5b9ee92 100644 --- a/yazi-actor/src/lives/yanked.rs +++ b/yazi-actor/src/lives/yanked.rs @@ -23,7 +23,7 @@ impl Yanked { Lives::scoped_userdata(Self { inner, iter: Lives::scoped_userdata(Iter::new( - inner.as_static().iter().cloned().map(yazi_binding::Url::new), + inner.as_static().iter().map(yazi_binding::Url::new), Some(inner.len()), ))?, }) diff --git a/yazi-actor/src/mgr/back.rs b/yazi-actor/src/mgr/back.rs index 95f744f3..b8ba672d 100644 --- a/yazi-actor/src/mgr/back.rs +++ b/yazi-actor/src/mgr/back.rs @@ -14,7 +14,7 @@ impl Actor for Back { fn act(cx: &mut Ctx, _: Self::Options) -> Result { if let Some(u) = cx.tab_mut().backstack.shift_backward().cloned() { - return act!(mgr:cd, cx, (u, CdSource::Back)); + act!(mgr:cd, cx, (u, CdSource::Back))?; } succ!(); } diff --git a/yazi-actor/src/mgr/bulk_rename.rs b/yazi-actor/src/mgr/bulk_rename.rs index bf178b5e..9c853bd9 100644 --- a/yazi-actor/src/mgr/bulk_rename.rs +++ b/yazi-actor/src/mgr/bulk_rename.rs @@ -1,17 +1,18 @@ -use std::{ffi::{OsStr, OsString}, hash::Hash, io::{Read, Write}, ops::Deref, path::Path}; +use std::{hash::Hash, io::{Read, Write}, ops::Deref, path::Path}; use anyhow::{Result, anyhow}; use crossterm::{execute, style::Print}; use hashbrown::HashMap; use scopeguard::defer; use tokio::io::AsyncWriteExt; +use yazi_binding::Permit; use yazi_config::{YAZI, opener::OpenerRule}; use yazi_dds::Pubsub; use yazi_fs::{File, FilesOp, Splatter, max_common_root, path::skip_url, provider::{FileBuilder, Provider, local::{Gate, Local}}}; use yazi_macro::{err, succ}; use yazi_parser::VoidOpt; use yazi_proxy::{AppProxy, HIDER, TasksProxy}; -use yazi_shared::{OsStrJoin, data::Data, terminal_clear, url::{AsUrl, Component, UrlBuf, UrlCow, UrlLike}}; +use yazi_shared::{data::Data, path::PathDyn, strand::{AsStrand, AsStrandJoin, Strand, StrandBuf, StrandLike}, terminal_clear, url::{AsUrl, UrlBuf, UrlCow, UrlLike}}; use yazi_term::tty::TTY; use yazi_vfs::{VfsFile, maybe_exists, provider}; use yazi_watcher::WATCHER; @@ -47,10 +48,15 @@ impl Actor for BulkRename { .create_new(true) .open(&tmp) .await? - .write_all(old.join(OsStr::new("\n")).as_encoded_bytes()) + .write_all(old.join(Strand::Utf8("\n")).encoded_bytes()) .await?; - defer! { tokio::spawn(Local.remove_file(tmp.clone())); } + defer! { + let tmp = tmp.clone(); + tokio::spawn(async move { + Local::regular(&tmp).remove_file().await + }); + } TasksProxy::process_exec( cwd.into(), Splatter::new(&[UrlCow::default(), tmp.as_url().into()]).splat(&opener.run), @@ -60,12 +66,11 @@ impl Actor for BulkRename { ) .await; - let _permit = HIDER.acquire().await.unwrap(); - defer!(AppProxy::resume()); + let _permit = Permit::new(HIDER.acquire().await.unwrap(), AppProxy::resume()); AppProxy::stop().await; - let new: Vec<_> = Local - .read_to_string(&tmp) + let new: Vec<_> = Local::regular(&tmp) + .read_to_string() .await? .lines() .take(old.len()) @@ -120,10 +125,12 @@ impl BulkRename { let permit = WATCHER.acquire().await.unwrap(); let (mut failed, mut succeeded) = (Vec::new(), HashMap::with_capacity(todo.len())); for (o, n) in todo { - let (old, new): (UrlBuf, UrlBuf) = ( - selected[o.0].components().take(root).chain([Component::Normal(&o)]).collect(), - selected[n.0].components().take(root).chain([Component::Normal(&n)]).collect(), - ); + let (Ok(old), Ok(new)) = + (Self::replace_url(&selected[o.0], root, &o), Self::replace_url(&selected[n.0], root, &n)) + else { + failed.push((o, n, anyhow!("Invalid new or old file name"))); + continue; + }; if maybe_exists(&new).await && !provider::must_identical(&old, &new).await { failed.push((o, n, anyhow!("Destination already exists"))); @@ -137,7 +144,7 @@ impl BulkRename { } if !succeeded.is_empty() { - let it = succeeded.iter().map(|(o, n)| (o, &n.url)); + let it = succeeded.iter().map(|(o, n)| (o.as_url(), n.url.as_url())); err!(Pubsub::pub_after_bulk(it)); FilesOp::rename(succeeded); } @@ -153,6 +160,10 @@ impl BulkRename { YAZI.opener.block(YAZI.open.all(Path::new("bulk-rename.txt"), "text/plain")) } + fn replace_url(url: &UrlBuf, take: usize, rep: &StrandBuf) -> Result { + Ok(url.try_replace(take, PathDyn::with(url.kind(), rep)?)?.into_owned()) + } + async fn output_failed(failed: Vec<(Tuple, Tuple, anyhow::Error)>) -> Result<()> { let mut stdout = TTY.lockout(); terminal_clear(&mut *stdout)?; @@ -209,10 +220,10 @@ impl BulkRename { // --- Tuple #[derive(Clone, Debug)] -struct Tuple(usize, OsString); +struct Tuple(usize, StrandBuf); impl Deref for Tuple { - type Target = OsStr; + type Target = StrandBuf; fn deref(&self) -> &Self::Target { &self.1 } } @@ -227,12 +238,12 @@ impl Hash for Tuple { fn hash(&self, state: &mut H) { self.1.hash(state); } } -impl AsRef for Tuple { - fn as_ref(&self) -> &OsStr { &self.1 } +impl AsStrand for &Tuple { + fn as_strand(&self) -> Strand<'_> { self.1.as_strand() } } impl Tuple { - fn new(index: usize, inner: impl Into) -> Self { Self(index, inner.into()) } + fn new(index: usize, inner: impl Into) -> Self { Self(index, inner.into()) } } // --- Tests diff --git a/yazi-actor/src/mgr/cd.rs b/yazi-actor/src/mgr/cd.rs index 72d4f87f..2e7fe80a 100644 --- a/yazi-actor/src/mgr/cd.rs +++ b/yazi-actor/src/mgr/cd.rs @@ -5,12 +5,12 @@ use tokio::pin; use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream}; use yazi_config::popup::InputCfg; use yazi_dds::Pubsub; -use yazi_fs::{File, FilesOp, path::expand_url}; +use yazi_fs::{File, FilesOp, path::{clean_url, expand_url}}; use yazi_macro::{act, err, render, succ}; use yazi_parser::mgr::CdOpt; use yazi_proxy::{CmpProxy, InputProxy, MgrProxy}; -use yazi_shared::{Debounce, data::Data, errors::InputError, path::PathLike, url::{AsUrl, UrlBuf, UrlLike}}; -use yazi_vfs::VfsFile; +use yazi_shared::{Debounce, data::Data, errors::InputError, url::{AsUrl, UrlBuf, UrlLike}}; +use yazi_vfs::{VfsFile, provider}; use crate::{Actor, Ctx}; @@ -24,7 +24,7 @@ impl Actor for Cd { fn act(cx: &mut Ctx, opt: Self::Options) -> Result { act!(mgr:escape_visual, cx)?; if opt.interactive { - return Self::cd_interactive(); + return Self::cd_interactive(cx); } let tab = cx.tab_mut(); @@ -33,18 +33,8 @@ impl Actor for Cd { } // Take parent to history - if let Some(rep) = tab.parent.take() { - tab.history.insert(rep.url.to_owned(), rep); - } - - // Backstack - if opt.source.big_jump() { - if tab.current.url.is_regular() { - tab.backstack.push(tab.current.url.as_url()); - } - if opt.target.is_regular() { - tab.backstack.push(opt.target.as_url()); - } + if let Some(t) = tab.parent.take() { + tab.history.insert(t.url.clone(), t); } // Current @@ -60,7 +50,7 @@ impl Actor for Cd { rep.stage = Default::default(); } let rep = mem::replace(&mut tab.current, rep); - tab.history.insert(rep.url.to_owned(), rep); + tab.history.insert(rep.url.clone(), rep); // Parent if let Some(parent) = opt.target.parent() { @@ -74,8 +64,9 @@ impl Actor for Cd { tab.parent = Some(parent_folder); } err!(Pubsub::pub_after_cd(tab.id, tab.cwd())); + act!(mgr:displace, cx)?; act!(mgr:hidden, cx)?; - act!(mgr:sort, cx)?; + act!(mgr:sort, cx).ok(); // Apply config excludes if no plugin patterns are set // This ensures config patterns work when gitignore plugin is disabled @@ -86,13 +77,14 @@ impl Actor for Cd { act!(mgr:hover, cx)?; act!(mgr:refresh, cx)?; + act!(mgr:stash, cx, opt).ok(); succ!(render!()); } } impl Cd { - fn cd_interactive() -> Result { - let input = InputProxy::show(InputCfg::cd()); + fn cd_interactive(cx: &Ctx) -> Result { + let input = InputProxy::show(InputCfg::cd(cx.cwd().as_url())); tokio::spawn(async move { let rx = Debounce::new(UnboundedReceiverStream::new(input), Duration::from_millis(50)); @@ -102,6 +94,8 @@ impl Cd { match result { Ok(s) => { let Ok(url) = UrlBuf::try_from(s).map(expand_url) else { return }; + let Ok(url) = provider::absolute(&url).await else { return }; + let url = clean_url(url); let Ok(file) = File::new(&url).await else { return }; if file.is_dir() { @@ -109,12 +103,12 @@ impl Cd { } if let Some(p) = url.parent() { - FilesOp::Upserting(p.into(), [(url.urn().owned(), file)].into()).emit(); + FilesOp::Upserting(p.into(), [(url.urn().into(), file)].into()).emit(); } - MgrProxy::reveal(&url); + MgrProxy::reveal(url); } Err(InputError::Completed(before, ticket)) => { - CmpProxy::trigger(&before, ticket); + CmpProxy::trigger(before, ticket); } _ => break, } diff --git a/yazi-actor/src/mgr/copy.rs b/yazi-actor/src/mgr/copy.rs index 152a5565..0ccf4ff9 100644 --- a/yazi-actor/src/mgr/copy.rs +++ b/yazi-actor/src/mgr/copy.rs @@ -1,9 +1,7 @@ -use std::ffi::OsString; - use anyhow::{Result, bail}; use yazi_macro::{act, succ}; use yazi_parser::mgr::CopyOpt; -use yazi_shared::{data::Data, url::UrlLike}; +use yazi_shared::{data::Data, strand::ToStrand, url::UrlLike}; use yazi_widgets::CLIPBOARD; use crate::{Actor, Ctx}; @@ -18,7 +16,7 @@ impl Actor for Copy { fn act(cx: &mut Ctx, opt: Self::Options) -> Result { act!(mgr:escape_visual, cx)?; - let mut s = OsString::new(); + let mut s = Vec::::new(); let mut it = if opt.hovered { Box::new(cx.hovered().map(|h| &h.url).into_iter()) } else { @@ -30,29 +28,29 @@ impl Actor for Copy { match opt.r#type.as_ref() { // TODO: rename to "url" "path" => { - s.push(opt.separator.transform(&u.os_str())); + s.extend_from_slice(&opt.separator.transform(&u.to_strand())); } "dirname" => { if let Some(p) = u.parent() { - s.push(opt.separator.transform(&p.os_str())); + s.extend_from_slice(&opt.separator.transform(&p.to_strand())); } } "filename" => { - s.push(opt.separator.transform(u.name().unwrap_or_default())); + s.extend_from_slice(&opt.separator.transform(&u.name().unwrap_or_default())); } "name_without_ext" => { - s.push(opt.separator.transform(u.stem().unwrap_or_default())); + s.extend_from_slice(&opt.separator.transform(&u.stem().unwrap_or_default())); } _ => bail!("Unknown copy type: {}", opt.r#type), }; if it.peek().is_some() { - s.push("\n"); + s.push(b'\n'); } } // Copy the CWD path regardless even if the directory is empty if s.is_empty() && opt.r#type == "dirname" { - s.push(opt.separator.transform(&cx.cwd().os_str())); + s.extend_from_slice(&opt.separator.transform(&cx.cwd().to_strand())); } futures::executor::block_on(CLIPBOARD.set(s)); diff --git a/yazi-actor/src/mgr/create.rs b/yazi-actor/src/mgr/create.rs index 0b73d6c9..05e278a9 100644 --- a/yazi-actor/src/mgr/create.rs +++ b/yazi-actor/src/mgr/create.rs @@ -4,7 +4,7 @@ use yazi_fs::{File, FilesOp}; use yazi_macro::{ok_or_not_found, succ}; use yazi_parser::mgr::CreateOpt; use yazi_proxy::{ConfirmProxy, InputProxy, MgrProxy}; -use yazi_shared::{data::Data, path::PathLike, url::{UrlBuf, UrlLike}}; +use yazi_shared::{data::Data, url::{UrlBuf, UrlLike}}; use yazi_vfs::{VfsFile, maybe_exists, provider}; use yazi_watcher::WATCHER; @@ -27,7 +27,10 @@ impl Actor for Create { return; } - let new = cwd.join(&name); + let Ok(new) = cwd.try_join(&name) else { + return; + }; + if !opt.force && maybe_exists(&new).await && !ConfirmProxy::show(ConfirmCfg::overwrite(&new)).await @@ -51,7 +54,7 @@ impl Create { && let Some((parent, urn)) = real.pair() { ok_or_not_found!(provider::remove_file(&new).await); - FilesOp::Deleting(parent.into(), [urn.owned()].into()).emit(); + FilesOp::Deleting(parent.into(), [urn.into()].into()).emit(); provider::create(&new).await?; } else if let Some(parent) = new.parent() { provider::create_dir_all(parent).await.ok(); @@ -65,7 +68,7 @@ impl Create { && let Some((parent, urn)) = real.pair() { let file = File::new(&real).await?; - FilesOp::Upserting(parent.into(), [(urn.owned(), file)].into()).emit(); + FilesOp::Upserting(parent.into(), [(urn.into(), file)].into()).emit(); MgrProxy::reveal(&real); } diff --git a/yazi-actor/src/mgr/displace.rs b/yazi-actor/src/mgr/displace.rs new file mode 100644 index 00000000..ef039798 --- /dev/null +++ b/yazi-actor/src/mgr/displace.rs @@ -0,0 +1,30 @@ +use anyhow::Result; +use yazi_macro::succ; +use yazi_parser::{VoidOpt, mgr::DisplaceDoOpt}; +use yazi_proxy::MgrProxy; +use yazi_shared::{data::Data, url::UrlLike}; +use yazi_vfs::provider; + +use crate::{Actor, Ctx}; + +pub struct Displace; + +impl Actor for Displace { + type Options = VoidOpt; + + const NAME: &str = "displace"; + + fn act(cx: &mut Ctx, _: Self::Options) -> Result { + if cx.cwd().is_absolute() { + succ!(); + } + + let tab = cx.tab().id; + let from = cx.cwd().to_owned(); + tokio::spawn(async move { + MgrProxy::displace_do(tab, DisplaceDoOpt { to: provider::canonicalize(&from).await, from }); + }); + + succ!(); + } +} diff --git a/yazi-actor/src/mgr/displace_do.rs b/yazi-actor/src/mgr/displace_do.rs new file mode 100644 index 00000000..aa707ed2 --- /dev/null +++ b/yazi-actor/src/mgr/displace_do.rs @@ -0,0 +1,36 @@ +use anyhow::{Result, bail}; +use yazi_fs::FilesOp; +use yazi_macro::{act, succ}; +use yazi_parser::mgr::{CdSource, DisplaceDoOpt}; +use yazi_shared::{data::Data, url::UrlLike}; + +use crate::{Actor, Ctx}; + +pub struct DisplaceDo; + +impl Actor for DisplaceDo { + type Options = DisplaceDoOpt; + + const NAME: &str = "displace_do"; + + fn act(cx: &mut Ctx, opt: Self::Options) -> Result { + if cx.cwd() != opt.from { + succ!() + } + + let to = match opt.to { + Ok(url) => url, + Err(e) => return act!(mgr:update_files, cx, FilesOp::IOErr(opt.from, e.into())), + }; + + if !to.is_absolute() { + bail!("Target URL must be absolute"); + } else if let Some(hovered) = cx.hovered() + && let Ok(url) = to.try_join(hovered.urn()) + { + act!(mgr:reveal, cx, (url, CdSource::Displace)) + } else { + act!(mgr:cd, cx, (to, CdSource::Displace)) + } + } +} diff --git a/yazi-actor/src/mgr/download.rs b/yazi-actor/src/mgr/download.rs index a0c1090b..8fcb2640 100644 --- a/yazi-actor/src/mgr/download.rs +++ b/yazi-actor/src/mgr/download.rs @@ -3,12 +3,11 @@ use std::{mem, time::{Duration, Instant}}; use anyhow::Result; use futures::{StreamExt, stream::FuturesUnordered}; use hashbrown::HashSet; -use tokio::sync::oneshot; use yazi_fs::{File, FsScheme, provider::{Provider, local::Local}}; use yazi_macro::succ; use yazi_parser::mgr::{DownloadOpt, OpenOpt}; use yazi_proxy::MgrProxy; -use yazi_shared::{data::Data, url::UrlCow}; +use yazi_shared::{data::Data, url::{UrlCow, UrlLike}}; use yazi_vfs::VfsFile; use crate::{Actor, Ctx}; @@ -29,9 +28,8 @@ impl Actor for Download { let mut wg1 = FuturesUnordered::new(); for url in opt.urls { - let (tx, rx) = oneshot::channel(); - scheduler.file_download(url.to_owned(), Some(tx)); - wg1.push(async move { (rx.await == Ok(false), url) }); + let done = scheduler.file_download(url.to_owned()); + wg1.push(async move { (done.future().await, url) }); } let mut wg2 = vec![]; @@ -78,7 +76,7 @@ impl Download { let roots: HashSet<_> = urls.iter().filter_map(|u| u.scheme().cache()).collect(); for mut root in roots { root.push("%lock"); - Local.create_dir_all(root).await.ok(); + Local::regular(&root).create_dir_all().await.ok(); } } } diff --git a/yazi-actor/src/mgr/enter.rs b/yazi-actor/src/mgr/enter.rs index efece673..abae6034 100644 --- a/yazi-actor/src/mgr/enter.rs +++ b/yazi-actor/src/mgr/enter.rs @@ -1,7 +1,7 @@ use anyhow::Result; use yazi_macro::{act, succ}; use yazi_parser::{VoidOpt, mgr::CdSource}; -use yazi_shared::data::Data; +use yazi_shared::{data::Data, url::UrlLike}; use crate::{Actor, Ctx}; @@ -15,7 +15,7 @@ impl Actor for Enter { fn act(cx: &mut Ctx, _: Self::Options) -> Result { let Some(h) = cx.hovered().filter(|h| h.is_dir()) else { succ!() }; - let url = if h.url.is_search() { h.url.to_regular() } else { h.url.clone() }; + let url = if h.url.is_search() { h.url.to_regular()? } else { h.url.clone() }; act!(mgr:cd, cx, (url, CdSource::Enter)) } diff --git a/yazi-actor/src/mgr/escape.rs b/yazi-actor/src/mgr/escape.rs index aee89094..ed4bbde0 100644 --- a/yazi-actor/src/mgr/escape.rs +++ b/yazi-actor/src/mgr/escape.rs @@ -2,7 +2,7 @@ use anyhow::{Result, bail}; use yazi_macro::{act, render, render_and, succ}; use yazi_parser::{VoidOpt, mgr::EscapeOpt}; use yazi_proxy::AppProxy; -use yazi_shared::data::Data; +use yazi_shared::{data::Data, url::UrlLike}; use crate::{Actor, Ctx}; diff --git a/yazi-actor/src/mgr/filter_do.rs b/yazi-actor/src/mgr/filter_do.rs index 6998907b..37062d6c 100644 --- a/yazi-actor/src/mgr/filter_do.rs +++ b/yazi-actor/src/mgr/filter_do.rs @@ -2,7 +2,7 @@ use anyhow::Result; use yazi_fs::Filter; use yazi_macro::{act, render, succ}; use yazi_parser::mgr::FilterOpt; -use yazi_shared::{data::Data, path::PathLike}; +use yazi_shared::data::Data; use crate::{Actor, Ctx}; @@ -16,7 +16,7 @@ impl Actor for FilterDo { fn act(cx: &mut Ctx, opt: Self::Options) -> Result { let filter = if opt.query.is_empty() { None } else { Some(Filter::new(&opt.query, opt.case)?) }; - let hovered = cx.hovered().map(|f| f.urn().owned()); + let hovered = cx.hovered().map(|f| f.urn().into()); cx.current_mut().files.set_filter(filter); if cx.hovered().map(|f| f.urn()) != hovered.as_ref().map(Into::into) { diff --git a/yazi-actor/src/mgr/follow.rs b/yazi-actor/src/mgr/follow.rs index 00e5f4fc..b0a699dc 100644 --- a/yazi-actor/src/mgr/follow.rs +++ b/yazi-actor/src/mgr/follow.rs @@ -1,7 +1,7 @@ use anyhow::Result; use yazi_fs::path::clean_url; use yazi_macro::{act, succ}; -use yazi_parser::VoidOpt; +use yazi_parser::{VoidOpt, mgr::CdSource}; use yazi_shared::{data::Data, url::UrlLike}; use crate::{Actor, Ctx}; @@ -16,11 +16,8 @@ impl Actor for Follow { fn act(cx: &mut Ctx, _: Self::Options) -> Result { let Some(file) = cx.hovered() else { succ!() }; let Some(link_to) = &file.link_to else { succ!() }; - - if let Some(p) = file.url.parent() { - act!(mgr:reveal, cx, clean_url(p.join(link_to))) - } else { - succ!() - } + let Some(parent) = file.url.parent() else { succ!() }; + let Ok(joined) = parent.try_join(link_to) else { succ!() }; + act!(mgr:reveal, cx, (clean_url(joined), CdSource::Follow)) } } diff --git a/yazi-actor/src/mgr/forward.rs b/yazi-actor/src/mgr/forward.rs index a6642df5..b0a10732 100644 --- a/yazi-actor/src/mgr/forward.rs +++ b/yazi-actor/src/mgr/forward.rs @@ -13,9 +13,9 @@ impl Actor for Forward { const NAME: &str = "forward"; fn act(cx: &mut Ctx, _: Self::Options) -> Result { - match cx.tab_mut().backstack.shift_forward().cloned() { - Some(u) => act!(mgr:cd, cx, (u, CdSource::Forward)), - None => succ!(), + if let Some(u) = cx.tab_mut().backstack.shift_forward().cloned() { + act!(mgr:cd, cx, (u, CdSource::Forward))?; } + succ!() } } diff --git a/yazi-actor/src/mgr/hidden.rs b/yazi-actor/src/mgr/hidden.rs index 2aba7f2b..1e42ee7d 100644 --- a/yazi-actor/src/mgr/hidden.rs +++ b/yazi-actor/src/mgr/hidden.rs @@ -3,7 +3,7 @@ use yazi_core::tab::Folder; use yazi_fs::FolderStage; use yazi_macro::{act, render, render_and, succ}; use yazi_parser::mgr::HiddenOpt; -use yazi_shared::{data::Data, path::PathLike}; +use yazi_shared::data::Data; use crate::{Actor, Ctx}; @@ -18,7 +18,7 @@ impl Actor for Hidden { let state = opt.state.bool(cx.tab().pref.show_hidden); cx.tab_mut().pref.show_hidden = state; - let hovered = cx.hovered().map(|f| f.urn().owned()); + let hovered = cx.hovered().map(|f| f.urn().to_owned()); let apply = |f: &mut Folder| { if f.stage == FolderStage::Loading { render!(); diff --git a/yazi-actor/src/mgr/hover.rs b/yazi-actor/src/mgr/hover.rs index 75e8afdb..bb16eab4 100644 --- a/yazi-actor/src/mgr/hover.rs +++ b/yazi-actor/src/mgr/hover.rs @@ -18,7 +18,7 @@ impl Actor for Hover { // Parent should always track CWD if let Some(p) = &mut tab.parent { - render!(p.repos(tab.current.url.strip_prefix(&p.url))); + render!(p.repos(tab.current.url.try_strip_prefix(&p.url).ok())); } // Repos CWD @@ -30,7 +30,7 @@ impl Actor for Hover { { // `hover(Some)` occurs after user actions, such as create, rename, reveal, etc. // At this point, it's intuitive to track the location of the file regardless. - tab.current.trace = Some(u.to_owned()); + tab.current.trace = Some(u.clone()); } // Publish through DDS diff --git a/yazi-actor/src/mgr/leave.rs b/yazi-actor/src/mgr/leave.rs index 8de02c97..c83d2f23 100644 --- a/yazi-actor/src/mgr/leave.rs +++ b/yazi-actor/src/mgr/leave.rs @@ -21,7 +21,7 @@ impl Actor for Leave { let Some(mut url) = url else { succ!() }; if url.is_search() { - url = url.into_regular(); + url = url.as_regular()?; } act!(mgr:cd, cx, (url, CdSource::Leave)) diff --git a/yazi-actor/src/mgr/mod.rs b/yazi-actor/src/mgr/mod.rs index 6fb6b65f..5d7e64be 100644 --- a/yazi-actor/src/mgr/mod.rs +++ b/yazi-actor/src/mgr/mod.rs @@ -6,6 +6,8 @@ yazi_macro::mod_flat!( close copy create + displace + displace_do download enter escape @@ -39,6 +41,7 @@ yazi_macro::mod_flat!( shell sort spot + stash suspend tab_close tab_create diff --git a/yazi-actor/src/mgr/quit.rs b/yazi-actor/src/mgr/quit.rs index 9eb28e5a..3014c7ef 100644 --- a/yazi-actor/src/mgr/quit.rs +++ b/yazi-actor/src/mgr/quit.rs @@ -1,4 +1,4 @@ -use std::{ffi::OsString, time::Duration}; +use std::time::Duration; use anyhow::Result; use tokio::{select, time}; @@ -7,7 +7,7 @@ use yazi_dds::spark::SparkKind; use yazi_macro::{emit, succ}; use yazi_parser::mgr::QuitOpt; use yazi_proxy::ConfirmProxy; -use yazi_shared::{data::Data, event::EventQuit, url::{AsUrl, UrlCow}}; +use yazi_shared::{data::Data, event::EventQuit, strand::{Strand, StrandLike, ToStrandJoin}, url::AsUrl}; use crate::{Actor, Ctx}; @@ -66,17 +66,12 @@ impl Actor for Quit { } impl Quit { - pub(super) fn with_selected<'a, I, T>(selected: I) + pub(super) fn with_selected(selected: I) where - I: IntoIterator, - T: Into>, + I: IntoIterator, + I::Item: AsUrl, { - let paths = selected.into_iter().fold(OsString::new(), |mut s, u| { - s.push(u.into().as_url().os_str()); - s.push("\n"); - s - }); - + let paths = selected.into_iter().join(Strand::Utf8("\n")); if !paths.is_empty() { emit!(Quit(EventQuit { selected: Some(paths), ..Default::default() })); } diff --git a/yazi-actor/src/mgr/refresh.rs b/yazi-actor/src/mgr/refresh.rs index b2b13cab..5de557b9 100644 --- a/yazi-actor/src/mgr/refresh.rs +++ b/yazi-actor/src/mgr/refresh.rs @@ -6,7 +6,7 @@ use yazi_fs::{CWD, Files, FilesOp, cha::Cha}; use yazi_macro::{act, succ}; use yazi_parser::VoidOpt; use yazi_proxy::MgrProxy; -use yazi_shared::{data::Data, scheme::SchemeLike, url::UrlBuf}; +use yazi_shared::{data::Data, url::{UrlBuf, UrlLike}}; use yazi_term::tty::TTY; use yazi_vfs::{VfsFiles, VfsFilesOp}; @@ -41,7 +41,7 @@ impl Actor for Refresh { impl Refresh { fn cwd_changed() { - if CWD.load().scheme.is_virtual() { + if CWD.load().kind().is_virtual() { MgrProxy::watch(); } } @@ -58,8 +58,8 @@ impl Refresh { let futs: Vec<_> = folders .iter() - .filter(|&f| f.url.is_internal()) - .map(|&f| go(f.url.to_owned(), f.cha)) + .filter(|&f| f.url.is_absolute() && f.url.is_internal()) + .map(|&f| go(f.url.clone(), f.cha)) .collect(); if !futs.is_empty() { tokio::spawn(futures::future::join_all(futs)); diff --git a/yazi-actor/src/mgr/rename.rs b/yazi-actor/src/mgr/rename.rs index 068f7e47..0c857d73 100644 --- a/yazi-actor/src/mgr/rename.rs +++ b/yazi-actor/src/mgr/rename.rs @@ -5,7 +5,7 @@ use yazi_fs::{File, FilesOp}; use yazi_macro::{act, err, ok_or_not_found, succ}; use yazi_parser::mgr::RenameOpt; use yazi_proxy::{ConfirmProxy, InputProxy, MgrProxy}; -use yazi_shared::{Id, data::Data, path::PathLike, url::{UrlBuf, UrlLike}}; +use yazi_shared::{Id, data::Data, url::{UrlBuf, UrlLike}}; use yazi_vfs::{VfsFile, maybe_exists, provider}; use yazi_watcher::WATCHER; @@ -49,7 +49,10 @@ impl Actor for Rename { return; } - let new = old.parent().unwrap().join(name); + let Some(Ok(new)) = old.parent().map(|u| u.try_join(name)) else { + return; + }; + if opt.force || !maybe_exists(&new).await || provider::must_identical(&old, &new).await { Self::r#do(tab, old, new).await.ok(); } else if ConfirmProxy::show(ConfirmCfg::overwrite(&new)).await { @@ -70,10 +73,11 @@ impl Rename { provider::rename(&old, &new).await?; if let Ok(u) = overwritten + && u != new && let Some((parent, urn)) = u.pair() { ok_or_not_found!(provider::rename(&u, &new).await); - FilesOp::Deleting(parent.to_owned(), [urn.owned()].into()).emit(); + FilesOp::Deleting(parent.to_owned(), [urn.into()].into()).emit(); } let new = provider::casefold(&new).await?; @@ -81,10 +85,10 @@ impl Rename { let file = File::new(&new).await?; if new_p == old_p { - FilesOp::Upserting(old_p.into(), [(old_n.owned(), file)].into()).emit(); + FilesOp::Upserting(old_p.into(), [(old_n.into(), file)].into()).emit(); } else { - FilesOp::Deleting(old_p.into(), [old_n.owned()].into()).emit(); - FilesOp::Upserting(new_p.into(), [(new_n.owned(), file)].into()).emit(); + FilesOp::Deleting(old_p.into(), [old_n.into()].into()).emit(); + FilesOp::Upserting(new_p.into(), [(new_n.into(), file)].into()).emit(); } MgrProxy::reveal(&new); diff --git a/yazi-actor/src/mgr/reveal.rs b/yazi-actor/src/mgr/reveal.rs index d174d10f..7da8ea1b 100644 --- a/yazi-actor/src/mgr/reveal.rs +++ b/yazi-actor/src/mgr/reveal.rs @@ -2,7 +2,7 @@ use anyhow::Result; use yazi_fs::{File, FilesOp}; use yazi_macro::{act, render, succ}; use yazi_parser::mgr::RevealOpt; -use yazi_shared::{data::Data, path::PathLike, url::UrlLike}; +use yazi_shared::{data::Data, url::UrlLike}; use crate::{Actor, Ctx}; @@ -19,7 +19,7 @@ impl Actor for Reveal { // Cd to the parent directory act!(mgr:cd, cx, (parent, opt.source))?; - // Try to hover on the child file + // Try to hover over the child file let tab = cx.tab_mut(); render!(tab.current.hover(child)); @@ -30,8 +30,8 @@ impl Actor for Reveal { tab.current.update_pub(tab.id, op); } - // Now, we can safely hover on the target - act!(mgr:hover, cx, Some(child.owned()))?; + // Now, we can safely hover over the target + act!(mgr:hover, cx, Some(child.into()))?; act!(mgr:peek, cx)?; act!(mgr:watch, cx)?; diff --git a/yazi-actor/src/mgr/search.rs b/yazi-actor/src/mgr/search.rs index 224531d6..af526351 100644 --- a/yazi-actor/src/mgr/search.rs +++ b/yazi-actor/src/mgr/search.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, mem, time::Duration}; +use std::{borrow::Cow, time::Duration}; use anyhow::Result; use tokio::pin; @@ -6,10 +6,10 @@ use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream}; use yazi_config::popup::InputCfg; use yazi_fs::{FilesOp, cha::Cha}; use yazi_macro::{act, succ}; -use yazi_parser::{VoidOpt, mgr::{SearchOpt, SearchOptVia}}; +use yazi_parser::{VoidOpt, mgr::{CdSource, SearchOpt, SearchOptVia}}; use yazi_plugin::external; -use yazi_proxy::{InputProxy, MgrProxy}; -use yazi_shared::data::Data; +use yazi_proxy::{AppProxy, InputProxy, MgrProxy}; +use yazi_shared::{data::Data, url::UrlLike}; use crate::{Actor, Ctx}; @@ -52,8 +52,10 @@ impl Actor for SearchDo { handle.abort(); } - let cwd = tab.cwd().to_search(opt.subject.as_ref()); let hidden = tab.pref.show_hidden; + let Ok(cwd) = tab.cwd().to_search(&opt.subject) else { + succ!(AppProxy::notify_warn("Search", "Only local filesystem searches are supported")); + }; tab.search = Some(tokio::spawn(async move { let rx = match opt.via { @@ -107,15 +109,10 @@ impl Actor for SearchStop { handle.abort(); } - if !tab.cwd().is_search() { - succ!(); + if tab.cwd().is_search() { + act!(mgr:cd, cx, (tab.cwd().to_regular()?, CdSource::Escape))?; } - let rep = tab.history.remove_or(tab.cwd().to_regular()); - drop(mem::replace(&mut tab.current, rep)); - - act!(mgr:hidden, cx)?; - act!(mgr:sort, cx)?; - act!(mgr:refresh, cx) + succ!(); } } diff --git a/yazi-actor/src/mgr/shell.rs b/yazi-actor/src/mgr/shell.rs index 722788d1..2d1a0437 100644 --- a/yazi-actor/src/mgr/shell.rs +++ b/yazi-actor/src/mgr/shell.rs @@ -40,7 +40,7 @@ impl Actor for Shell { TasksProxy::open_shell_compat(ProcessOpenOpt { cwd: cwd.into(), - cmd: Splatter::new(&selected).splat(opt.run.as_ref()), + cmd: Splatter::new(&selected).splat(&*opt.run), args: selected, block: opt.block, orphan: opt.orphan, diff --git a/yazi-actor/src/mgr/sort.rs b/yazi-actor/src/mgr/sort.rs index d29a2efd..7ad3b322 100644 --- a/yazi-actor/src/mgr/sort.rs +++ b/yazi-actor/src/mgr/sort.rs @@ -1,9 +1,10 @@ use anyhow::Result; use yazi_core::tab::Folder; +use yazi_dds::spark::SparkKind; use yazi_fs::{FilesSorter, FolderStage}; use yazi_macro::{act, render, render_and, succ}; use yazi_parser::mgr::SortOpt; -use yazi_shared::{data::Data, path::PathLike}; +use yazi_shared::{Source, data::Data}; use crate::{Actor, Ctx}; @@ -23,7 +24,7 @@ impl Actor for Sort { pref.sort_translit = opt.translit.unwrap_or(pref.sort_translit); let sorter = FilesSorter::from(&*pref); - let hovered = cx.hovered().map(|f| f.urn().owned()); + let hovered = cx.hovered().map(|f| f.urn().to_owned()); let apply = |f: &mut Folder| { if f.stage == FolderStage::Loading { render!(); @@ -56,4 +57,12 @@ impl Actor for Sort { succ!(); } + + fn hook(cx: &Ctx, _: &Self::Options) -> Option { + match cx.source() { + Source::Ind => Some(SparkKind::IndSort), + Source::Key => Some(SparkKind::KeySort), + _ => None, + } + } } diff --git a/yazi-actor/src/mgr/stash.rs b/yazi-actor/src/mgr/stash.rs new file mode 100644 index 00000000..2dede4a5 --- /dev/null +++ b/yazi-actor/src/mgr/stash.rs @@ -0,0 +1,31 @@ +use anyhow::Result; +use yazi_dds::spark::SparkKind; +use yazi_macro::succ; +use yazi_parser::mgr::StashOpt; +use yazi_shared::{Source, data::Data, url::{AsUrl, UrlLike}}; + +use crate::{Actor, Ctx}; + +pub struct Stash; + +impl Actor for Stash { + type Options = StashOpt; + + const NAME: &str = "stash"; + + fn act(cx: &mut Ctx, opt: Self::Options) -> Result { + if opt.target.is_absolute() && opt.target.is_internal() { + cx.tab_mut().backstack.push(opt.target.as_url()); + } + + succ!() + } + + fn hook(cx: &Ctx, _opt: &Self::Options) -> Option { + match cx.source() { + Source::Ind => Some(SparkKind::IndStash), + Source::Relay => Some(SparkKind::RelayStash), + _ => None, + } + } +} diff --git a/yazi-actor/src/mgr/tab_create.rs b/yazi-actor/src/mgr/tab_create.rs index 9ddbcea9..835baf46 100644 --- a/yazi-actor/src/mgr/tab_create.rs +++ b/yazi-actor/src/mgr/tab_create.rs @@ -3,7 +3,7 @@ use yazi_core::tab::Tab; use yazi_macro::{act, render, succ}; use yazi_parser::mgr::{CdSource, TabCreateOpt}; use yazi_proxy::AppProxy; -use yazi_shared::data::Data; +use yazi_shared::{data::Data, url::UrlLike}; use crate::{Actor, Ctx}; @@ -25,14 +25,17 @@ impl Actor for TabCreate { } let mut tab = Tab::default(); - let (cd, url) = if let Some(wd) = opt.wd { + let (cd, url) = if let Some(wd) = opt.url { (true, wd.into_owned()) } else if let Some(h) = cx.hovered() { tab.pref = cx.tab().pref.clone(); - (false, h.url.to_regular()) + (false, h.url.clone()) + } else if cx.cwd().is_search() { + tab.pref = cx.tab().pref.clone(); + (true, cx.cwd().to_regular()?) } else { tab.pref = cx.tab().pref.clone(); - (true, cx.cwd().to_regular()) + (true, cx.cwd().clone()) }; let tabs = &mut cx.mgr.tabs; diff --git a/yazi-actor/src/mgr/update_files.rs b/yazi-actor/src/mgr/update_files.rs index b785e38a..08e8d225 100644 --- a/yazi-actor/src/mgr/update_files.rs +++ b/yazi-actor/src/mgr/update_files.rs @@ -18,6 +18,7 @@ impl Actor for UpdateFiles { fn act(cx: &mut Ctx, opt: Self::Options) -> Result { let revision = cx.current().files.revision; let linked: Vec<_> = LINKED.read().from_dir(opt.op.cwd()).map(|u| opt.op.chdir(u)).collect(); + for op in [opt.op].into_iter().chain(linked) { cx.mgr.yanked.apply_op(&op); Self::update_tab(cx, op).ok(); @@ -25,7 +26,7 @@ impl Actor for UpdateFiles { render!(cx.mgr.yanked.catchup_revision(false)); act!(mgr:hidden, cx)?; - act!(mgr:sort, cx)?; + act!(mgr:sort, cx).ok(); if revision != cx.current().files.revision { act!(mgr:hover, cx)?; diff --git a/yazi-actor/src/tasks/inspect.rs b/yazi-actor/src/tasks/inspect.rs index f3bd889d..dc78acd5 100644 --- a/yazi-actor/src/tasks/inspect.rs +++ b/yazi-actor/src/tasks/inspect.rs @@ -4,6 +4,7 @@ use anyhow::Result; use crossterm::{execute, terminal::{disable_raw_mode, enable_raw_mode}}; use scopeguard::defer; use tokio::{io::{AsyncReadExt, stdin}, select, sync::mpsc, time}; +use yazi_binding::Permit; use yazi_macro::succ; use yazi_parser::VoidOpt; use yazi_proxy::{AppProxy, HIDER}; @@ -26,7 +27,7 @@ impl Actor for Inspect { }; tokio::spawn(async move { - let _permit = HIDER.acquire().await.unwrap(); + let _permit = Permit::new(HIDER.acquire().await.unwrap(), AppProxy::resume()); let (tx, mut rx) = mpsc::unbounded_channel(); let buffered = { @@ -37,9 +38,7 @@ impl Actor for Inspect { task.logs.clone() }; - defer!(AppProxy::resume()); AppProxy::stop().await; - terminal_clear(TTY.writer()).ok(); TTY.writer().write_all(buffered.as_bytes()).ok(); TTY.writer().flush().ok(); diff --git a/yazi-adapter/Cargo.toml b/yazi-adapter/Cargo.toml index 32010648..3125a017 100644 --- a/yazi-adapter/Cargo.toml +++ b/yazi-adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-adapter" -version = "25.9.15" +version = "26.1.4" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -8,21 +8,25 @@ description = "Yazi image adapter" homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" +[lints] +workspace = true + [dependencies] -yazi-config = { path = "../yazi-config", version = "25.9.15" } -yazi-fs = { path = "../yazi-fs", version = "25.9.15" } -yazi-macro = { path = "../yazi-macro", version = "25.9.15" } -yazi-shared = { path = "../yazi-shared", version = "25.9.15" } -yazi-term = { path = "../yazi-term", version = "25.9.15" } +yazi-config = { path = "../yazi-config", version = "26.1.4" } +yazi-fs = { path = "../yazi-fs", version = "26.1.4" } +yazi-macro = { path = "../yazi-macro", version = "26.1.4" } +yazi-shared = { path = "../yazi-shared", version = "26.1.4" } +yazi-term = { path = "../yazi-term", version = "26.1.4" } # External dependencies ansi-to-tui = { workspace = true } anyhow = { workspace = true } base64 = { workspace = true } crossterm = { workspace = true } -image = { version = "0.25.8", default-features = false, features = [ "avif", "bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "webp" ] } +image = { version = "0.25.9", default-features = false, features = [ "avif", "bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "webp" ] } +moxcms = "0.7.11" palette = { version = "0.7.6", default-features = false } -quantette = { version = "0.3.0", default-features = false } +quantette = { version = "0.5.1", default-features = false } ratatui = { workspace = true } scopeguard = { workspace = true } tokio = { workspace = true } diff --git a/yazi-adapter/README.md b/yazi-adapter/README.md new file mode 100644 index 00000000..de79a81f --- /dev/null +++ b/yazi-adapter/README.md @@ -0,0 +1,5 @@ +# yazi-adapter + +This crate is part of [Yazi][source], and it is not supposed to be used outside, as there are no guarantees about the stability of its API. + +[source]: https://github.com/sxyazi/yazi diff --git a/yazi-adapter/src/adapter.rs b/yazi-adapter/src/adapter.rs index 8a8f091b..e10b7db7 100644 --- a/yazi-adapter/src/adapter.rs +++ b/yazi-adapter/src/adapter.rs @@ -84,7 +84,7 @@ impl Adapter { } impl Adapter { - pub fn matches(emulator: Emulator) -> Self { + pub fn matches(emulator: &Emulator) -> Self { let mut protocols = emulator.adapters().to_owned(); if env_exists("ZELLIJ_SESSION_NAME") { protocols.retain(|p| *p == Self::Sixel); diff --git a/yazi-adapter/src/brand.rs b/yazi-adapter/src/brand.rs index 91c740f6..c180591c 100644 --- a/yazi-adapter/src/brand.rs +++ b/yazi-adapter/src/brand.rs @@ -44,42 +44,40 @@ impl Brand { } pub fn from_env() -> Option { - use Brand as B; - - let (term, program) = B::env(); + let (term, program) = Self::env(); let vars = [ - ("KITTY_WINDOW_ID", B::Kitty), - ("KONSOLE_VERSION", B::Konsole), - ("ITERM_SESSION_ID", B::Iterm2), - ("WEZTERM_EXECUTABLE", B::WezTerm), - ("GHOSTTY_RESOURCES_DIR", B::Ghostty), - ("WT_Session", B::Microsoft), - ("WARP_HONOR_PS1", B::Warp), - ("VSCODE_INJECTION", B::VSCode), - ("TABBY_CONFIG_DIRECTORY", B::Tabby), + ("KITTY_WINDOW_ID", Self::Kitty), + ("KONSOLE_VERSION", Self::Konsole), + ("ITERM_SESSION_ID", Self::Iterm2), + ("WEZTERM_EXECUTABLE", Self::WezTerm), + ("GHOSTTY_RESOURCES_DIR", Self::Ghostty), + ("WT_Session", Self::Microsoft), + ("WARP_HONOR_PS1", Self::Warp), + ("VSCODE_INJECTION", Self::VSCode), + ("TABBY_CONFIG_DIRECTORY", Self::Tabby), ]; match term.as_str() { - "xterm-kitty" => return Some(B::Kitty), - "foot" => return Some(B::Foot), - "foot-extra" => return Some(B::Foot), - "xterm-ghostty" => return Some(B::Ghostty), - "rio" => return Some(B::Rio), - "rxvt-unicode-256color" => return Some(B::Urxvt), + "xterm-kitty" => return Some(Self::Kitty), + "foot" => return Some(Self::Foot), + "foot-extra" => return Some(Self::Foot), + "xterm-ghostty" => return Some(Self::Ghostty), + "rio" => return Some(Self::Rio), + "rxvt-unicode-256color" => return Some(Self::Urxvt), _ => {} } match program.as_str() { - "iTerm.app" => return Some(B::Iterm2), - "WezTerm" => return Some(B::WezTerm), - "ghostty" => return Some(B::Ghostty), - "WarpTerminal" => return Some(B::Warp), - "rio" => return Some(B::Rio), - "BlackBox" => return Some(B::BlackBox), - "vscode" => return Some(B::VSCode), - "Tabby" => return Some(B::Tabby), - "Hyper" => return Some(B::Hyper), - "mintty" => return Some(B::Mintty), - "Apple_Terminal" => return Some(B::Apple), + "iTerm.app" => return Some(Self::Iterm2), + "WezTerm" => return Some(Self::WezTerm), + "ghostty" => return Some(Self::Ghostty), + "WarpTerminal" => return Some(Self::Warp), + "rio" => return Some(Self::Rio), + "BlackBox" => return Some(Self::BlackBox), + "vscode" => return Some(Self::VSCode), + "Tabby" => return Some(Self::Tabby), + "Hyper" => return Some(Self::Hyper), + "mintty" => return Some(Self::Mintty), + "Apple_Terminal" => return Some(Self::Apple), _ => {} } if let Some((var, brand)) = vars.into_iter().find(|&(s, _)| env_exists(s)) { @@ -91,30 +89,28 @@ impl Brand { } pub(super) fn adapters(self) -> &'static [crate::Adapter] { - use Brand as B; - use crate::Adapter as A; match self { - B::Kitty => &[A::Kgp], - B::Konsole => &[A::KgpOld], - B::Iterm2 => &[A::Iip, A::Sixel], - B::WezTerm => &[A::Iip, A::Sixel], - B::Foot => &[A::Sixel], - B::Ghostty => &[A::Kgp], - B::Microsoft => &[A::Sixel], - B::Warp => &[A::Iip, A::KgpOld], - B::Rio => &[A::Iip, A::Sixel], - B::BlackBox => &[A::Sixel], - B::VSCode => &[A::Iip, A::Sixel], - B::Tabby => &[A::Iip, A::Sixel], - B::Hyper => &[A::Iip, A::Sixel], - B::Mintty => &[A::Iip], - B::Tmux => &[], - B::VTerm => &[], - B::Apple => &[], - B::Urxvt => &[], - B::Bobcat => &[A::Iip, A::Sixel], + Self::Kitty => &[A::Kgp], + Self::Konsole => &[A::KgpOld], + Self::Iterm2 => &[A::Iip, A::Sixel], + Self::WezTerm => &[A::Iip, A::Sixel], + Self::Foot => &[A::Sixel], + Self::Ghostty => &[A::Kgp], + Self::Microsoft => &[A::Sixel], + Self::Warp => &[A::Iip, A::KgpOld], + Self::Rio => &[A::Iip, A::Sixel], + Self::BlackBox => &[A::Sixel], + Self::VSCode => &[A::Iip, A::Sixel], + Self::Tabby => &[A::Iip, A::Sixel], + Self::Hyper => &[A::Iip, A::Sixel], + Self::Mintty => &[A::Iip], + Self::Tmux => &[], + Self::VTerm => &[], + Self::Apple => &[], + Self::Urxvt => &[], + Self::Bobcat => &[A::Iip, A::Sixel], } } diff --git a/yazi-adapter/src/dimension.rs b/yazi-adapter/src/dimension.rs index 9a81e320..dcbcb6fd 100644 --- a/yazi-adapter/src/dimension.rs +++ b/yazi-adapter/src/dimension.rs @@ -50,7 +50,7 @@ impl Dimension { } pub fn cell_size() -> Option<(f64, f64)> { - let emu = EMULATOR.get(); + let emu = &*EMULATOR; Some(if emu.force_16t { (emu.csi_16t.0 as f64, emu.csi_16t.1 as f64) } else if let Some(r) = Self::available().ratio() { diff --git a/yazi-adapter/src/drivers/sixel.rs b/yazi-adapter/src/drivers/sixel.rs index d8e4ce8e..bcb4bfd8 100644 --- a/yazi-adapter/src/drivers/sixel.rs +++ b/yazi-adapter/src/drivers/sixel.rs @@ -4,13 +4,18 @@ use anyhow::{Result, bail}; use crossterm::{cursor::MoveTo, queue}; use image::{DynamicImage, GenericImageView, RgbImage}; use palette::{Srgb, cast::ComponentsAs}; -use quantette::{ColorSlice, PaletteSize, QuantizeOutput, wu::UIntBinner}; +use quantette::{PaletteSize, color_map::IndexedColorMap, wu::{BinnerU8x3, WuU8x3}}; use ratatui::layout::Rect; use crate::{CLOSE, ESCAPE, Emulator, Image, START, adapter::Adapter}; pub(crate) struct Sixel; +struct QuantizeOutput { + indices: Vec, + palette: Vec, +} + impl Sixel { pub(crate) async fn image_show(path: PathBuf, max: Rect) -> Result { let img = Image::downscale(path, max).await?; @@ -50,7 +55,7 @@ impl Sixel { tokio::task::spawn_blocking(move || { let mut buf = vec![]; - write!(buf, "{START}P0;1;8q\"1;1;{};{}", img.width(), img.height())?; + write!(buf, "{START}P9;1q\"1;1;{};{}", img.width(), img.height())?; // Palette for (i, c) in qo.palette.iter().enumerate() { @@ -110,12 +115,14 @@ impl Sixel { fn quantify(rgb: &RgbImage, alpha: bool) -> Result>> { let buf = &rgb.as_raw()[..(rgb.pixels().len() * 3)]; - let slice: ColorSlice> = buf.components_as().try_into()?; + let colors: &[Srgb] = buf.components_as(); - Ok(quantette::wu::indexed_palette( - &slice, - PaletteSize::try_from(256u16 - alpha as u16)?, - &UIntBinner::<32>, - )) + let wu = WuU8x3::run_slice(colors, BinnerU8x3::rgb())?; + let color_map = wu.color_map(PaletteSize::try_from(256u16 - alpha as u16)?); + + Ok(QuantizeOutput { + indices: color_map.map_to_indices(colors), + palette: color_map.into_palette().into_vec(), + }) } } diff --git a/yazi-adapter/src/emulator.rs b/yazi-adapter/src/emulator.rs index ef77d842..4d192917 100644 --- a/yazi-adapter/src/emulator.rs +++ b/yazi-adapter/src/emulator.rs @@ -10,16 +10,25 @@ use yazi_term::tty::{Handle, TTY}; use crate::{Adapter, Brand, Dimension, Mux, TMUX, Unknown}; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub struct Emulator { pub kind: Either, + pub version: String, pub light: bool, pub csi_16t: (u16, u16), pub force_16t: bool, } impl Default for Emulator { - fn default() -> Self { Self::unknown() } + fn default() -> Self { + Self { + kind: Either::Right(Unknown::default()), + version: String::new(), + light: false, + csi_16t: (0, 0), + force_16t: false, + } + } } impl Emulator { @@ -60,22 +69,14 @@ impl Emulator { let csi_16t = Self::csi_16t(&resp).unwrap_or_default(); Ok(Self { kind, + version: Self::csi_gt_q(&resp).unwrap_or_default(), light: Self::light_bg(&resp).unwrap_or_default(), csi_16t, force_16t: Self::force_16t(csi_16t), }) } - pub const fn unknown() -> Self { - Self { - kind: Either::Right(Unknown::default()), - light: false, - csi_16t: (0, 0), - force_16t: false, - } - } - - pub fn adapters(self) -> &'static [Adapter] { + pub fn adapters(&self) -> &'static [Adapter] { match self.kind { Either::Left(brand) => brand.adapters(), Either::Right(unknown) => unknown.adapters(), @@ -182,6 +183,11 @@ impl Emulator { Some((w.parse().ok()?, h.parse().ok()?)) } + fn csi_gt_q(resp: &str) -> Option { + let (_, s) = resp.split_once("\x1bP>|")?; + Some(s[..s.find("\x1b\\")?].to_owned()) + } + fn light_bg(resp: &str) -> Result { match resp.split_once("]11;rgb:") { Some((_, s)) if s.len() >= 14 => { diff --git a/yazi-adapter/src/icc.rs b/yazi-adapter/src/icc.rs new file mode 100644 index 00000000..6b3f0541 --- /dev/null +++ b/yazi-adapter/src/icc.rs @@ -0,0 +1,69 @@ +use anyhow::Context; +use image::{ColorType, DynamicImage, GrayAlphaImage, GrayImage, ImageDecoder, RgbImage, RgbaImage, metadata::Cicp}; +use moxcms::{CicpColorPrimaries, ColorProfile, DataColorSpace, Layout, TransferCharacteristics, TransformOptions}; + +pub(super) struct Icc; +impl Icc { + pub(super) fn transform(mut decoder: impl ImageDecoder) -> anyhow::Result { + if let Some(layout) = Self::color_type_to_layout(decoder.color_type()) + && let Some(icc) = decoder.icc_profile().unwrap_or_default() + && let Ok(profile) = ColorProfile::new_from_slice(&icc) + && Self::requires_transform(&profile) + { + let mut buf = vec![0u8; decoder.total_bytes() as usize]; + let (w, h) = decoder.dimensions(); + decoder.read_image(&mut buf)?; + + let transformer = profile + // TODO: Use `create_transform_in_place_nbit` in the next minor version of moxcms. + .create_transform_8bit(layout, &ColorProfile::new_srgb(), layout, TransformOptions::default()) + .context("cannot make a profile transformer")?; + + let mut converted = vec![0u8; buf.len()]; + transformer.transform(&buf, &mut converted).context("cannot transform image")?; + + let mut image: DynamicImage = match layout { + Layout::Gray => { + GrayImage::from_raw(w, h, converted).context("cannot load transformed image")?.into() + } + Layout::GrayAlpha => { + GrayAlphaImage::from_raw(w, h, converted).context("cannot load transformed image")?.into() + } + Layout::Rgb => { + RgbImage::from_raw(w, h, converted).context("cannot load transformed image")?.into() + } + Layout::Rgba => { + RgbaImage::from_raw(w, h, converted).context("cannot load transformed image")?.into() + } + _ => unreachable!(), + }; + + image.set_rgb_primaries(Cicp::SRGB.primaries); + image.set_transfer_function(Cicp::SRGB.transfer); + Ok(image) + } else { + Ok(DynamicImage::from_decoder(decoder)?) + } + } + + fn color_type_to_layout(color_type: ColorType) -> Option { + match color_type { + ColorType::L8 => Some(Layout::Gray), + ColorType::La8 => Some(Layout::GrayAlpha), + ColorType::Rgb8 => Some(Layout::Rgb), + ColorType::Rgba8 => Some(Layout::Rgba), + _ => None, + } + } + + fn requires_transform(profile: &ColorProfile) -> bool { + if profile.color_space == DataColorSpace::Cmyk { + return false; + } + + profile.cicp.is_none_or(|c| { + c.color_primaries != CicpColorPrimaries::Bt709 + || c.transfer_characteristics != TransferCharacteristics::Srgb + }) + } +} diff --git a/yazi-adapter/src/image.rs b/yazi-adapter/src/image.rs index 7a058f6f..35b8a52a 100644 --- a/yazi-adapter/src/image.rs +++ b/yazi-adapter/src/image.rs @@ -1,18 +1,18 @@ use std::path::{Path, PathBuf}; use anyhow::Result; -use image::{DynamicImage, ExtendedColorType, ImageDecoder, ImageEncoder, ImageError, ImageReader, ImageResult, Limits, codecs::{jpeg::JpegEncoder, png::PngEncoder}, imageops::FilterType, metadata::Orientation}; +use image::{DynamicImage, ImageDecoder, ImageError, ImageReader, Limits, codecs::{jpeg::JpegEncoder, png::PngEncoder}, imageops::FilterType, metadata::Orientation}; use ratatui::layout::Rect; use yazi_config::YAZI; use yazi_fs::provider::{Provider, local::Local}; -use crate::Dimension; +use crate::{Dimension, Icc}; pub struct Image; impl Image { pub async fn precache(src: PathBuf, cache: &Path) -> Result<()> { - let (mut img, orientation, icc) = Self::decode_from(src).await?; + let (mut img, orientation) = Self::decode_from(src).await?; let (w, h) = Self::flip_size(orientation, (YAZI.preview.max_width, YAZI.preview.max_height)); let buf = tokio::task::spawn_blocking(move || { @@ -25,25 +25,22 @@ impl Image { let mut buf = Vec::new(); if img.color().has_alpha() { - let rgba = img.into_rgba8(); - let mut encoder = PngEncoder::new(&mut buf); - icc.map(|b| encoder.set_icc_profile(b)); - encoder.write_image(&rgba, rgba.width(), rgba.height(), ExtendedColorType::Rgba8)?; + let encoder = PngEncoder::new(&mut buf); + img.write_with_encoder(encoder)?; } else { - let mut encoder = JpegEncoder::new_with_quality(&mut buf, YAZI.preview.image_quality); - icc.map(|b| encoder.set_icc_profile(b)); - encoder.encode_image(&img.into_rgb8())?; + let encoder = JpegEncoder::new_with_quality(&mut buf, YAZI.preview.image_quality); + img.write_with_encoder(encoder)?; } Ok::<_, ImageError>(buf) }) .await??; - Ok(Local.write(cache, buf).await?) + Ok(Local::regular(&cache).write(buf).await?) } pub(super) async fn downscale(path: PathBuf, rect: Rect) -> Result { - let (mut img, orientation, _) = Self::decode_from(path).await?; + let (mut img, orientation) = Self::decode_from(path).await?; let (w, h) = Self::flip_size(orientation, Self::max_pixel(rect)); // Fast path. @@ -96,7 +93,7 @@ impl Image { } } - async fn decode_from(path: PathBuf) -> ImageResult<(DynamicImage, Orientation, Option>)> { + async fn decode_from(path: PathBuf) -> Result<(DynamicImage, Orientation)> { let mut limits = Limits::no_limits(); if YAZI.tasks.image_alloc > 0 { limits.max_alloc = Some(YAZI.tasks.image_alloc as u64); @@ -114,9 +111,7 @@ impl Image { let mut decoder = reader.with_guessed_format()?.into_decoder()?; let orientation = decoder.orientation().unwrap_or(Orientation::NoTransforms); - let icc = decoder.icc_profile().unwrap_or_default(); - - Ok((DynamicImage::from_decoder(decoder)?, orientation, icc)) + Ok((Icc::transform(decoder)?, orientation)) }) .await .map_err(|e| ImageError::IoError(e.into()))? diff --git a/yazi-adapter/src/lib.rs b/yazi-adapter/src/lib.rs index 3decaa14..4333d583 100644 --- a/yazi-adapter/src/lib.rs +++ b/yazi-adapter/src/lib.rs @@ -1,12 +1,10 @@ -#![allow(clippy::option_map_unit_fn, clippy::unit_arg)] - yazi_macro::mod_pub!(drivers); -yazi_macro::mod_flat!(adapter brand dimension emulator image info mux unknown); +yazi_macro::mod_flat!(adapter brand dimension emulator icc image info mux unknown); -use yazi_shared::{SyncCell, in_wsl}; +use yazi_shared::{RoCell, SyncCell, in_wsl}; -pub static EMULATOR: SyncCell = SyncCell::new(Emulator::unknown()); +pub static EMULATOR: RoCell = RoCell::new(); pub static ADAPTOR: SyncCell = SyncCell::new(Adapter::Chafa); // Image state @@ -26,8 +24,8 @@ pub fn init() -> anyhow::Result<()> { WSL.set(in_wsl()); // Emulator detection - EMULATOR.set(Emulator::detect().unwrap_or_default()); - TMUX.set(EMULATOR.get().kind.is_left_and(|&b| b == Brand::Tmux)); + let mut emulator = Emulator::detect().unwrap_or_default(); + TMUX.set(emulator.kind.is_left_and(|&b| b == Brand::Tmux)); // Tmux support if TMUX.get() { @@ -35,12 +33,13 @@ pub fn init() -> anyhow::Result<()> { START.set("\x1bPtmux;\x1b\x1b"); CLOSE.set("\x1b\\"); Mux::tmux_passthrough(); - EMULATOR.set(Emulator::detect().unwrap_or_default()); + emulator = Emulator::detect().unwrap_or_default(); } - yazi_config::init_flavor(EMULATOR.get().light)?; + EMULATOR.init(emulator); + yazi_config::init_flavor(EMULATOR.light)?; - ADAPTOR.set(Adapter::matches(EMULATOR.get())); + ADAPTOR.set(Adapter::matches(&EMULATOR)); ADAPTOR.get().start(); Ok(()) } diff --git a/yazi-adapter/src/unknown.rs b/yazi-adapter/src/unknown.rs index fc1f447a..74f5f8fd 100644 --- a/yazi-adapter/src/unknown.rs +++ b/yazi-adapter/src/unknown.rs @@ -1,14 +1,12 @@ use crate::Adapter; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, Default)] pub struct Unknown { pub kgp: bool, pub sixel: bool, } impl Unknown { - pub(super) const fn default() -> Self { Self { kgp: false, sixel: false } } - pub(super) fn adapters(self) -> &'static [Adapter] { use Adapter as A; diff --git a/yazi-binding/Cargo.toml b/yazi-binding/Cargo.toml index 0ed3286d..7f93fff8 100644 --- a/yazi-binding/Cargo.toml +++ b/yazi-binding/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-binding" -version = "25.9.15" +version = "26.1.4" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -8,19 +8,23 @@ description = "Yazi Lua bindings" homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" +[lints] +workspace = true + [features] default = [ "vendored-lua" ] vendored-lua = [ "mlua/vendored" ] [dependencies] -yazi-adapter = { path = "../yazi-adapter", version = "25.9.15" } -yazi-config = { path = "../yazi-config", version = "25.9.15" } -yazi-fs = { path = "../yazi-fs", version = "25.9.15" } -yazi-macro = { path = "../yazi-macro", version = "25.9.15" } -yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-adapter = { path = "../yazi-adapter", version = "26.1.4" } +yazi-config = { path = "../yazi-config", version = "26.1.4" } +yazi-fs = { path = "../yazi-fs", version = "26.1.4" } +yazi-macro = { path = "../yazi-macro", version = "26.1.4" } +yazi-shared = { path = "../yazi-shared", version = "26.1.4" } # External dependencies ansi-to-tui = { workspace = true } +futures = { workspace = true } hashbrown = { workspace = true } mlua = { workspace = true } paste = { workspace = true } diff --git a/yazi-binding/README.md b/yazi-binding/README.md new file mode 100644 index 00000000..bc60416b --- /dev/null +++ b/yazi-binding/README.md @@ -0,0 +1,5 @@ +# yazi-binding + +This crate is part of [Yazi][source], and it is not supposed to be used outside, as there are no guarantees about the stability of its API. + +[source]: https://github.com/sxyazi/yazi diff --git a/yazi-binding/src/elements/border.rs b/yazi-binding/src/elements/border.rs index ab9866f7..2460c33c 100644 --- a/yazi-binding/src/elements/border.rs +++ b/yazi-binding/src/elements/border.rs @@ -20,7 +20,7 @@ pub struct Border { pub r#type: ratatui::widgets::BorderType, pub style: ratatui::style::Style, - pub titles: Vec<(ratatui::widgets::block::Position, ratatui::text::Line<'static>)>, + pub titles: Vec<(ratatui::widgets::TitlePosition, ratatui::text::Line<'static>)>, } impl Border { @@ -51,8 +51,8 @@ impl Border { for title in self.titles { block = match title { - (ratatui::widgets::block::Position::Top, line) => block.title(line), - (ratatui::widgets::block::Position::Bottom, line) => block.title(line), + (ratatui::widgets::TitlePosition::Top, line) => block.title(line), + (ratatui::widgets::TitlePosition::Bottom, line) => block.title(line), }; } @@ -80,9 +80,9 @@ impl UserData for Border { "title", |_, (ud, line, position): (AnyUserData, Value, Option)| { let position = if position == Some(Borders::BOTTOM.bits()) { - ratatui::widgets::block::Position::Bottom + ratatui::widgets::TitlePosition::Bottom } else { - ratatui::widgets::block::Position::Top + ratatui::widgets::TitlePosition::Top }; ud.borrow_mut::()?.titles.push((position, Line::try_from(line)?.inner)); diff --git a/yazi-binding/src/elements/line.rs b/yazi-binding/src/elements/line.rs index 69df7adb..63e8a623 100644 --- a/yazi-binding/src/elements/line.rs +++ b/yazi-binding/src/elements/line.rs @@ -227,7 +227,7 @@ mod tests { .call(()) .unwrap(); - line.spans.iter().map(|s| s.content.as_ref()).collect() + line.spans.iter().map(|s| &*s.content).collect() } #[test] diff --git a/yazi-binding/src/elements/rect.rs b/yazi-binding/src/elements/rect.rs index c1f8262d..f54d9069 100644 --- a/yazi-binding/src/elements/rect.rs +++ b/yazi-binding/src/elements/rect.rs @@ -36,7 +36,7 @@ impl Rect { })?; let index = lua.create_function(move |lua, (_, key): (Table, mlua::String)| { - Ok(match key.as_bytes().as_ref() { + Ok(match &*key.as_bytes() { b"default" => { deprecate!(lua, "`ui.Rect.default` is deprecated, use `ui.Rect{{}}` instead, in your {}\nSee #2927 for more details: https://github.com/sxyazi/yazi/pull/2927"); Some(Self(Default::default())) diff --git a/yazi-binding/src/error.rs b/yazi-binding/src/error.rs index 382326f9..e53698ae 100644 --- a/yazi-binding/src/error.rs +++ b/yazi-binding/src/error.rs @@ -14,9 +14,20 @@ pub enum Error { impl Error { pub fn install(lua: &Lua) -> mlua::Result<()> { - let new = lua.create_function(|_, msg: String| Ok(Self::custom(msg)))?; + let custom = lua.create_function(|_, msg: String| Ok(Self::custom(msg)))?; - lua.globals().raw_set("Error", lua.create_table_from([("custom", new)])?) + let fs = lua.create_function(|_, value: Value| { + Ok(Self::Fs(match value { + Value::Table(t) => yazi_fs::error::Error::custom( + &t.raw_get::("kind")?.to_str()?, + t.raw_get("code")?, + &t.raw_get::("message")?.to_str()?, + )?, + _ => Err("expected a table".into_lua_err())?, + })) + })?; + + lua.globals().raw_set("Error", lua.create_table_from([("custom", custom), ("fs", fs)])?) } pub fn custom(msg: impl Into) -> Self { Self::Custom(msg.into()) } @@ -60,13 +71,20 @@ impl UserData for Error { _ => None, }) }); + fields.add_field_method_get("kind", |_, me| { + Ok(match me { + Self::Io(e) => Some(yazi_fs::error::Error::from(e.kind()).kind_str()), + Self::Fs(e) => Some(e.kind_str()), + _ => None, + }) + }); } fn add_methods>(methods: &mut M) { methods.add_meta_method(MetaMethod::ToString, |lua, me, ()| { Ok(match me { Self::Io(_) | Self::Fs(_) | Self::Serde(_) => lua.create_string(me.to_string()), - Self::Custom(s) => lua.create_string(s.as_ref()), + Self::Custom(s) => lua.create_string(&**s), }) }); methods.add_meta_function(MetaMethod::Concat, |lua, (lhs, rhs): (Value, Value)| { diff --git a/yazi-binding/src/file.rs b/yazi-binding/src/file.rs index 9ef1b7a8..8555d9e5 100644 --- a/yazi-binding/src/file.rs +++ b/yazi-binding/src/file.rs @@ -1,11 +1,14 @@ use std::ops::Deref; -use mlua::{ExternalError, FromLua, Lua, Table, UserData, UserDataFields, UserDataMethods, UserDataRef, Value}; +use mlua::{AnyUserData, ExternalError, FromLua, Lua, ObjectLike, Table, UserData, UserDataFields, UserDataMethods, UserDataRef, Value}; use crate::{Cha, Url, impl_file_fields, impl_file_methods}; pub type FileRef = UserDataRef; +const EXPECTED: &str = "expected a table, File, or fs::File"; + +#[derive(Clone)] pub struct File { inner: yazi_fs::File, @@ -14,6 +17,7 @@ pub struct File { v_link_to: Option, v_name: Option, + v_path: Option, v_cache: Option, } @@ -28,23 +32,53 @@ impl From for yazi_fs::File { } impl File { - pub fn new(inner: yazi_fs::File) -> Self { - Self { inner, v_cha: None, v_url: None, v_link_to: None, v_name: None, v_cache: None } + pub fn new(inner: impl Into) -> Self { + Self { + inner: inner.into(), + v_cha: None, + v_url: None, + v_link_to: None, + + v_name: None, + v_path: None, + v_cache: None, + } + } + + pub fn install(lua: &Lua) -> mlua::Result<()> { + lua.globals().raw_set("File", lua.create_function(|_, value: Value| Self::try_from(value))?) } } -impl File { - pub fn install(lua: &Lua) -> mlua::Result<()> { - lua.globals().raw_set( - "File", - lua.create_function(|_, t: Table| { - Ok(Self::new(yazi_fs::File { - url: t.raw_get::("url")?.into(), - cha: *t.raw_get::("cha")?, - ..Default::default() - })) - })?, - ) +impl TryFrom for File { + type Error = mlua::Error; + + fn try_from(value: Value) -> Result { + match value { + Value::Table(tbl) => Self::try_from(tbl), + Value::UserData(ud) => Self::try_from(ud), + _ => Err(EXPECTED.into_lua_err())?, + } + } +} + +impl TryFrom for File { + type Error = mlua::Error; + + fn try_from(value: Table) -> Result { + Ok(Self::new(yazi_fs::File { + url: value.raw_get::("url")?.into(), + cha: *value.raw_get::("cha")?, + ..Default::default() + })) + } +} + +impl TryFrom for File { + type Error = mlua::Error; + + fn try_from(value: AnyUserData) -> Result { + Ok(if let Ok(me) = value.borrow::() { me.clone() } else { value.get("bare")? }) } } @@ -52,7 +86,7 @@ impl FromLua for File { fn from_lua(value: Value, _: &Lua) -> mlua::Result { Ok(match value { Value::UserData(ud) => Self::new(ud.take::()?.inner), - _ => Err("Expected a File".into_lua_err())?, + _ => Err("expected a File".into_lua_err())?, }) } } diff --git a/yazi-binding/src/handle.rs b/yazi-binding/src/handle.rs new file mode 100644 index 00000000..c9a6f35e --- /dev/null +++ b/yazi-binding/src/handle.rs @@ -0,0 +1,16 @@ +use mlua::{MultiValue, UserData, UserDataMethods}; +use tokio::task::JoinHandle; + +pub enum Handle { + AsyncFn(JoinHandle>), +} + +impl UserData for Handle { + fn add_methods>(methods: &mut M) { + methods.add_method("abort", |_, me, ()| { + Ok(match me { + Self::AsyncFn(h) => h.abort(), + }) + }); + } +} diff --git a/yazi-binding/src/lib.rs b/yazi-binding/src/lib.rs index 2d1ffdc5..e23749be 100644 --- a/yazi-binding/src/lib.rs +++ b/yazi-binding/src/lib.rs @@ -1,7 +1,5 @@ -#![allow(clippy::unit_arg)] - mod macros; yazi_macro::mod_pub!(elements); -yazi_macro::mod_flat!(cha color composer error file icon id iter permit runtime scheme stage style url urn utils); +yazi_macro::mod_flat!(cha color composer error file handle icon id iter path permit runtime scheme stage style url utils); diff --git a/yazi-binding/src/macros.rs b/yazi-binding/src/macros.rs index 6bc50e69..37e0a13f 100644 --- a/yazi-binding/src/macros.rs +++ b/yazi-binding/src/macros.rs @@ -82,65 +82,122 @@ macro_rules! impl_style_method { macro_rules! impl_style_shorthands { ($methods:ident, $($field:tt).+) => { $methods.add_function_mut("fg", |lua, (ud, value): (mlua::AnyUserData, mlua::Value)| { + use ratatui::style::Modifier; + + let me = &mut ud.borrow_mut::()?.$($field).+; match value { - mlua::Value::Nil => { - ud.borrow::()?.$($field).+.fg.map($crate::Color).into_lua(lua) - }, + mlua::Value::Boolean(true) if me.add_modifier.contains(Modifier::REVERSED) && !me.sub_modifier.contains(Modifier::REVERSED) => { + me.bg.map($crate::Color).into_lua(lua) + } + mlua::Value::Nil | mlua::Value::Boolean(_) => { + me.fg.map($crate::Color).into_lua(lua) + } _ => { - ud.borrow_mut::()?.$($field).+.fg = Some($crate::Color::try_from(value)?.0); + me.fg = Some($crate::Color::try_from(value)?.0); ud.into_lua(lua) } } }); $methods.add_function_mut("bg", |lua, (ud, value): (mlua::AnyUserData, mlua::Value)| { + use ratatui::style::Modifier; + + let me = &mut ud.borrow_mut::()?.$($field).+; match value { - mlua::Value::Nil => { - ud.borrow::()?.$($field).+.bg.map($crate::Color).into_lua(lua) + mlua::Value::Boolean(true) if me.add_modifier.contains(Modifier::REVERSED) && !me.sub_modifier.contains(Modifier::REVERSED) => { + me.fg.map($crate::Color).into_lua(lua) + } + mlua::Value::Nil | mlua::Value::Boolean(_) => { + me.bg.map($crate::Color).into_lua(lua) } _ => { - ud.borrow_mut::()?.$($field).+.bg = Some($crate::Color::try_from(value)?.0); + me.bg = Some($crate::Color::try_from(value)?.0); ud.into_lua(lua) } } }); - $methods.add_function_mut("bold", |_, ud: mlua::AnyUserData| { - ud.borrow_mut::()?.$($field).+.add_modifier |= ratatui::style::Modifier::BOLD; + $methods.add_function_mut("bold", |_, (ud, remove): (mlua::AnyUserData, bool)| { + let me = &mut ud.borrow_mut::()?.$($field).+; + if remove { + *me = me.remove_modifier(ratatui::style::Modifier::BOLD); + } else { + *me = me.add_modifier(ratatui::style::Modifier::BOLD); + } Ok(ud) }); - $methods.add_function_mut("dim", |_, ud: mlua::AnyUserData| { - ud.borrow_mut::()?.$($field).+.add_modifier |= ratatui::style::Modifier::DIM; + $methods.add_function_mut("dim", |_, (ud, remove): (mlua::AnyUserData, bool)| { + let me = &mut ud.borrow_mut::()?.$($field).+; + if remove { + *me = me.remove_modifier(ratatui::style::Modifier::DIM); + } else { + *me = me.add_modifier(ratatui::style::Modifier::DIM); + } Ok(ud) }); - $methods.add_function_mut("italic", |_, ud: mlua::AnyUserData| { - ud.borrow_mut::()?.$($field).+.add_modifier |= ratatui::style::Modifier::ITALIC; + $methods.add_function_mut("italic", |_, (ud, remove): (mlua::AnyUserData, bool)| { + let me = &mut ud.borrow_mut::()?.$($field).+; + if remove { + *me = me.remove_modifier(ratatui::style::Modifier::ITALIC); + } else { + *me = me.add_modifier(ratatui::style::Modifier::ITALIC); + } Ok(ud) }); - $methods.add_function_mut("underline", |_, ud: mlua::AnyUserData| { - ud.borrow_mut::()?.$($field).+.add_modifier |= ratatui::style::Modifier::UNDERLINED; + $methods.add_function_mut("underline", |_, (ud, remove): (mlua::AnyUserData, bool)| { + let me = &mut ud.borrow_mut::()?.$($field).+; + if remove { + *me = me.remove_modifier(ratatui::style::Modifier::UNDERLINED); + } else { + *me = me.add_modifier(ratatui::style::Modifier::UNDERLINED); + } Ok(ud) }); - $methods.add_function_mut("blink", |_, ud: mlua::AnyUserData| { - ud.borrow_mut::()?.$($field).+.add_modifier |= ratatui::style::Modifier::SLOW_BLINK; + $methods.add_function_mut("blink", |_, (ud, remove): (mlua::AnyUserData, bool)| { + let me = &mut ud.borrow_mut::()?.$($field).+; + if remove { + *me = me.remove_modifier(ratatui::style::Modifier::SLOW_BLINK); + } else { + *me = me.add_modifier(ratatui::style::Modifier::SLOW_BLINK); + } Ok(ud) }); - $methods.add_function_mut("blink_rapid", |_, ud: mlua::AnyUserData| { - ud.borrow_mut::()?.$($field).+.add_modifier |= ratatui::style::Modifier::RAPID_BLINK; + $methods.add_function_mut("blink_rapid", |_, (ud, remove): (mlua::AnyUserData, bool)| { + let me = &mut ud.borrow_mut::()?.$($field).+; + if remove { + *me = me.remove_modifier(ratatui::style::Modifier::RAPID_BLINK); + } else { + *me = me.add_modifier(ratatui::style::Modifier::RAPID_BLINK); + } Ok(ud) }); - $methods.add_function_mut("reverse", |_, ud: mlua::AnyUserData| { - ud.borrow_mut::()?.$($field).+.add_modifier |= ratatui::style::Modifier::REVERSED; + $methods.add_function_mut("reverse", |_, (ud, remove): (mlua::AnyUserData, bool)| { + let me = &mut ud.borrow_mut::()?.$($field).+; + if remove { + *me = me.remove_modifier(ratatui::style::Modifier::REVERSED); + } else { + *me = me.add_modifier(ratatui::style::Modifier::REVERSED); + } Ok(ud) }); - $methods.add_function_mut("hidden", |_, ud: mlua::AnyUserData| { - ud.borrow_mut::()?.$($field).+.add_modifier |= ratatui::style::Modifier::HIDDEN; + $methods.add_function_mut("hidden", |_, (ud, remove): (mlua::AnyUserData, bool)| { + let me = &mut ud.borrow_mut::()?.$($field).+; + if remove { + *me = me.remove_modifier(ratatui::style::Modifier::HIDDEN); + } else { + *me = me.add_modifier(ratatui::style::Modifier::HIDDEN); + } Ok(ud) }); - $methods.add_function_mut("crossed", |_, ud: mlua::AnyUserData| { - ud.borrow_mut::()?.$($field).+.add_modifier |= ratatui::style::Modifier::CROSSED_OUT; + $methods.add_function_mut("crossed", |_, (ud, remove): (mlua::AnyUserData, bool)| { + let me = &mut ud.borrow_mut::()?.$($field).+; + if remove { + *me = me.remove_modifier(ratatui::style::Modifier::CROSSED_OUT); + } else { + *me = me.add_modifier(ratatui::style::Modifier::CROSSED_OUT); + } Ok(ud) }); $methods.add_function_mut("reset", |_, ud: mlua::AnyUserData| { - ud.borrow_mut::()?.$($field).+.add_modifier = ratatui::style::Modifier::empty(); + ud.borrow_mut::()?.$($field).+ = ratatui::style::Style::reset(); Ok(ud) }); }; @@ -151,14 +208,19 @@ macro_rules! impl_file_fields { ($fields:ident) => { $crate::cached_field!($fields, cha, |_, me| Ok($crate::Cha(me.cha))); $crate::cached_field!($fields, url, |_, me| Ok($crate::Url::new(me.url_owned()))); - $crate::cached_field!($fields, link_to, |_, me| Ok(me.link_to.clone().map($crate::Url::new))); + $crate::cached_field!($fields, link_to, |_, me| Ok(me.link_to.as_ref().map($crate::Path::new))); $crate::cached_field!($fields, name, |lua, me| { - me.name().map(|s| lua.create_string(s.as_encoded_bytes())).transpose() + me.name().map(|s| lua.create_string(s.encoded_bytes())).transpose() + }); + $crate::cached_field!($fields, path, |_, me| { + use yazi_fs::FsUrl; + use yazi_shared::url::AsUrl; + Ok($crate::Path::new(me.url.as_url().unified_path())) }); $crate::cached_field!($fields, cache, |_, me| { use yazi_fs::FsUrl; - Ok(me.url.cache().map($crate::Url::new)) + Ok(me.url.cache().map($crate::Path::new)) }); }; } diff --git a/yazi-binding/src/path.rs b/yazi-binding/src/path.rs new file mode 100644 index 00000000..137a1d84 --- /dev/null +++ b/yazi-binding/src/path.rs @@ -0,0 +1,136 @@ +use std::ops::Deref; + +use mlua::{ExternalError, ExternalResult, FromLua, Lua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, Value}; +use yazi_shared::{path::{PathBufDyn, PathLike, StripPrefixError}, strand::{AsStrand, Strand, StrandCow}}; + +use crate::cached_field; + +pub type PathRef = UserDataRef; + +pub struct Path { + inner: PathBufDyn, + + v_ext: Option, + v_name: Option, + v_parent: Option, + v_stem: Option, +} + +impl Deref for Path { + type Target = PathBufDyn; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +impl From for PathBufDyn { + fn from(value: Path) -> Self { value.inner } +} + +impl AsStrand for Path { + fn as_strand(&self) -> Strand<'_> { self.inner.as_strand() } +} + +impl AsStrand for &Path { + fn as_strand(&self) -> Strand<'_> { self.inner.as_strand() } +} + +impl Path { + pub fn new(path: impl Into) -> Self { + Self { + inner: path.into(), + + v_ext: None, + v_name: None, + v_parent: None, + v_stem: None, + } + } + + fn ends_with(&self, child: Value) -> mlua::Result { + match child { + Value::String(s) => { + self.try_ends_with(StrandCow::with(self.kind(), &*s.as_bytes())?).into_lua_err() + } + Value::UserData(ud) => self.try_ends_with(&*ud.borrow::()?).into_lua_err(), + _ => Err("must be a string or Path".into_lua_err())?, + } + } + + fn join(&self, other: Value) -> mlua::Result { + Ok(Self::new(match other { + Value::String(s) => { + self.try_join(StrandCow::with(self.kind(), &*s.as_bytes())?).into_lua_err()? + } + Value::UserData(ref ud) => { + let path = ud.borrow::()?; + self.try_join(&*path).into_lua_err()? + } + _ => Err("must be a string or Path".into_lua_err())?, + })) + } + + fn starts_with(&self, base: Value) -> mlua::Result { + match base { + Value::String(s) => { + self.try_starts_with(StrandCow::with(self.kind(), &*s.as_bytes())?).into_lua_err() + } + Value::UserData(ud) => self.try_starts_with(&*ud.borrow::()?).into_lua_err(), + _ => Err("must be a string or Path".into_lua_err())?, + } + } + + fn strip_prefix(&self, base: Value) -> mlua::Result> { + let strip = match base { + Value::String(s) => self.try_strip_prefix(StrandCow::with(self.kind(), &*s.as_bytes())?), + Value::UserData(ud) => self.try_strip_prefix(&*ud.borrow::()?), + _ => Err("must be a string or Path".into_lua_err())?, + }; + + Ok(match strip { + Ok(p) => Some(Self::new(p)), + Err(StripPrefixError::Exotic | StripPrefixError::NotPrefix) => None, + Err(e @ StripPrefixError::WrongEncoding) => Err(e.into_lua_err())?, + }) + } +} + +impl FromLua for Path { + fn from_lua(value: Value, _: &Lua) -> mlua::Result { + Ok(match value { + Value::UserData(ud) => ud.take()?, + _ => Err("Expected a Path".into_lua_err())?, + }) + } +} + +impl UserData for Path { + fn add_fields>(fields: &mut F) { + cached_field!(fields, ext, |lua, me| { + me.ext().map(|s| lua.create_string(s.encoded_bytes())).transpose() + }); + cached_field!(fields, name, |lua, me| { + me.name().map(|s| lua.create_string(s.encoded_bytes())).transpose() + }); + cached_field!(fields, parent, |_, me| Ok(me.parent().map(Self::new))); + cached_field!(fields, stem, |lua, me| { + me.stem().map(|s| lua.create_string(s.encoded_bytes())).transpose() + }); + + fields.add_field_method_get("is_absolute", |_, me| Ok(me.is_absolute())); + fields.add_field_method_get("has_root", |_, me| Ok(me.has_root())); + } + + fn add_methods>(methods: &mut M) { + methods.add_method("ends_with", |_, me, child: Value| me.ends_with(child)); + methods.add_method("join", |_, me, other: Value| me.join(other)); + methods.add_method("starts_with", |_, me, base: Value| me.starts_with(base)); + methods.add_method("strip_prefix", |_, me, base: Value| me.strip_prefix(base)); + + methods.add_meta_method(MetaMethod::Concat, |lua, lhs, rhs: mlua::String| { + lua.create_string([lhs.encoded_bytes(), &rhs.as_bytes()].concat()) + }); + methods.add_meta_method(MetaMethod::Eq, |_, me, other: PathRef| Ok(me.inner == other.inner)); + methods + .add_meta_method(MetaMethod::ToString, |lua, me, ()| lua.create_string(me.encoded_bytes())); + } +} diff --git a/yazi-binding/src/permit.rs b/yazi-binding/src/permit.rs index 2d16037f..19acf379 100644 --- a/yazi-binding/src/permit.rs +++ b/yazi-binding/src/permit.rs @@ -1,42 +1,51 @@ use std::{mem, ops::Deref}; +use futures::{FutureExt, future::BoxFuture}; use mlua::{UserData, prelude::LuaUserDataMethods}; use tokio::sync::SemaphorePermit; -pub type PermitRef = mlua::UserDataRef>; +pub type PermitRef = mlua::UserDataRef; -pub struct Permit { +pub struct Permit { inner: Option>, - destruct: Option, + destruct: Option>, } -impl Deref for Permit { +impl Deref for Permit { type Target = Option>; fn deref(&self) -> &Self::Target { &self.inner } } -impl Permit { - pub fn new(inner: SemaphorePermit<'static>, f: F) -> Self { - Self { inner: Some(inner), destruct: Some(f) } +impl Permit { + pub fn new(inner: SemaphorePermit<'static>, f: F) -> Self + where + F: Future + 'static + Send, + { + Self { inner: Some(inner), destruct: Some(f.boxed()) } } - fn dropping(&mut self) { - if let Some(f) = self.destruct.take() { - f(); - } - if let Some(p) = self.inner.take() { - mem::drop(p); + fn dropping(&mut self) -> impl Future + 'static { + let inner = self.inner.take(); + let destruct = self.destruct.take(); + + async move { + if let Some(f) = destruct { + f.await; + } + if let Some(p) = inner { + mem::drop(p); + } } } } -impl Drop for Permit { - fn drop(&mut self) { self.dropping(); } +impl Drop for Permit { + fn drop(&mut self) { tokio::spawn(self.dropping()); } } -impl UserData for Permit { +impl UserData for Permit { fn add_methods>(methods: &mut M) { - methods.add_method_mut("drop", |_, me, ()| Ok(me.dropping())); + methods.add_async_method_mut("drop", |_, mut me, ()| async move { Ok(me.dropping().await) }); } } diff --git a/yazi-binding/src/runtime.rs b/yazi-binding/src/runtime.rs index 2eec279b..24c0ae96 100644 --- a/yazi-binding/src/runtime.rs +++ b/yazi-binding/src/runtime.rs @@ -3,10 +3,11 @@ use std::collections::VecDeque; use hashbrown::HashMap; use mlua::Function; -#[derive(Debug, Default)] +#[derive(Debug)] pub struct Runtime { - frames: VecDeque, - blocks: HashMap>, + frames: VecDeque, + blocks: HashMap>, + pub initing: bool, } #[derive(Debug)] @@ -16,10 +17,13 @@ struct RuntimeFrame { } impl Runtime { - pub fn new(id: &str) -> Self { + pub fn new() -> Self { Self { frames: <_>::default(), blocks: <_>::default(), initing: true } } + + pub fn new_isolate(id: &str) -> Self { Self { - frames: VecDeque::from([RuntimeFrame { id: id.to_owned(), calls: 0 }]), - ..Default::default() + frames: VecDeque::from([RuntimeFrame { id: id.to_owned(), calls: 0 }]), + blocks: <_>::default(), + initing: false, } } @@ -49,7 +53,7 @@ impl Runtime { if let Some(v) = self.blocks.get_mut(&cur.id) { v.push(f); } else { - self.blocks.insert(cur.id.to_owned(), vec![f]); + self.blocks.insert(cur.id.clone(), vec![f]); } true } diff --git a/yazi-binding/src/scheme.rs b/yazi-binding/src/scheme.rs index defec5fc..53f686b7 100644 --- a/yazi-binding/src/scheme.rs +++ b/yazi-binding/src/scheme.rs @@ -4,7 +4,7 @@ use mlua::{UserData, UserDataFields, Value}; use yazi_fs::FsScheme; use yazi_shared::scheme::SchemeLike; -use crate::{Url, cached_field}; +use crate::{Path, cached_field}; pub struct Scheme { inner: yazi_shared::scheme::Scheme, @@ -20,15 +20,15 @@ impl Deref for Scheme { } impl Scheme { - pub fn new(scheme: &yazi_shared::scheme::Scheme) -> Self { - Self { inner: scheme.clone(), v_kind: None, v_cache: None } + pub fn new(scheme: impl Into) -> Self { + Self { inner: scheme.into(), v_kind: None, v_cache: None } } } impl UserData for Scheme { fn add_fields>(fields: &mut F) { - cached_field!(fields, kind, |_, me| Ok(me.kind())); - cached_field!(fields, cache, |_, me| Ok(me.cache().map(Url::new))); + cached_field!(fields, kind, |_, me| Ok(me.kind().as_str())); + cached_field!(fields, cache, |_, me| Ok(me.cache().map(Path::new))); fields.add_field_method_get("is_virtual", |_, me| Ok(me.is_virtual())); } diff --git a/yazi-binding/src/style.rs b/yazi-binding/src/style.rs index 3403619e..ddcaf181 100644 --- a/yazi-binding/src/style.rs +++ b/yazi-binding/src/style.rs @@ -1,4 +1,6 @@ -use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; +use mlua::{AnyUserData, ExternalError, IntoLua, Lua, LuaSerdeExt, MetaMethod, Table, UserData, UserDataMethods, Value}; + +use crate::SER_OPT; #[derive(Clone, Copy, Default)] pub struct Style(pub ratatui::style::Style); @@ -34,6 +36,9 @@ impl UserData for Style { fn add_methods>(methods: &mut M) { crate::impl_style_shorthands!(methods, 0); + methods + .add_method("raw", |lua, me, ()| lua.to_value_with(&yazi_config::Style::from(me.0), SER_OPT)); + methods.add_function_mut("patch", |_, (ud, value): (AnyUserData, Value)| { { let mut me = ud.borrow_mut::()?; diff --git a/yazi-binding/src/url.rs b/yazi-binding/src/url.rs index 4c75f7ea..44af8778 100644 --- a/yazi-binding/src/url.rs +++ b/yazi-binding/src/url.rs @@ -1,16 +1,19 @@ use std::ops::Deref; -use mlua::{AnyUserData, ExternalError, FromLua, Lua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, Value}; -use yazi_fs::{FsHash64, FsHash128}; -use yazi_shared::{IntoOsStr, scheme::SchemeLike, url::{AsUrl, UrlCow, UrlLike}}; +use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, Value}; +use yazi_fs::{FsHash64, FsHash128, FsUrl}; +use yazi_shared::{path::{PathLike, StripPrefixError}, scheme::SchemeCow, strand::{StrandLike, ToStrand}, url::{AsUrl, UrlCow, UrlLike}}; -use crate::{Scheme, cached_field, deprecate}; +use crate::{Path, Scheme, cached_field, deprecate}; pub type UrlRef = UserDataRef; +const EXPECTED: &str = "expected a string, Url, or Path"; + pub struct Url { inner: yazi_shared::url::UrlBuf, + v_path: Option, v_name: Option, v_stem: Option, v_ext: Option, @@ -20,6 +23,8 @@ pub struct Url { v_scheme: Option, v_domain: Option, + + v_cache: Option, } impl Deref for Url { @@ -28,10 +33,6 @@ impl Deref for Url { fn deref(&self) -> &Self::Target { &self.inner } } -impl AsRef for Url { - fn as_ref(&self) -> &yazi_shared::url::UrlBuf { &self.inner } -} - impl AsUrl for Url { fn as_url(&self) -> yazi_shared::url::Url<'_> { self.inner.as_url() } } @@ -48,12 +49,14 @@ impl From for yazi_shared::url::UrlBufCov { fn from(value: Url) -> Self { Self(value.inner) } } +impl From for yazi_shared::url::UrlCow<'_> { + fn from(value: Url) -> Self { value.inner.into() } +} + impl TryFrom<&[u8]> for Url { type Error = mlua::Error; - fn try_from(value: &[u8]) -> mlua::Result { - Ok(Self::new(UrlCow::try_from(value)?.into_owned())) - } + fn try_from(value: &[u8]) -> mlua::Result { Ok(Self::new(UrlCow::try_from(value)?)) } } impl Url { @@ -61,6 +64,7 @@ impl Url { Self { inner: url.into(), + v_path: None, v_name: None, v_stem: None, v_ext: None, @@ -70,6 +74,8 @@ impl Url { v_scheme: None, v_domain: None, + + v_cache: None, } } @@ -78,13 +84,82 @@ impl Url { "Url", lua.create_function(|_, value: Value| { Ok(match value { - Value::String(s) => Self::try_from(s.as_bytes().as_ref())?, - Value::UserData(ud) => Self::new(ud.borrow::()?.inner.clone()), - _ => Err("Expected a string or a Url".into_lua_err())?, + Value::String(s) => Self::try_from(&*s.as_bytes())?, + Value::UserData(ud) => { + if let Ok(url) = ud.borrow::() { + Self::new(&url.inner) + } else if let Ok(path) = ud.borrow::() { + Self::new(path.as_os().into_lua_err()?) + } else { + Err(EXPECTED.into_lua_err())? + } + } + _ => Err(EXPECTED.into_lua_err())?, }) })?, ) } + + fn ends_with(&self, child: Value) -> mlua::Result { + match child { + Value::String(s) => self.try_ends_with(UrlCow::try_from(&*s.as_bytes())?).into_lua_err(), + Value::UserData(ud) => self.try_ends_with(&*ud.borrow::()?).into_lua_err(), + _ => Err("must be a string or Url".into_lua_err())?, + } + } + + fn hash(&self, long: Option) -> mlua::Result { + Ok(if long.unwrap_or(false) { + format!("{:x}", self.hash_u128()) + } else { + format!("{:x}", self.hash_u64()) + }) + } + + fn join(&self, lua: &Lua, other: Value) -> mlua::Result { + match other { + Value::String(s) => { + let b = s.as_bytes(); + let (scheme, path) = SchemeCow::parse(&b)?; + if scheme == self.scheme() { + Self::new(self.try_join(path).into_lua_err()?).into_lua(lua) + } else { + Self::new(UrlCow::try_from((scheme, path))?).into_lua(lua) + } + } + Value::UserData(ref ud) => { + let url = ud.borrow::()?; + if url.scheme() == self.scheme() { + Self::new(self.try_join(url.loc()).into_lua_err()?).into_lua(lua) + } else { + Ok(other) + } + } + _ => Err("must be a string or Url".into_lua_err())?, + } + } + + fn starts_with(&self, base: Value) -> mlua::Result { + match base { + Value::String(s) => self.try_starts_with(UrlCow::try_from(&*s.as_bytes())?).into_lua_err(), + Value::UserData(ud) => self.try_starts_with(&*ud.borrow::()?).into_lua_err(), + _ => Err("must be a string or Url".into_lua_err())?, + } + } + + fn strip_prefix(&self, base: Value) -> mlua::Result> { + let strip = match base { + Value::String(s) => self.try_strip_prefix(UrlCow::try_from(&*s.as_bytes())?), + Value::UserData(ud) => self.try_strip_prefix(&*ud.borrow::()?), + _ => Err("must be a string or Url".into_lua_err())?, + }; + + Ok(match strip { + Ok(p) => Some(Path::new(p)), + Err(StripPrefixError::Exotic | StripPrefixError::NotPrefix) => None, + Err(e @ StripPrefixError::WrongEncoding) => Err(e.into_lua_err())?, + }) + } } impl FromLua for Url { @@ -98,27 +173,32 @@ impl FromLua for Url { impl UserData for Url { fn add_fields>(fields: &mut F) { + cached_field!(fields, path, |_, me| Ok(Path::new(me.loc()))); cached_field!(fields, name, |lua, me| { - me.name().map(|s| lua.create_string(s.as_encoded_bytes())).transpose() + me.name().map(|s| lua.create_string(s.encoded_bytes())).transpose() }); cached_field!(fields, stem, |lua, me| { - me.stem().map(|s| lua.create_string(s.as_encoded_bytes())).transpose() + me.stem().map(|s| lua.create_string(s.encoded_bytes())).transpose() }); cached_field!(fields, ext, |lua, me| { - me.ext().map(|s| lua.create_string(s.as_encoded_bytes())).transpose() + me.ext().map(|s| lua.create_string(s.encoded_bytes())).transpose() + }); + cached_field!(fields, urn, |_, me| Ok(Path::new(me.urn()))); + cached_field!(fields, base, |_, me| { + Ok(Some(me.base()).filter(|u| !u.loc().is_empty()).map(Self::new)) }); cached_field!(fields, parent, |_, me| Ok(me.parent().map(Self::new))); - cached_field!(fields, urn, |_, me| Ok(super::Path::new(me.urn()))); - cached_field!(fields, base, |_, me| Ok(me.base().map(Self::new))); - cached_field!(fields, scheme, |_, me| Ok(Scheme::new(&me.scheme))); + cached_field!(fields, scheme, |_, me| Ok(Scheme::new(me.scheme()))); cached_field!(fields, domain, |lua, me| { - me.scheme.domain().map(|s| lua.create_string(s)).transpose() + me.scheme().domain().map(|s| lua.create_string(s)).transpose() }); + cached_field!(fields, cache, |_, me| Ok(me.cache().map(Path::new))); + fields.add_field_method_get("frag", |lua, me| { deprecate!(lua, "`frag` property of Url is deprecated and renamed to `domain`, please use the new name instead, in your {}"); - me.scheme.domain().map(|s| lua.create_string(s)).transpose() + me.scheme().domain().map(|s| lua.create_string(s)).transpose() }); fields.add_field_method_get("is_regular", |_, me| Ok(me.is_regular())); @@ -129,59 +209,23 @@ impl UserData for Url { } fn add_methods>(methods: &mut M) { - methods.add_method("hash", |_, me, long: Option| { - Ok(if long.unwrap_or(false) { - format!("{:x}", me.hash_u128()) - } else { - format!("{:x}", me.hash_u64()) - }) - }); - methods.add_method("join", |_, me, other: Value| { - Ok(Self::new(match other { - Value::String(s) => me.join(s.as_bytes().into_os_str()?), - Value::UserData(ud) => { - let url = ud.borrow::()?; - if !me.scheme.covariant(&url.scheme) { - return Err("cannot join Urls with different schemes".into_lua_err()); - } - me.join(&url.loc) - } - _ => Err("must be a string or Url".into_lua_err())?, - })) - }); - methods.add_method("starts_with", |_, me, base: Value| { - Ok(match base { - Value::String(s) => me.loc.starts_with(s.as_bytes().into_os_str()?), - Value::UserData(ud) => me.starts_with(&*ud.borrow::()?), - _ => Err("must be a string or Url".into_lua_err())?, - }) - }); - methods.add_method("ends_with", |_, me, child: Value| { - Ok(match child { - Value::String(s) => me.loc.ends_with(s.as_bytes().into_os_str()?), - Value::UserData(ud) => me.ends_with(&*ud.borrow::()?), - _ => Err("must be a string or Url".into_lua_err())?, - }) - }); - methods.add_method("strip_prefix", |_, me, base: Value| { - let path = match base { - Value::String(s) => me.loc().strip_prefix(&s.as_bytes().into_os_str()?).map(Into::into), - Value::UserData(ud) => me.strip_prefix(&*ud.borrow::()?), - _ => Err("must be a string or Url".into_lua_err())?, - }; - Ok(path.map(Self::new)) // TODO: return `Path` instead of `Url` - }); + methods.add_method("ends_with", |_, me, child: Value| me.ends_with(child)); + methods.add_method("hash", |_, me, long: Option| me.hash(long)); + methods.add_method("join", |lua, me, other: Value| me.join(lua, other)); + methods.add_method("starts_with", |_, me, base: Value| me.starts_with(base)); + methods.add_method("strip_prefix", |_, me, base: Value| me.strip_prefix(base)); methods.add_function_mut("into_search", |_, (ud, domain): (AnyUserData, mlua::String)| { - Ok(Self::new(ud.take::()?.inner.into_search(domain.to_str()?))) + let url = ud.take::()?.inner.into_search(domain.to_str()?).into_lua_err()?; + Ok(Self::new(url)) }); methods.add_meta_method(MetaMethod::Eq, |_, me, other: UrlRef| Ok(me.inner == other.inner)); methods.add_meta_method(MetaMethod::ToString, |lua, me, ()| { - lua.create_string(me.os_str().as_encoded_bytes()) + lua.create_string(me.to_strand().encoded_bytes()) }); methods.add_meta_method(MetaMethod::Concat, |lua, lhs, rhs: mlua::String| { - lua.create_string([lhs.os_str().as_encoded_bytes(), &rhs.as_bytes()].concat()) + lua.create_string([lhs.to_strand().encoded_bytes(), &rhs.as_bytes()].concat()) }); } } diff --git a/yazi-binding/src/urn.rs b/yazi-binding/src/urn.rs deleted file mode 100644 index 6463ca87..00000000 --- a/yazi-binding/src/urn.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::ops::Deref; - -use mlua::{ExternalError, FromLua, Lua, UserData, Value}; -use yazi_shared::path::PathBufDyn; - -pub struct Path(pub PathBufDyn); - -impl Deref for Path { - type Target = PathBufDyn; - - fn deref(&self) -> &Self::Target { &self.0 } -} - -impl Path { - pub fn new(urn: impl Into) -> Self { Self(urn.into()) } -} - -impl FromLua for Path { - fn from_lua(value: Value, _: &Lua) -> mlua::Result { - Ok(match value { - Value::UserData(ud) => ud.take()?, - _ => Err("Expected a Path".into_lua_err())?, - }) - } -} - -impl UserData for Path {} diff --git a/yazi-binding/src/utils.rs b/yazi-binding/src/utils.rs index 52cada49..c48f3173 100644 --- a/yazi-binding/src/utils.rs +++ b/yazi-binding/src/utils.rs @@ -1,4 +1,7 @@ -use mlua::{IntoLua, Lua, Table, Value}; +use mlua::{IntoLua, Lua, SerializeOptions, Table, Value}; + +pub const SER_OPT: SerializeOptions = + SerializeOptions::new().serialize_none_to_null(false).serialize_unit_to_null(false); pub fn get_metatable(lua: &Lua, value: impl IntoLua) -> mlua::Result
{ let (_, mt): (Value, Table) = unsafe { diff --git a/yazi-boot/Cargo.toml b/yazi-boot/Cargo.toml index 6670c893..c218bd0f 100644 --- a/yazi-boot/Cargo.toml +++ b/yazi-boot/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-boot" -version = "25.9.15" +version = "26.1.4" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -8,27 +8,29 @@ description = "Yazi bootstrapper" homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" +[lints] +workspace = true + [dependencies] -yazi-adapter = { path = "../yazi-adapter", version = "25.9.15" } -yazi-config = { path = "../yazi-config", version = "25.9.15" } -yazi-fs = { path = "../yazi-fs", version = "25.9.15" } -yazi-macro = { path = "../yazi-macro", version = "25.9.15" } -yazi-shared = { path = "../yazi-shared", version = "25.9.15" } -yazi-vfs = { path = "../yazi-vfs", version = "25.9.15" } +yazi-adapter = { path = "../yazi-adapter", version = "26.1.4" } +yazi-config = { path = "../yazi-config", version = "26.1.4" } +yazi-fs = { path = "../yazi-fs", version = "26.1.4" } +yazi-macro = { path = "../yazi-macro", version = "26.1.4" } +yazi-shared = { path = "../yazi-shared", version = "26.1.4" } +yazi-vfs = { path = "../yazi-vfs", version = "26.1.4" } # External dependencies clap = { workspace = true } futures = { workspace = true } hashbrown = { workspace = true } regex = { workspace = true } -serde = { workspace = true } [build-dependencies] -yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "26.1.4" } # External dependencies clap = { workspace = true } -clap_complete = "4.5.60" +clap_complete = "4.5.64" clap_complete_fig = "4.5.2" clap_complete_nushell = "4.5.10" vergen-gitcl = { version = "1.0.8", features = [ "build", "rustc" ] } diff --git a/yazi-boot/README.md b/yazi-boot/README.md new file mode 100644 index 00000000..ae559d9f --- /dev/null +++ b/yazi-boot/README.md @@ -0,0 +1,5 @@ +# yazi-boot + +This crate is part of [Yazi][source], and it is not supposed to be used outside, as there are no guarantees about the stability of its API. + +[source]: https://github.com/sxyazi/yazi diff --git a/yazi-boot/src/actions/debug.rs b/yazi-boot/src/actions/debug.rs index b64302f8..b77ff130 100644 --- a/yazi-boot/src/actions/debug.rs +++ b/yazi-boot/src/actions/debug.rs @@ -2,7 +2,8 @@ use std::{env, ffi::OsStr, fmt::Write, path::Path}; use regex::Regex; use yazi_adapter::Mux; -use yazi_config::YAZI; +use yazi_config::{THEME, YAZI}; +use yazi_fs::Xdg; use yazi_shared::timestamp_us; use super::Actions; @@ -19,12 +20,20 @@ impl Actions { writeln!(s, "\nYa")?; writeln!(s, " Version: {}", Self::process_output("ya", "--version"))?; + writeln!(s, "\nConfig")?; + writeln!(s, " Yazi : {}", Self::config_state("yazi"))?; + writeln!(s, " Keymap : {}", Self::config_state("keymap"))?; + writeln!(s, " Theme : {}", Self::config_state("theme"))?; + writeln!(s, " VFS : {}", Self::config_state("vfs"))?; + writeln!(s, " Package : {}", Self::config_state("package"))?; + writeln!(s, " Dark/light flavor: {:?} / {:?}", THEME.flavor.dark, THEME.flavor.light)?; + writeln!(s, "\nEmulator")?; writeln!(s, " TERM : {:?}", env::var_os("TERM"))?; writeln!(s, " TERM_PROGRAM : {:?}", env::var_os("TERM_PROGRAM"))?; writeln!(s, " TERM_PROGRAM_VERSION: {:?}", env::var_os("TERM_PROGRAM_VERSION"))?; writeln!(s, " Brand.from_env : {:?}", yazi_adapter::Brand::from_env())?; - writeln!(s, " Emulator.detect : {:?}", yazi_adapter::EMULATOR)?; + writeln!(s, " Emulator.detect : {:?}", &*yazi_adapter::EMULATOR)?; writeln!(s, "\nAdapter")?; writeln!(s, " Adapter.matches : {:?}", yazi_adapter::ADAPTOR)?; @@ -115,6 +124,16 @@ impl Actions { Ok(s) } + fn config_state(name: &str) -> String { + let p = Xdg::config_dir().join(format!("{name}.toml")); + match std::fs::read_to_string(&p) { + Ok(s) if s.is_empty() => format!("{} (empty)", p.display()), + Ok(s) if s.trim().is_empty() => format!("{} (whitespaces)", p.display()), + Ok(s) => format!("{} ({} chars)", p.display(), s.chars().count()), + Err(e) => format!("{} ({e})", p.display()), + } + } + fn process_output(name: impl AsRef, arg: impl AsRef) -> String { match std::process::Command::new(&name).arg(arg).output() { Ok(out) if out.status.success() => { diff --git a/yazi-boot/src/boot.rs b/yazi-boot/src/boot.rs index b08fb59d..a9b48bb7 100644 --- a/yazi-boot/src/boot.rs +++ b/yazi-boot/src/boot.rs @@ -2,15 +2,14 @@ use std::path::PathBuf; use futures::executor::block_on; use hashbrown::HashSet; -use serde::Serialize; -use yazi_fs::{CWD, Xdg, path::expand_url}; -use yazi_shared::{path::{PathBufDyn, PathLike}, url::{UrlBuf, UrlCow, UrlLike}}; +use yazi_fs::{CWD, Xdg, path::clean_url}; +use yazi_shared::{strand::StrandBuf, url::{UrlBuf, UrlLike}}; use yazi_vfs::provider; -#[derive(Debug, Default, Serialize)] +#[derive(Debug, Default)] pub struct Boot { pub cwds: Vec, - pub files: Vec, + pub files: Vec, pub local_events: HashSet, pub remote_events: HashSet, @@ -22,25 +21,28 @@ pub struct Boot { } impl Boot { - async fn parse_entries(entries: &[UrlBuf]) -> (Vec, Vec) { + async fn parse_entries(entries: &[UrlBuf]) -> (Vec, Vec) { if entries.is_empty() { - return (vec![CWD.load().as_ref().clone()], vec![PathBufDyn::os_default()]); + return (vec![CWD.load().as_ref().clone()], vec![Default::default()]); } - async fn go(entry: &UrlBuf) -> (UrlBuf, PathBufDyn) { - let mut entry = expand_url(entry); - if let Ok(u @ UrlCow::Owned { .. }) = provider::absolute(&entry).await { + async fn go(entry: &UrlBuf) -> (UrlBuf, StrandBuf) { + let mut entry = clean_url(entry); + + if let Ok(u) = provider::absolute(&entry).await + && u.is_owned() + { entry = u.into_owned(); } let Some((parent, child)) = entry.pair() else { - return (entry, PathBufDyn::os_default()); + return (entry, Default::default()); }; if provider::metadata(&entry).await.is_ok_and(|m| m.is_file()) { - (parent.into(), child.owned()) + (parent.into(), child.into()) } else { - (entry, PathBufDyn::os_default()) + (entry, Default::default()) } } diff --git a/yazi-build/Cargo.toml b/yazi-build/Cargo.toml index d21e1cea..348387a5 100644 --- a/yazi-build/Cargo.toml +++ b/yazi-build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-build" -version = "25.9.15" +version = "26.1.4" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -8,6 +8,9 @@ description = "Yazi build system" homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" +[lints] +workspace = true + [profile.release] codegen-units = 1 lto = true @@ -15,7 +18,7 @@ panic = "abort" strip = true [build-dependencies] -yazi-term = { path = "../yazi-term", version = "25.9.15" } +yazi-term = { path = "../yazi-term", version = "26.1.4" } [[bin]] name = "yazi-build" diff --git a/yazi-build/README.md b/yazi-build/README.md new file mode 100644 index 00000000..4d40eb8e --- /dev/null +++ b/yazi-build/README.md @@ -0,0 +1,5 @@ +# yazi-build + +This crate is part of [Yazi][source], and it is not supposed to be used outside, as there are no guarantees about the stability of its API. + +[source]: https://github.com/sxyazi/yazi diff --git a/yazi-cli/Cargo.toml b/yazi-cli/Cargo.toml index 2fdbe660..3b4ec04f 100644 --- a/yazi-cli/Cargo.toml +++ b/yazi-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-cli" -version = "25.9.15" +version = "26.1.4" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -8,6 +8,9 @@ description = "Yazi command-line interface" homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" +[lints] +workspace = true + [profile.release] codegen-units = 1 lto = true @@ -19,11 +22,11 @@ inherits = "release" panic = "unwind" [dependencies] -yazi-boot = { path = "../yazi-boot", version = "25.9.15" } -yazi-dds = { path = "../yazi-dds", version = "25.9.15" } -yazi-fs = { path = "../yazi-fs", version = "25.9.15" } -yazi-macro = { path = "../yazi-macro", version = "25.9.15" } -yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-boot = { path = "../yazi-boot", version = "26.1.4" } +yazi-dds = { path = "../yazi-dds", version = "26.1.4" } +yazi-fs = { path = "../yazi-fs", version = "26.1.4" } +yazi-macro = { path = "../yazi-macro", version = "26.1.4" } +yazi-shared = { path = "../yazi-shared", version = "26.1.4" } # External dependencies anyhow = { workspace = true } @@ -36,12 +39,12 @@ toml = { workspace = true } twox-hash = { workspace = true } [build-dependencies] -yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "26.1.4" } # External build dependencies anyhow = { workspace = true } clap = { workspace = true } -clap_complete = "4.5.60" +clap_complete = "4.5.64" clap_complete_fig = "4.5.2" clap_complete_nushell = "4.5.10" serde_json = { workspace = true } diff --git a/yazi-cli/README.md b/yazi-cli/README.md new file mode 100644 index 00000000..646e0c73 --- /dev/null +++ b/yazi-cli/README.md @@ -0,0 +1,5 @@ +# yazi-cli + +This crate is part of [Yazi][source], and it is not supposed to be used outside, as there are no guarantees about the stability of its API. + +[source]: https://github.com/sxyazi/yazi diff --git a/yazi-cli/src/main.rs b/yazi-cli/src/main.rs index 06776ea7..a2a15be2 100644 --- a/yazi-cli/src/main.rs +++ b/yazi-cli/src/main.rs @@ -6,10 +6,14 @@ use std::process::ExitCode; use clap::Parser; use yazi_macro::{errln, outln}; +use yazi_shared::LOCAL_SET; #[tokio::main] async fn main() -> ExitCode { - match run().await { + yazi_shared::init(); + yazi_fs::init(); + + match LOCAL_SET.run_until(run()).await { Ok(()) => ExitCode::SUCCESS, Err(e) => { for cause in e.chain() { @@ -26,9 +30,6 @@ async fn main() -> ExitCode { } async fn run() -> anyhow::Result<()> { - yazi_shared::init(); - yazi_fs::init(); - if std::env::args_os().nth(1).is_some_and(|s| s == "-V" || s == "--version") { outln!( "Ya {} ({} {})", diff --git a/yazi-cli/src/package/delete.rs b/yazi-cli/src/package/delete.rs index 02782bc0..4968e143 100644 --- a/yazi-cli/src/package/delete.rs +++ b/yazi-cli/src/package/delete.rs @@ -1,5 +1,5 @@ use anyhow::{Context, Result}; -use yazi_fs::{ok_or_not_found, provider::{DirReader, FileHolder, Provider, local::Local}}; +use yazi_fs::{ok_or_not_found, provider::{Provider, local::Local}}; use yazi_macro::outln; use super::Dependency; @@ -23,9 +23,9 @@ impl Dependency { pub(super) async fn delete_assets(&self) -> Result<()> { let assets = self.target().join("assets"); - match Local.read_dir(&assets).await { + match tokio::fs::read_dir(&assets).await { Ok(mut it) => { - while let Some(entry) = it.next().await? { + while let Some(entry) = it.next_entry().await? { remove_sealed(&entry.path()) .await .with_context(|| format!("failed to remove `{}`", entry.path().display()))?; @@ -35,7 +35,7 @@ impl Dependency { Err(e) => Err(e).context(format!("failed to read `{}`", assets.display()))?, }; - Local.remove_dir_clean(assets).await; + Local::regular(&assets).remove_dir_clean().await; Ok(()) } @@ -49,7 +49,7 @@ impl Dependency { .with_context(|| format!("failed to delete `{}`", path.display()))?; } - if ok_or_not_found(Local.remove_dir(&dir).await).is_ok() { + if ok_or_not_found(Local::regular(&dir).remove_dir().await).is_ok() { outln!("Done!")?; } else { outln!( diff --git a/yazi-cli/src/package/dependency.rs b/yazi-cli/src/package/dependency.rs index aee07cca..ccb14696 100644 --- a/yazi-cli/src/package/dependency.rs +++ b/yazi-cli/src/package/dependency.rs @@ -3,7 +3,8 @@ use std::{io::BufWriter, path::{Path, PathBuf}, str::FromStr}; use anyhow::{Result, bail}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use twox_hash::XxHash3_128; -use yazi_fs::{Xdg, provider::{DirReader, FileHolder, Provider, local::Local}}; +use yazi_fs::Xdg; +use yazi_macro::ok_or_not_found; use yazi_shared::BytesExt; #[derive(Clone, Default)] @@ -62,11 +63,11 @@ impl Dependency { } pub(super) async fn plugin_files(dir: &Path) -> std::io::Result> { - let mut it = Local.read_dir(dir).await?; + let mut it = ok_or_not_found!(tokio::fs::read_dir(dir).await, return Ok(vec![])); let mut files: Vec = ["LICENSE", "README.md", "main.lua"].into_iter().map(Into::into).collect(); - while let Some(entry) = it.next().await? { - if let Ok(name) = entry.name().into_owned().into_string() + while let Some(entry) = it.next_entry().await? { + if let Ok(name) = entry.file_name().into_string() && let Some(stripped) = name.strip_suffix(".lua") && stripped != "main" && stripped.as_bytes().kebab_cased() diff --git a/yazi-cli/src/package/deploy.rs b/yazi-cli/src/package/deploy.rs index 84d758bc..2cc10ac5 100644 --- a/yazi-cli/src/package/deploy.rs +++ b/yazi-cli/src/package/deploy.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; use anyhow::{Context, Result}; -use yazi_fs::provider::{DirReader, FileHolder, Provider, local::Local}; +use yazi_fs::provider::{Provider, local::Local}; use yazi_macro::outln; use super::Dependency; @@ -20,7 +20,7 @@ impl Dependency { self.hash_check().await?; } - Local.create_dir_all(&to).await?; + Local::regular(&to).create_dir_all().await?; self.delete_assets().await?; let res1 = Self::deploy_assets(from.join("assets"), to.join("assets")).await; @@ -30,7 +30,7 @@ impl Dependency { self.delete_sources().await?; } - Local.remove_dir_clean(to).await; + Local::regular(&to).remove_dir_clean().await; self.hash = self.hash().await?; res2?; res1?; @@ -40,11 +40,11 @@ impl Dependency { } async fn deploy_assets(from: PathBuf, to: PathBuf) -> Result<()> { - match Local.read_dir(&from).await { + match tokio::fs::read_dir(&from).await { Ok(mut it) => { - Local.create_dir_all(&to).await?; - while let Some(entry) = it.next().await? { - let (src, dist) = (entry.path(), to.join(entry.name())); + Local::regular(&to).create_dir_all().await?; + while let Some(entry) = it.next_entry().await? { + let (src, dist) = (entry.path(), to.join(entry.file_name())); copy_and_seal(&src, &dist).await.with_context(|| { format!("failed to copy `{}` to `{}`", src.display(), dist.display()) })?; diff --git a/yazi-cli/src/package/hash.rs b/yazi-cli/src/package/hash.rs index 88430f01..37fc5350 100644 --- a/yazi-cli/src/package/hash.rs +++ b/yazi-cli/src/package/hash.rs @@ -1,6 +1,6 @@ use anyhow::{Context, Result, bail}; use twox_hash::XxHash3_128; -use yazi_fs::provider::{DirReader, FileHolder, Provider, local::Local}; +use yazi_fs::provider::local::Local; use yazi_macro::ok_or_not_found; use super::Dependency; @@ -15,17 +15,17 @@ impl Dependency { for file in files { h.write(file.as_bytes()); h.write(b"VpvFw9Atb7cWGOdqhZCra634CcJJRlsRl72RbZeV0vpG1\0"); - h.write(&ok_or_not_found!(Local.read(dir.join(file)).await)); + h.write(&ok_or_not_found!(Local::regular(&dir.join(file)).read().await)); } let mut assets = vec![]; - match Local.read_dir(dir.join("assets")).await { + match tokio::fs::read_dir(dir.join("assets")).await { Ok(mut it) => { - while let Some(entry) = it.next().await? { - let Ok(name) = entry.name().into_owned().into_string() else { + while let Some(entry) = it.next_entry().await? { + let Ok(name) = entry.file_name().into_string() else { bail!("asset path is not valid UTF-8: {}", entry.path().display()); }; - assets.push((name, Local.read(entry.path()).await?)); + assets.push((name, Local::regular(&entry.path()).read().await?)); } } Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} diff --git a/yazi-cli/src/package/mod.rs b/yazi-cli/src/package/mod.rs index e07284f0..44c4f203 100644 --- a/yazi-cli/src/package/mod.rs +++ b/yazi-cli/src/package/mod.rs @@ -4,9 +4,13 @@ use anyhow::Context; use yazi_fs::Xdg; pub(super) fn init() -> anyhow::Result<()> { - let root = Xdg::state_dir().join("packages"); - std::fs::create_dir_all(&root) - .with_context(|| format!("failed to create packages directory: {root:?}"))?; + let packages_dir = Xdg::state_dir().join("packages"); + std::fs::create_dir_all(&packages_dir) + .with_context(|| format!("failed to create packages directory: {packages_dir:?}"))?; + + let config_dir = Xdg::config_dir(); + std::fs::create_dir_all(&config_dir) + .with_context(|| format!("failed to create config directory: {config_dir:?}"))?; Ok(()) } diff --git a/yazi-cli/src/package/package.rs b/yazi-cli/src/package/package.rs index 617635da..dc654bc7 100644 --- a/yazi-cli/src/package/package.rs +++ b/yazi-cli/src/package/package.rs @@ -15,7 +15,7 @@ pub(crate) struct Package { impl Package { pub(crate) async fn load() -> Result { - let s = ok_or_not_found!(Local.read_to_string(Self::toml()).await); + let s = ok_or_not_found!(Local::regular(&Self::toml()).read_to_string().await); Ok(toml::from_str(&s)?) } @@ -132,7 +132,7 @@ impl Package { async fn save(&self) -> Result<()> { let s = toml::to_string_pretty(self)?; - Local.write(Self::toml(), s).await.context("Failed to write package.toml") + Local::regular(&Self::toml()).write(s).await.context("Failed to write package.toml") } fn toml() -> PathBuf { Xdg::config_dir().join("package.toml") } diff --git a/yazi-cli/src/shared/shared.rs b/yazi-cli/src/shared/shared.rs index f2077dd9..387b5ccb 100644 --- a/yazi-cli/src/shared/shared.rs +++ b/yazi-cli/src/shared/shared.rs @@ -6,19 +6,19 @@ use yazi_macro::ok_or_not_found; #[inline] pub async fn must_exists(path: impl AsRef) -> bool { - Local.symlink_metadata(path).await.is_ok() + Local::regular(&path).symlink_metadata().await.is_ok() } #[inline] pub async fn maybe_exists(path: impl AsRef) -> bool { - match Local.symlink_metadata(path).await { + match Local::regular(&path).symlink_metadata().await { Ok(_) => true, Err(e) => e.kind() != std::io::ErrorKind::NotFound, } } pub async fn copy_and_seal(from: &Path, to: &Path) -> io::Result<()> { - let b = Local.read(from).await?; + let b = Local::regular(from).read().await?; ok_or_not_found!(remove_sealed(to).await); let mut file = Gate::default().create_new(true).write(true).truncate(true).open(to).await?; @@ -31,7 +31,6 @@ pub async fn copy_and_seal(from: &Path, to: &Path) -> io::Result<()> { Ok(()) } -// TODO: use `yazi_fs` instead of `tokio::fs` pub async fn remove_sealed(p: &Path) -> io::Result<()> { #[cfg(windows)] { @@ -40,5 +39,5 @@ pub async fn remove_sealed(p: &Path) -> io::Result<()> { tokio::fs::set_permissions(p, perm).await?; } - Local.remove_file(p).await + Local::regular(p).remove_file().await } diff --git a/yazi-codegen/Cargo.toml b/yazi-codegen/Cargo.toml index ff14e7d7..7513e988 100644 --- a/yazi-codegen/Cargo.toml +++ b/yazi-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-codegen" -version = "25.9.15" +version = "26.1.4" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -8,10 +8,13 @@ description = "Yazi code generator" homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" +[lints] +workspace = true + [lib] proc-macro = true [dependencies] # External dependencies -syn = { version = "2.0.108", features = [ "full" ] } -quote = "1.0.41" +syn = { version = "2.0.113", features = [ "full" ] } +quote = "1.0.42" diff --git a/yazi-codegen/README.md b/yazi-codegen/README.md new file mode 100644 index 00000000..f7a66057 --- /dev/null +++ b/yazi-codegen/README.md @@ -0,0 +1,5 @@ +# yazi-codegen + +This crate is part of [Yazi][source], and it is not supposed to be used outside, as there are no guarantees about the stability of its API. + +[source]: https://github.com/sxyazi/yazi diff --git a/yazi-config/Cargo.toml b/yazi-config/Cargo.toml index 382716fe..d69aba80 100644 --- a/yazi-config/Cargo.toml +++ b/yazi-config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-config" -version = "25.9.15" +version = "26.1.4" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -8,12 +8,15 @@ description = "Yazi configuration file parser" homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" +[lints] +workspace = true + [dependencies] -yazi-codegen = { path = "../yazi-codegen", version = "25.9.15" } -yazi-fs = { path = "../yazi-fs", version = "25.9.15" } -yazi-macro = { path = "../yazi-macro", version = "25.9.15" } -yazi-shared = { path = "../yazi-shared", version = "25.9.15" } -yazi-term = { path = "../yazi-term", version = "25.9.15" } +yazi-codegen = { path = "../yazi-codegen", version = "26.1.4" } +yazi-fs = { path = "../yazi-fs", version = "26.1.4" } +yazi-macro = { path = "../yazi-macro", version = "26.1.4" } +yazi-shared = { path = "../yazi-shared", version = "26.1.4" } +yazi-term = { path = "../yazi-term", version = "26.1.4" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-config/README.md b/yazi-config/README.md new file mode 100644 index 00000000..4ca9feee --- /dev/null +++ b/yazi-config/README.md @@ -0,0 +1,5 @@ +# yazi-config + +This crate is part of [Yazi][source], and it is not supposed to be used outside, as there are no guarantees about the stability of its API. + +[source]: https://github.com/sxyazi/yazi diff --git a/yazi-config/preset/keymap-default.toml b/yazi-config/preset/keymap-default.toml index 7342a93c..96eadc9d 100644 --- a/yazi-config/preset/keymap-default.toml +++ b/yazi-config/preset/keymap-default.toml @@ -43,9 +43,9 @@ keymap = [ { on = "L", run = "forward", desc = "Forward to next directory" }, # Toggle - { on = "", run = [ "toggle", "arrow next" ], desc = "Toggle the current selection state" }, - { on = "", run = "toggle_all --state=on", desc = "Select all files" }, - { on = "", run = "toggle_all", desc = "Invert selection of all files" }, + { on = "", run = [ "toggle", "arrow 1" ], desc = "Toggle the current selection state" }, + { on = "", run = "toggle_all --state=on", desc = "Select all files" }, + { on = "", run = "toggle_all", desc = "Invert selection of all files" }, # Visual mode { on = "v", run = "visual_mode", desc = "Enter visual mode (selection mode)" }, diff --git a/yazi-config/preset/theme-dark.toml b/yazi-config/preset/theme-dark.toml index d4bb9230..56f46344 100644 --- a/yazi-config/preset/theme-dark.toml +++ b/yazi-config/preset/theme-dark.toml @@ -29,10 +29,6 @@ overall = {} [mgr] cwd = { fg = "cyan" } -# Hovered -hovered = { reversed = true } -preview_hovered = { underline = true } - # Find find_keyword = { fg = "yellow", bold = true, italic = true, underline = true } find_position = { fg = "magenta", bg = "reset", bold = true, italic = true } @@ -91,6 +87,17 @@ unset_alt = { fg = "red", bg = "gray" } # : }}} +# : Indicator of hovered file {{{ + +[indicator] +parent = { reversed = true } +current = { reversed = true } +preview = { underline = true } +padding = { open = "", close = "" } + +# : }}} + + # : Status bar {{{ [status] diff --git a/yazi-config/preset/theme-light.toml b/yazi-config/preset/theme-light.toml index 8bd2c90e..d6aef72b 100644 --- a/yazi-config/preset/theme-light.toml +++ b/yazi-config/preset/theme-light.toml @@ -29,10 +29,6 @@ overall = {} [mgr] cwd = { fg = "cyan" } -# Hovered -hovered = { reversed = true } -preview_hovered = { underline = true } - # Find find_keyword = { fg = "yellow", bold = true, italic = true, underline = true } find_position = { fg = "magenta", bg = "reset", bold = true, italic = true } @@ -91,6 +87,17 @@ unset_alt = { fg = "red", bg = "gray" } # : }}} +# : Indicator of hovered file {{{ + +[indicator] +parent = { reversed = true } +current = { reversed = true } +preview = { underline = true } +padding = { open = "", close = "" } + +# : }}} + + # : Status bar {{{ [status] diff --git a/yazi-config/preset/vfs-default.toml b/yazi-config/preset/vfs-default.toml new file mode 100644 index 00000000..48be1dab --- /dev/null +++ b/yazi-config/preset/vfs-default.toml @@ -0,0 +1 @@ +[services] diff --git a/yazi-config/preset/yazi-default.toml b/yazi-config/preset/yazi-default.toml index 02c641fd..8fb9f3db 100644 --- a/yazi-config/preset/yazi-default.toml +++ b/yazi-config/preset/yazi-default.toml @@ -135,6 +135,8 @@ spotters = [ { mime = "video/*", run = "video" }, # Virtual file system { mime = "vfs/*", run = "vfs" }, + # Error + { mime = "null/*", run = "null" }, # Fallback { url = "*", run = "file" }, ] @@ -181,6 +183,8 @@ previewers = [ { mime = "inode/empty", run = "empty" }, # Virtual file system { mime = "vfs/*", run = "vfs" }, + # Error + { mime = "null/*", run = "null" }, # Fallback { url = "*", run = "file" }, ] diff --git a/yazi-config/src/color.rs b/yazi-config/src/color.rs deleted file mode 100644 index bf0b63ba..00000000 --- a/yazi-config/src/color.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::{ops::Deref, str::FromStr}; - -use serde::Deserialize; - -#[derive(Clone, Copy, Debug, Default)] -pub struct Color(ratatui::style::Color); - -impl Deref for Color { - type Target = ratatui::style::Color; - - fn deref(&self) -> &Self::Target { &self.0 } -} - -impl From for ratatui::style::Color { - fn from(value: Color) -> Self { value.0 } -} - -impl<'de> Deserialize<'de> for Color { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - ratatui::style::Color::from_str(&String::deserialize(deserializer)?) - .map_err(serde::de::Error::custom) - .map(Self) - } -} diff --git a/yazi-config/src/lib.rs b/yazi-config/src/lib.rs index 84a8d0be..5884009c 100644 --- a/yazi-config/src/lib.rs +++ b/yazi-config/src/lib.rs @@ -1,6 +1,6 @@ yazi_macro::mod_pub!(files keymap mgr open opener plugin popup preview tasks theme which vfs); -yazi_macro::mod_flat!(color icon layout pattern platform preset priority style yazi); +yazi_macro::mod_flat!(icon layout pattern platform preset priority style utils yazi); use std::io::{Read, Write}; diff --git a/yazi-config/src/mgr/mgr.rs b/yazi-config/src/mgr/mgr.rs index 6be3ebfb..735a161d 100644 --- a/yazi-config/src/mgr/mgr.rs +++ b/yazi-config/src/mgr/mgr.rs @@ -2,7 +2,7 @@ use anyhow::{Result, bail}; use serde::Deserialize; use yazi_codegen::DeserializeOver2; use yazi_fs::{CWD, SortBy}; -use yazi_shared::{SyncCell, path::PathLike, url::{UrlBuf, UrlLike}}; +use yazi_shared::{SyncCell, url::UrlLike}; use super::{MgrRatio, MouseEvents}; @@ -32,8 +32,8 @@ impl Mgr { return None; } - let home = UrlBuf::from(dirs::home_dir().unwrap_or_default()); - let cwd = if let Some(p) = CWD.load().strip_prefix(&home) { + let home = dirs::home_dir().unwrap_or_default(); + let cwd = if let Ok(p) = CWD.load().try_strip_prefix(home) { format!("~{}{}", std::path::MAIN_SEPARATOR, p.display()) } else { format!("{}", CWD.load().display()) diff --git a/yazi-config/src/open/open.rs b/yazi-config/src/open/open.rs index 05953e16..731fcda6 100644 --- a/yazi-config/src/open/open.rs +++ b/yazi-config/src/open/open.rs @@ -34,10 +34,11 @@ impl Open { self .rules .iter() - .filter(move |&r| { + .find(move |&r| { r.mime.as_ref().is_some_and(|p| p.match_mime(&mime)) || r.url.as_ref().is_some_and(|p| p.match_url(url.as_url(), is_dir)) }) + .into_iter() .flat_map(|r| &r.r#use) .map(String::as_str) } diff --git a/yazi-config/src/pattern.rs b/yazi-config/src/pattern.rs index ab33b88c..acb580ce 100644 --- a/yazi-config/src/pattern.rs +++ b/yazi-config/src/pattern.rs @@ -1,9 +1,9 @@ use std::{fmt::Debug, str::FromStr}; use anyhow::{Result, bail}; -use globset::GlobBuilder; +use globset::{Candidate, GlobBuilder}; use serde::Deserialize; -use yazi_shared::{scheme::SchemeRef, url::AsUrl}; +use yazi_shared::{scheme::SchemeKind, url::AsUrl}; #[derive(Deserialize)] #[serde(try_from = "String")] @@ -33,23 +33,26 @@ impl Pattern { if is_dir != self.is_dir { return false; - } else if !self.scheme.matches(url.scheme) { + } else if !self.scheme.matches(url.kind()) { return false; } else if self.is_star { return true; } #[cfg(unix)] - let path = &url.loc; + { + self.inner.is_match_candidate(&Candidate::from_bytes(url.loc().encoded_bytes())) + } #[cfg(windows)] - let path = if self.sep_lit { - yazi_fs::path::backslash_to_slash(&url.loc) + if self.sep_lit { + use yazi_shared::strand::{AsStrand, StrandLike}; + self.inner.is_match_candidate(&Candidate::from_bytes( + url.loc().as_strand().backslash_to_slash().encoded_bytes(), + )) } else { - std::borrow::Cow::Borrowed(url.loc.as_path()) - }; - - self.inner.is_match(path) + self.inner.is_match_candidate(&Candidate::from_bytes(url.loc().encoded_bytes())) + } } pub fn match_mime(&self, mime: impl AsRef) -> bool { @@ -144,18 +147,19 @@ impl PatternScheme { } #[inline] - fn matches(self, scheme: SchemeRef) -> bool { - use SchemeRef as S; - match (self, scheme) { + fn matches(self, kind: SchemeKind) -> bool { + use SchemeKind as K; + + match (self, kind) { (Self::Any, _) => true, (Self::Local, s) => s.is_local(), (Self::Remote, s) => s.is_remote(), (Self::Virtual, s) => s.is_virtual(), - (Self::Regular, S::Regular) => true, - (Self::Search, S::Search(_)) => true, - (Self::Archive, S::Archive(_)) => true, - (Self::Sftp, S::Sftp(_)) => true, + (Self::Regular, K::Regular) => true, + (Self::Search, K::Search) => true, + (Self::Archive, K::Archive) => true, + (Self::Sftp, K::Sftp) => true, _ => false, } diff --git a/yazi-config/src/popup/options.rs b/yazi-config/src/popup/options.rs index 66b45b02..55a41be1 100644 --- a/yazi-config/src/popup/options.rs +++ b/yazi-config/src/popup/options.rs @@ -1,5 +1,5 @@ use ratatui::{text::{Line, Text}, widgets::{Paragraph, Wrap}}; -use yazi_shared::{IntoStringLossy, url::UrlBuf}; +use yazi_shared::{scheme::Encode as EncodeScheme, strand::ToStrand, url::{Url, UrlBuf}}; use super::{Offset, Position}; use crate::YAZI; @@ -31,9 +31,10 @@ pub struct ConfirmCfg { } impl InputCfg { - pub fn cd() -> Self { + pub fn cd(cwd: Url) -> Self { Self { - title: YAZI.input.cd_title.to_owned(), + title: YAZI.input.cd_title.clone(), + value: if cwd.kind().is_local() { String::new() } else { EncodeScheme(cwd).to_string() }, position: Position::new(YAZI.input.cd_origin, YAZI.input.cd_offset), completion: true, ..Default::default() @@ -42,7 +43,7 @@ impl InputCfg { pub fn create(dir: bool) -> Self { Self { - title: YAZI.input.create_title[dir as usize].to_owned(), + title: YAZI.input.create_title[dir as usize].clone(), position: Position::new(YAZI.input.create_origin, YAZI.input.create_offset), ..Default::default() } @@ -50,7 +51,7 @@ impl InputCfg { pub fn rename() -> Self { Self { - title: YAZI.input.rename_title.to_owned(), + title: YAZI.input.rename_title.clone(), position: Position::new(YAZI.input.rename_origin, YAZI.input.rename_offset), ..Default::default() } @@ -58,7 +59,7 @@ impl InputCfg { pub fn filter() -> Self { Self { - title: YAZI.input.filter_title.to_owned(), + title: YAZI.input.filter_title.clone(), position: Position::new(YAZI.input.filter_origin, YAZI.input.filter_offset), realtime: true, ..Default::default() @@ -67,7 +68,7 @@ impl InputCfg { pub fn find(prev: bool) -> Self { Self { - title: YAZI.input.find_title[prev as usize].to_owned(), + title: YAZI.input.find_title[prev as usize].clone(), position: Position::new(YAZI.input.find_origin, YAZI.input.find_offset), realtime: true, ..Default::default() @@ -84,7 +85,7 @@ impl InputCfg { pub fn shell(block: bool) -> Self { Self { - title: YAZI.input.shell_title[block as usize].to_owned(), + title: YAZI.input.shell_title[block as usize].clone(), position: Position::new(YAZI.input.shell_origin, YAZI.input.shell_offset), ..Default::default() } @@ -123,7 +124,7 @@ impl ConfirmCfg { Self::replace_number(&YAZI.confirm.trash_title, urls.len()), YAZI.confirm.trash_position(), None, - Self::truncate_list(urls.iter(), urls.len(), 100), + Self::truncate_list(urls, urls.len(), 100), ) } @@ -132,16 +133,16 @@ impl ConfirmCfg { Self::replace_number(&YAZI.confirm.delete_title, urls.len()), YAZI.confirm.delete_position(), None, - Self::truncate_list(urls.iter(), urls.len(), 100), + Self::truncate_list(urls, urls.len(), 100), ) } pub fn overwrite(url: &UrlBuf) -> Self { Self::new( - YAZI.confirm.overwrite_title.to_owned(), + YAZI.confirm.overwrite_title.clone(), YAZI.confirm.overwrite_position(), Some(Text::raw(&YAZI.confirm.overwrite_body)), - Some(url.into_string_lossy().into()), + Some(url.to_strand().into_string_lossy().into()), ) } @@ -150,7 +151,7 @@ impl ConfirmCfg { Self::replace_number(&YAZI.confirm.quit_title, len), YAZI.confirm.quit_position(), Some(Text::raw(&YAZI.confirm.quit_body)), - Self::truncate_list(names.into_iter(), len, 10), + Self::truncate_list(names, len, 10), ) } @@ -158,18 +159,18 @@ impl ConfirmCfg { tpl.replace("{n}", &n.to_string()).replace("{s}", if n > 1 { "s" } else { "" }) } - fn truncate_list( - it: impl Iterator, - len: usize, - max: usize, - ) -> Option> { + fn truncate_list(it: I, len: usize, max: usize) -> Option> + where + I: IntoIterator, + I::Item: ToStrand, + { let mut lines = Vec::with_capacity(len.min(max + 1)); - for (i, s) in it.enumerate() { + for (i, s) in it.into_iter().enumerate() { if i >= max { lines.push(format!("... and {} more", len - max)); break; } - lines.push(s.into_string_lossy()); + lines.push(s.to_strand().into_string_lossy()); } Some(Text::from_iter(lines)) } @@ -183,7 +184,7 @@ impl PickCfg { pub fn open(items: Vec) -> Self { let max_height = Self::max_height(items.len()); Self { - title: YAZI.pick.open_title.to_owned(), + title: YAZI.pick.open_title.clone(), items, position: Position::new(YAZI.pick.open_origin, Offset { height: max_height, diff --git a/yazi-config/src/preset.rs b/yazi-config/src/preset.rs index 7c7762ef..7030e5f4 100644 --- a/yazi-config/src/preset.rs +++ b/yazi-config/src/preset.rs @@ -1,4 +1,4 @@ -use crate::{Yazi, keymap::Keymap, theme::Theme}; +use crate::{Yazi, keymap::Keymap, theme::Theme, vfs::Vfs}; pub(crate) struct Preset; @@ -19,6 +19,10 @@ impl Preset { }) } + pub(super) fn vfs() -> Result { + toml::from_str(&yazi_macro::config_preset!("vfs")) + } + #[inline] pub(crate) fn mix(a: A, b: B, c: C) -> impl Iterator where diff --git a/yazi-config/src/preview/preview.rs b/yazi-config/src/preview/preview.rs index 50a02941..02e6da83 100644 --- a/yazi-config/src/preview/preview.rs +++ b/yazi-config/src/preview/preview.rs @@ -3,10 +3,11 @@ use std::{borrow::Cow, path::PathBuf}; use anyhow::{Context, Result, bail}; use serde::{Deserialize, Serialize}; use yazi_codegen::DeserializeOver2; -use yazi_fs::{Xdg, path::expand_url}; +use yazi_fs::Xdg; use yazi_shared::{SStr, timestamp_us}; use super::PreviewWrap; +use crate::normalize_path; #[rustfmt::skip] const TABS: &[&str] = &["", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]; @@ -50,10 +51,10 @@ impl Preview { self.cache_dir = if self.cache_dir.as_os_str().is_empty() { Xdg::cache_dir().to_owned() - } else if let Some(p) = expand_url(self.cache_dir).into_path() { + } else if let Some(p) = normalize_path(self.cache_dir) { p } else { - bail!("[preview].cache_dir must be a path within local filesystem."); + bail!("[preview].cache_dir must be either empty or an absolute path."); }; std::fs::create_dir_all(&self.cache_dir) diff --git a/yazi-config/src/style.rs b/yazi-config/src/style.rs index e2531bb0..5c2dd34a 100644 --- a/yazi-config/src/style.rs +++ b/yazi-config/src/style.rs @@ -1,75 +1,86 @@ -use ratatui::style::Modifier; -use serde::Deserialize; +use ratatui::style::Color; +use serde::{Deserialize, Serialize}; -use crate::Color; - -#[derive(Clone, Copy, Debug, Default, Deserialize)] +#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)] pub struct Style { pub fg: Option, pub bg: Option, - #[serde(default)] - pub bold: bool, - #[serde(default)] - pub dim: bool, - #[serde(default)] - pub italic: bool, - #[serde(default)] - pub underline: bool, - #[serde(default)] - pub blink: bool, - #[serde(default)] - pub blink_rapid: bool, - #[serde(default)] - pub reversed: bool, - #[serde(default)] - pub hidden: bool, - #[serde(default)] - pub crossed: bool, + pub bold: Option, + pub dim: Option, + pub italic: Option, + pub underline: Option, + pub blink: Option, + pub blink_rapid: Option, + pub reversed: Option, + pub hidden: Option, + pub crossed: Option, } -impl From