From 463150848d48357a4c6486e01b7ed345e95320a3 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Thu, 16 Apr 2026 17:05:46 +0800 Subject: [PATCH] feat: dynamic previewer Lua API (#3891) --- .github/workflows/check.yml | 2 +- .github/workflows/draft.yml | 4 +- .github/workflows/validate-form.yml | 2 +- CHANGELOG.md | 2 + Cargo.lock | 195 ++++++++++-------- Cargo.toml | 14 +- README.md | 40 ++-- cspell.json | 2 +- scripts/validate-form/package-lock.json | 8 +- scripts/validate-form/package.json | 2 +- yazi-actor/src/context.rs | 4 - yazi-actor/src/lives/file.rs | 2 +- yazi-actor/src/mgr/bulk_rename.rs | 2 +- yazi-actor/src/mgr/download.rs | 8 +- yazi-actor/src/mgr/open.rs | 37 ++-- yazi-actor/src/mgr/open_do.rs | 22 +- yazi-actor/src/mgr/seek.rs | 4 +- yazi-actor/src/mgr/shell.rs | 4 +- yazi-actor/src/mgr/toggle.rs | 4 +- yazi-actor/src/mgr/upload.rs | 2 +- yazi-adapter/src/adapters.rs | 2 +- yazi-binding/src/access.rs | 12 +- yazi-binding/src/config/fetcher.rs | 32 +++ yazi-binding/src/config/fetchers.rs | 59 ++++++ yazi-binding/src/config/mod.rs | 1 + yazi-binding/src/config/preloader.rs | 32 +++ yazi-binding/src/config/preloaders.rs | 59 ++++++ yazi-binding/src/config/previewer.rs | 69 +++++++ yazi-binding/src/config/previewers.rs | 75 +++++++ yazi-binding/src/config/spotter.rs | 32 +++ yazi-binding/src/config/spotters.rs | 59 ++++++ yazi-binding/src/elements/bar.rs | 4 +- yazi-binding/src/elements/border.rs | 25 +-- yazi-binding/src/elements/gauge.rs | 8 +- yazi-binding/src/elements/layout.rs | 10 +- yazi-binding/src/elements/line.rs | 4 +- yazi-binding/src/elements/pos.rs | 2 +- yazi-binding/src/elements/row.rs | 6 +- yazi-binding/src/elements/span.rs | 2 +- yazi-binding/src/elements/table.rs | 20 +- yazi-binding/src/elements/text.rs | 6 +- yazi-binding/src/file.rs | 2 +- yazi-binding/src/id.rs | 2 +- yazi-binding/src/lib.rs | 4 +- yazi-binding/src/macros.rs | 28 +-- yazi-binding/src/process/child.rs | 3 +- yazi-binding/src/process/command.rs | 14 +- yazi-binding/src/process/output.rs | 2 +- yazi-binding/src/selector.rs | 43 ++++ yazi-binding/src/style.rs | 5 + yazi-binding/src/url.rs | 2 +- yazi-boot/Cargo.toml | 2 +- yazi-boot/src/actions/debug.rs | 6 +- yazi-cli/Cargo.toml | 2 +- yazi-codegen/src/lib.rs | 47 +++-- yazi-config/Cargo.toml | 29 +-- yazi-config/preset/yazi-default.toml | 8 +- yazi-config/src/icon.rs | 5 +- yazi-config/src/keymap/chord.rs | 73 +++++-- yazi-config/src/keymap/cow.rs | 30 ++- yazi-config/src/keymap/deserializers.rs | 83 -------- yazi-config/src/keymap/keymap.rs | 45 ++-- yazi-config/src/keymap/mod.rs | 2 +- yazi-config/src/keymap/rules.rs | 43 ++-- yazi-config/src/lib.rs | 7 +- yazi-config/src/mgr/linemode.rs | 23 +++ yazi-config/src/mgr/mgr.rs | 19 +- yazi-config/src/mgr/mod.rs | 2 +- yazi-config/src/mixing.rs | 77 +++++++ yazi-config/src/open/open.rs | 54 ++--- yazi-config/src/open/rule.rs | 70 ++----- yazi-config/src/opener/opener.rs | 47 ++--- yazi-config/src/opener/rule.rs | 14 +- yazi-config/src/pattern.rs | 15 +- yazi-config/src/plugin/fetcher.rs | 42 ++-- yazi-config/src/plugin/fetchers.rs | 117 +++++++++++ yazi-config/src/plugin/ids.rs | 21 ++ yazi-config/src/plugin/mod.rs | 2 +- yazi-config/src/plugin/plugin.rs | 138 ++++--------- yazi-config/src/plugin/preloader.rs | 42 ++-- yazi-config/src/plugin/preloaders.rs | 99 +++++++++ yazi-config/src/plugin/previewer.rs | 42 ++-- yazi-config/src/plugin/previewers.rs | 121 +++++++++++ yazi-config/src/plugin/spotter.rs | 42 ++-- yazi-config/src/plugin/spotters.rs | 90 ++++++++ yazi-config/src/popup/confirm.rs | 4 +- yazi-config/src/popup/input.rs | 4 +- yazi-config/src/popup/pick.rs | 4 +- yazi-config/src/preset.rs | 10 - yazi-config/src/preview/preview.rs | 67 ++++-- yazi-config/src/selectable.rs | 21 ++ yazi-config/src/selector.rs | 42 ++++ yazi-config/src/tasks/tasks.rs | 38 +--- yazi-config/src/theme/filetype.rs | 27 +-- yazi-config/src/theme/flavor.rs | 18 +- yazi-config/src/theme/icon.rs | 189 ++++++----------- yazi-config/src/theme/is.rs | 7 +- yazi-config/src/theme/theme.rs | 260 +++++++++++++----------- yazi-config/src/vfs/mod.rs | 2 +- yazi-config/src/vfs/service.rs | 57 +----- yazi-config/src/vfs/services.rs | 34 ++-- yazi-config/src/vfs/sftp.rs | 52 +++++ yazi-config/src/vfs/vfs.rs | 11 +- yazi-config/src/which/which.rs | 4 +- yazi-config/src/yazi.rs | 15 -- yazi-core/src/highlighter.rs | 2 +- yazi-core/src/mgr/open.rs | 11 +- yazi-core/src/mgr/search.rs | 6 +- yazi-core/src/notify/level.rs | 16 +- yazi-core/src/notify/message.rs | 30 ++- yazi-core/src/proxy.rs | 5 +- yazi-core/src/spot/spot.rs | 4 +- yazi-core/src/tab/preview.rs | 4 +- yazi-core/src/tasks/prework.rs | 7 +- yazi-emulator/src/brand.rs | 1 + yazi-fm/src/cmp/cmp.rs | 8 +- yazi-fm/src/confirm/body.rs | 4 +- yazi-fm/src/confirm/buttons.rs | 4 +- yazi-fm/src/confirm/confirm.rs | 4 +- yazi-fm/src/confirm/list.rs | 4 +- yazi-fm/src/dispatcher.rs | 9 - yazi-fm/src/help/bindings.rs | 8 +- yazi-fm/src/help/help.rs | 2 +- yazi-fm/src/input/input.rs | 4 +- yazi-fm/src/notify/notify.rs | 6 +- yazi-fm/src/pick/list.rs | 4 +- yazi-fm/src/pick/pick.rs | 2 +- yazi-fm/src/tasks/tasks.rs | 4 +- yazi-fm/src/which/cand.rs | 9 +- yazi-fm/src/which/which.rs | 4 +- yazi-fs/src/file.rs | 10 +- yazi-fs/src/filter.rs | 1 - yazi-parser/src/mgr/bulk_exit.rs | 4 +- yazi-parser/src/mgr/download.rs | 4 +- yazi-parser/src/mgr/peek.rs | 4 +- yazi-parser/src/mgr/shell.rs | 4 +- yazi-parser/src/mgr/toggle.rs | 4 +- yazi-parser/src/mgr/toggle_all.rs | 4 +- yazi-parser/src/mgr/update_paged.rs | 4 +- yazi-parser/src/mgr/upload.rs | 4 +- yazi-plugin/preset/plugins/file.lua | 28 ++- yazi-plugin/src/runtime/plugin.rs | 108 +--------- yazi-plugin/src/runtime/runtime.rs | 14 +- yazi-plugin/src/tasks/option.rs | 2 +- yazi-plugin/src/theme/theme.rs | 180 ++++++++-------- yazi-plugin/src/utils/layer.rs | 2 +- yazi-plugin/src/utils/spot.rs | 4 +- yazi-proxy/src/tasks.rs | 4 +- yazi-runner/src/fetcher/fetcher.rs | 6 +- yazi-runner/src/fetcher/job.rs | 13 +- yazi-runner/src/loader/chunk.rs | 1 - yazi-runner/src/preloader/job.rs | 9 +- yazi-runner/src/preloader/preloader.rs | 6 +- yazi-runner/src/previewer/job.rs | 14 +- yazi-runner/src/previewer/previewer.rs | 6 +- yazi-runner/src/spot.rs | 15 +- yazi-scheduler/src/fetch/fetch.rs | 9 +- yazi-scheduler/src/fetch/in.rs | 8 +- yazi-scheduler/src/file/file.rs | 6 +- yazi-scheduler/src/preload/in.rs | 10 +- yazi-scheduler/src/preload/preload.rs | 9 +- yazi-scheduler/src/process/in.rs | 8 +- yazi-scheduler/src/process/option.rs | 4 +- yazi-scheduler/src/process/shell.rs | 4 +- yazi-scheduler/src/scheduler.rs | 14 +- yazi-scheduler/src/worker.rs | 10 +- yazi-shared/src/data/data.rs | 12 ++ yazi-shared/src/id.rs | 2 +- yazi-shared/src/layer.rs | 16 +- yazi-shared/src/lib.rs | 2 +- yazi-shared/src/non_empty_string.rs | 52 +++++ yazi-shared/src/strand/strand.rs | 2 - yazi-shared/src/sync_cell.rs | 12 +- yazi-shim/Cargo.toml | 4 + yazi-shim/src/arc_swap/mod.rs | 1 + yazi-shim/src/arc_swap/traits.rs | 11 + yazi-shim/src/lib.rs | 2 +- yazi-shim/src/toml/mod.rs | 1 + yazi-shim/src/toml/toml.rs | 20 ++ yazi-shim/src/toml/traits.rs | 20 ++ yazi-shim/src/vec/error.rs | 8 + yazi-shim/src/vec/mod.rs | 1 + yazi-shim/src/vec/traits.rs | 27 +++ yazi-vfs/src/file.rs | 2 - yazi-vfs/src/fns.rs | 1 - yazi-widgets/src/input/widget.rs | 4 +- 186 files changed, 2610 insertions(+), 1598 deletions(-) create mode 100644 yazi-binding/src/config/fetcher.rs create mode 100644 yazi-binding/src/config/fetchers.rs create mode 100644 yazi-binding/src/config/mod.rs create mode 100644 yazi-binding/src/config/preloader.rs create mode 100644 yazi-binding/src/config/preloaders.rs create mode 100644 yazi-binding/src/config/previewer.rs create mode 100644 yazi-binding/src/config/previewers.rs create mode 100644 yazi-binding/src/config/spotter.rs create mode 100644 yazi-binding/src/config/spotters.rs create mode 100644 yazi-binding/src/selector.rs delete mode 100644 yazi-config/src/keymap/deserializers.rs create mode 100644 yazi-config/src/mgr/linemode.rs create mode 100644 yazi-config/src/mixing.rs create mode 100644 yazi-config/src/plugin/fetchers.rs create mode 100644 yazi-config/src/plugin/ids.rs create mode 100644 yazi-config/src/plugin/preloaders.rs create mode 100644 yazi-config/src/plugin/previewers.rs create mode 100644 yazi-config/src/plugin/spotters.rs create mode 100644 yazi-config/src/selectable.rs create mode 100644 yazi-config/src/selector.rs create mode 100644 yazi-config/src/vfs/sftp.rs create mode 100644 yazi-shared/src/non_empty_string.rs create mode 100644 yazi-shim/src/arc_swap/mod.rs create mode 100644 yazi-shim/src/arc_swap/traits.rs create mode 100644 yazi-shim/src/toml/mod.rs create mode 100644 yazi-shim/src/toml/toml.rs create mode 100644 yazi-shim/src/toml/traits.rs create mode 100644 yazi-shim/src/vec/error.rs create mode 100644 yazi-shim/src/vec/mod.rs create mode 100644 yazi-shim/src/vec/traits.rs diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 3d363578..b8d5da24 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -51,7 +51,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v6 - - uses: JohnnyMorganz/stylua-action@v4 + - uses: JohnnyMorganz/stylua-action@v5 with: token: ${{ secrets.GITHUB_TOKEN }} version: latest diff --git a/.github/workflows/draft.yml b/.github/workflows/draft.yml index f518914e..448ad1fb 100644 --- a/.github/workflows/draft.yml +++ b/.github/workflows/draft.yml @@ -210,7 +210,7 @@ jobs: merge-multiple: true - name: Draft - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: draft: true files: | @@ -246,7 +246,7 @@ jobs: git tag --force nightly && git push --force origin tag nightly - name: Nightly - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: tag_name: nightly prerelease: true diff --git a/.github/workflows/validate-form.yml b/.github/workflows/validate-form.yml index b9416d4b..bd8d9764 100644 --- a/.github/workflows/validate-form.yml +++ b/.github/workflows/validate-form.yml @@ -25,7 +25,7 @@ jobs: npm ci - name: Validate Form - uses: actions/github-script@v8 + uses: actions/github-script@v9 with: script: | const script = require('./scripts/validate-form/main.js') diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bf1272f..40ff9a3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): - New `--in` for `search` action to set search directory ([#3696]) - Hover cursor over the new file after copying/cutting/linking/hardlinking/extracting ([#3846], [#3854]) - Multi-file spotter ([#3733]) +- Dynamic previewer Lua API ([#3891]) - Vim-like `lua` action that runs an inline Lua snippet ([#3813]) - Certificate authentication for SFTP VFS provider ([#3716]) - New `hovered` condition specifying different icons for hovered files ([#3728]) @@ -1699,3 +1700,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): [#3846]: https://github.com/sxyazi/yazi/pull/3846 [#3854]: https://github.com/sxyazi/yazi/pull/3854 [#3862]: https://github.com/sxyazi/yazi/pull/3862 +[#3891]: https://github.com/sxyazi/yazi/pull/3891 diff --git a/Cargo.lock b/Cargo.lock index 7c8669dc..e0b5c110 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -211,6 +211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" dependencies = [ "rustversion", + "serde", ] [[package]] @@ -410,20 +411,20 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] [[package]] name = "bitstream-io" -version = "4.9.0" +version = "4.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" dependencies = [ - "core2", + "no_std_io2", ] [[package]] @@ -629,7 +630,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -669,9 +670,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -691,9 +692,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.6.1" +version = "4.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406e68b4de5c59cfb8f750a7cbd4d31ae153788b8352167c1e5f4fc26e8c91e9" +checksum = "3ff7a1dccbdd8b078c2bdebff47e404615151534d5043da397ec50286816f9cb" dependencies = [ "clap", ] @@ -720,9 +721,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", @@ -826,15 +827,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "core2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" -dependencies = [ - "memchr", -] - [[package]] name = "cpubits" version = "0.1.0" @@ -908,7 +900,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "crossterm_winapi", "mio", "parking_lot", @@ -925,7 +917,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "crossterm_winapi", "derive_more", "document-features", @@ -967,7 +959,7 @@ dependencies = [ "getrandom 0.4.2", "hybrid-array", "num-traits", - "rand_core 0.10.0", + "rand_core 0.10.1", "serdect", "subtle", "zeroize", @@ -991,7 +983,7 @@ checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" dependencies = [ "getrandom 0.4.2", "hybrid-array", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -1002,7 +994,7 @@ checksum = "21f41f23de7d24cdbda7f0c4d9c0351f99a4ceb258ef30e5c1927af8987ffe5a" dependencies = [ "crypto-bigint", "libm", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -1349,7 +1341,7 @@ checksum = "053618a4c3d3bc24f188aa660ae75a46eeab74ef07fb415c61431e5e7cd4749b" dependencies = [ "curve25519-dalek", "ed25519", - "rand_core 0.10.0", + "rand_core 0.10.1", "serde", "sha2 0.11.0", "signature", @@ -1378,7 +1370,7 @@ dependencies = [ "once_cell", "pem-rfc7468 1.0.0", "pkcs8", - "rand_core 0.10.0", + "rand_core 0.10.1", "rustcrypto-ff", "rustcrypto-group", "sec1", @@ -1767,7 +1759,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -2046,7 +2038,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "inotify-sys", "libc", ] @@ -2110,7 +2102,7 @@ dependencies = [ "p256", "p384", "p521", - "rand_core 0.10.0", + "rand_core 0.10.1", "rsa", "sec1", "sha1 0.11.0", @@ -2130,8 +2122,8 @@ checksum = "ae8e22120c32fb4d19ec55fba35015f57095cd95a2e3b732e44457f5915b2ee8" dependencies = [ "num-integer", "num-traits", - "rand 0.10.0", - "rand_core 0.10.0", + "rand 0.10.1", + "rand_core 0.10.1", ] [[package]] @@ -2216,7 +2208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01737161ba802849cfd486b5bd209d38ba4943494c249a8126005170c7621edd" dependencies = [ "crypto-common 0.2.1", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -2268,9 +2260,9 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" -version = "0.2.184" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "libfuzzer-sys" @@ -2303,7 +2295,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -2350,13 +2342,22 @@ dependencies = [ [[package]] name = "lru" -version = "0.16.3" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" dependencies = [ "hashbrown 0.16.1", ] +[[package]] +name = "lru" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0b564323a0fb6d54b864f625ae139de9612e27edb944dda37c109f05aac531" +dependencies = [ + "hashbrown 0.17.0", +] + [[package]] name = "lua-src" version = "550.0.0" @@ -2468,7 +2469,7 @@ dependencies = [ "hybrid-array", "kem", "module-lattice", - "rand_core 0.10.0", + "rand_core 0.10.1", "sha3", ] @@ -2556,7 +2557,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "cfg-if", "cfg_aliases", "libc", @@ -2569,12 +2570,21 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "cfg-if", "cfg_aliases", "libc", ] +[[package]] +name = "no_std_io2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b51ed7824b6e07d354605f4abb3d9d300350701299da96642ee084f5ce631550" +dependencies = [ + "memchr", +] + [[package]] name = "nom" version = "7.1.3" @@ -2606,7 +2616,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "fsevent-sys", "inotify", "kqueue", @@ -2624,7 +2634,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -2766,7 +2776,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "objc2", ] @@ -2797,7 +2807,7 @@ version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "libc", "once_cell", "onig_sys", @@ -3156,7 +3166,7 @@ dependencies = [ "cbc 0.2.0", "der", "pbkdf2 0.13.0-rc.10", - "rand_core 0.10.0", + "rand_core 0.10.1", "scrypt", "sha2 0.11.0", "spki", @@ -3170,15 +3180,15 @@ checksum = "12922b6296c06eb741b02d7b5161e3aaa22864af38dfa025a1a3ba3f68c84577" dependencies = [ "der", "pkcs5", - "rand_core 0.10.0", + "rand_core 0.10.1", "spki", ] [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plist" @@ -3199,7 +3209,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "crc32fast", "fdeflate", "flate2", @@ -3279,7 +3289,7 @@ checksum = "c6543f5eec854fbf74ba5ef651fbdc9408919b47c3e1526623687135c16d12e9" dependencies = [ "crypto-bigint", "crypto-common 0.2.1", - "rand_core 0.10.0", + "rand_core 0.10.1", "rustcrypto-ff", "subtle", "zeroize", @@ -3431,9 +3441,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -3441,13 +3451,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20 0.10.0", "getrandom 0.4.2", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -3491,9 +3501,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "ratatui" @@ -3517,13 +3527,13 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "compact_str", "hashbrown 0.16.1", "indoc", "itertools", "kasuari", - "lru", + "lru 0.16.4", "serde", "strum 0.27.2", "thiserror 2.0.18", @@ -3582,7 +3592,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "hashbrown 0.16.1", "indoc", "instability", @@ -3623,7 +3633,7 @@ dependencies = [ "num-traits", "paste", "profiling", - "rand 0.9.2", + "rand 0.9.4", "rand_chacha 0.9.0", "simd_helpers", "thiserror 2.0.18", @@ -3647,9 +3657,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -3671,7 +3681,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -3776,7 +3786,7 @@ dependencies = [ "digest 0.11.2", "pkcs1", "pkcs8", - "rand_core 0.10.0", + "rand_core 0.10.1", "sha2 0.11.0", "signature", "spki", @@ -3790,7 +3800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b530252dc3ff163b73a7e48c97b925450d2ca53edcb466a46ad0a231e45f998" dependencies = [ "aes 0.8.4", - "bitflags 2.11.0", + "bitflags 2.11.1", "block-padding 0.3.3", "byteorder", "bytes", @@ -3828,8 +3838,8 @@ dependencies = [ "pkcs5", "pkcs8", "polyval 0.7.1", - "rand 0.10.0", - "rand_core 0.10.0", + "rand 0.10.1", + "rand_core 0.10.1", "ring", "rsa", "russh-cryptovec", @@ -3899,7 +3909,7 @@ version = "0.14.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd2a8adb347447693cd2ba0d218c4b66c62da9b0a5672b17b981e4291ec65ff6" dependencies = [ - "rand_core 0.10.0", + "rand_core 0.10.1", "subtle", ] @@ -3909,7 +3919,7 @@ version = "0.14.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "369f9b61aa45933c062c9f6b5c3c50ab710687eca83dd3802653b140b43f85ed" dependencies = [ - "rand_core 0.10.0", + "rand_core 0.10.1", "rustcrypto-ff", "subtle", ] @@ -3920,7 +3930,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys 0.4.15", @@ -3933,7 +3943,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys 0.12.1", @@ -4274,7 +4284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f1880df446116126965eeec169136b2e0251dba37c6223bcc819569550edea3" dependencies = [ "digest 0.11.2", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -4525,7 +4535,7 @@ checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" dependencies = [ "anyhow", "base64", - "bitflags 2.11.0", + "bitflags 2.11.1", "fancy-regex", "filedescriptor", "finl_unicode", @@ -4678,9 +4688,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.51.1" +version = "1.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" +checksum = "a91135f59b1cbf38c91e73cf3386fca9bb77915c45ce2771460c9d92f0f3d776" dependencies = [ "bytes", "libc", @@ -4864,7 +4874,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" dependencies = [ - "rand 0.9.2", + "rand 0.9.4", ] [[package]] @@ -4966,9 +4976,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "atomic", "getrandom 0.4.2", @@ -5175,7 +5185,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "hashbrown 0.15.5", "indexmap 2.14.0", "semver", @@ -5703,7 +5713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.0", + "bitflags 2.11.1", "indexmap 2.14.0", "log", "serde", @@ -5908,7 +5918,8 @@ name = "yazi-config" version = "26.2.2" dependencies = [ "anyhow", - "bitflags 2.11.0", + "arc-swap", + "bitflags 2.11.1", "crossterm 0.29.0", "globset", "hashbrown 0.17.0", @@ -5916,6 +5927,7 @@ dependencies = [ "ratatui", "regex", "serde", + "serde_with", "strum 0.28.0", "tokio", "toml", @@ -5924,6 +5936,7 @@ dependencies = [ "yazi-fs", "yazi-macro", "yazi-shared", + "yazi-shim", "yazi-tty", ] @@ -6066,7 +6079,7 @@ version = "26.2.2" dependencies = [ "anyhow", "arc-swap", - "bitflags 2.11.0", + "bitflags 2.11.1", "core-foundation-sys", "dirs", "either", @@ -6076,7 +6089,7 @@ dependencies = [ "objc2", "parking_lot", "percent-encoding", - "rand 0.10.0", + "rand 0.10.1", "regex", "scopeguard", "serde", @@ -6106,7 +6119,7 @@ name = "yazi-parser" version = "26.2.2" dependencies = [ "anyhow", - "bitflags 2.11.0", + "bitflags 2.11.1", "crossterm 0.29.0", "hashbrown 0.17.0", "mlua", @@ -6217,7 +6230,7 @@ dependencies = [ "foldhash 0.2.0", "hashbrown 0.17.0", "libc", - "lru", + "lru 0.17.0", "mlua", "ordered-float 5.3.0", "parking_lot", @@ -6240,7 +6253,7 @@ dependencies = [ name = "yazi-sftp" version = "26.2.2" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "parking_lot", "russh", "serde", @@ -6278,8 +6291,12 @@ dependencies = [ name = "yazi-shim" version = "26.2.2" dependencies = [ + "arc-swap", "crossterm 0.29.0", "ratatui", + "serde", + "thiserror 2.0.18", + "toml", "twox-hash", "unicode-segmentation", "unicode-width", diff --git a/Cargo.toml b/Cargo.toml index 6acc8042..d66c7f49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,11 +37,11 @@ debug = false [workspace.dependencies] ansi-to-tui = "8.0.1" anyhow = "1.0.102" -arc-swap = "1.9.1" +arc-swap = { version = "1.9.1", features = [ "serde" ] } base64 = "0.22.1" -bitflags = { version = "2.11.0", features = [ "serde" ] } +bitflags = { version = "2.11.1", features = [ "serde" ] } chrono = "0.4.44" -clap = { version = "4.6.0", features = [ "derive" ] } +clap = { version = "4.6.1", features = [ "derive" ] } core-foundation-sys = "0.8.7" crossterm = { version = "0.29.0", features = [ "event-stream" ] } dirs = "6.0.0" @@ -52,15 +52,15 @@ futures = "0.3.32" globset = "0.4.18" hashbrown = { version = "0.17.0", features = [ "serde" ] } indexmap = { version = "2.14.0", features = [ "serde" ] } -libc = "0.2.184" -lru = "0.16.3" +libc = "0.2.185" +lru = "0.17.0" mlua = { version = "0.11.6", features = [ "anyhow", "async", "error-send", "lua55", "macros", "serde" ] } objc2 = "0.6.4" ordered-float = { version = "5.3.0", features = [ "serde" ] } parking_lot = "0.12.5" paste = "1.0.15" percent-encoding = "2.3.2" -rand = { version = "0.10.0", default-features = false, features = [ "std", "sys_rng" ] } +rand = { version = "0.10.1", default-features = false, features = [ "std", "sys_rng" ] } ratatui = { version = "0.30.0", features = [ "serde", "unstable-rendered-line-info", "unstable-widget-ref" ] } regex = "1.12.3" russh = { version = "0.60.0", default-features = false, features = [ "ring", "rsa" ] } @@ -71,7 +71,7 @@ serde_with = "3.18.0" strum = { version = "0.28.0", features = [ "derive" ] } syntect = { version = "5.3.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] } thiserror = "2.0.18" -tokio = { version = "1.51.1", features = [ "full" ] } +tokio = { version = "1.52.0", features = [ "full" ] } tokio-stream = "0.1.18" tokio-util = "0.7.18" toml = { version = "1.1.2" } diff --git a/README.md b/README.md index e1f46cea..63e6513a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@
Special thanks to:
-|Warp sponsorship
Warp, built for coding with multiple AI agents
Available for macOS, Linux and Windows
| -|-| +| Warp sponsorship
Warp, built for coding with multiple AI agents
Available for macOS, Linux and Windows
| +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -47,24 +47,24 @@ Yazi is currently in heavy development, expect breaking changes. ## Image Preview -| Platform | Protocol | Support | -| ---------------------------------------------------------------------------- | -------------------------------------- | ---------------------------------------- | -| [kitty](https://github.com/kovidgoyal/kitty) (>= 0.28.0) | [Kitty unicode placeholders][kgp] | ✅ Built-in | -| [iTerm2](https://iterm2.com) | [Inline images protocol][iip] | ✅ Built-in | -| [WezTerm](https://github.com/wez/wezterm) | [Inline images protocol][iip] | ✅ Built-in | -| [Konsole](https://invent.kde.org/utilities/konsole) | [Kitty old protocol][kgp-old] | ✅ Built-in | -| [foot](https://codeberg.org/dnkl/foot) | [Sixel graphics format][sixel] | ✅ Built-in | -| [Ghostty](https://github.com/ghostty-org/ghostty) | [Kitty unicode placeholders][kgp] | ✅ Built-in | -| [Windows Terminal](https://github.com/microsoft/terminal) (>= v1.22.10352.0) | [Sixel graphics format][sixel] | ✅ Built-in | -| [st with Sixel patch](https://github.com/bakkeby/st-flexipatch) | [Sixel graphics format][sixel] | ✅ Built-in | -| [Warp](https://www.warp.dev) (macOS/Linux only) | [Inline images protocol][iip] | ✅ Built-in | -| [Tabby](https://github.com/Eugeny/tabby) | [Inline images protocol][iip] | ✅ Built-in | -| [VSCode](https://github.com/microsoft/vscode) | [Inline images protocol][iip] | ✅ Built-in | -| [Rio](https://github.com/raphamorim/rio) | [Inline images protocol][iip] | ❌ Rio renders images at incorrect sizes | -| [Black Box](https://gitlab.gnome.org/raggesilver/blackbox) | [Sixel graphics format][sixel] | ✅ Built-in | -| [Bobcat](https://github.com/ismail-yilmaz/Bobcat) | [Inline images protocol][iip] | ✅ Built-in | -| X11 / Wayland | Window system protocol | ☑️ [Überzug++][ueberzug] required | -| Fallback | [ASCII art (Unicode block)][ascii-art] | ☑️ [Chafa][chafa] required (>= 1.16.0) | +| Platform | Protocol | Support | +| ---------------------------------------------------------------------------- | -------------------------------------- | -------------------------------------- | +| [kitty](https://github.com/kovidgoyal/kitty) (>= 0.28.0) | [Kitty unicode placeholders][kgp] | ✅ Built-in | +| [iTerm2](https://iterm2.com) | [Inline images protocol][iip] | ✅ Built-in | +| [WezTerm](https://github.com/wez/wezterm) | [Inline images protocol][iip] | ✅ Built-in | +| [Konsole](https://invent.kde.org/utilities/konsole) | [Kitty old protocol][kgp-old] | ✅ Built-in | +| [foot](https://codeberg.org/dnkl/foot) | [Sixel graphics format][sixel] | ✅ Built-in | +| [Ghostty](https://github.com/ghostty-org/ghostty) | [Kitty unicode placeholders][kgp] | ✅ Built-in | +| [Windows Terminal](https://github.com/microsoft/terminal) (>= v1.22.10352.0) | [Sixel graphics format][sixel] | ✅ Built-in | +| [st with Sixel patch](https://github.com/bakkeby/st-flexipatch) | [Sixel graphics format][sixel] | ✅ Built-in | +| [Warp](https://www.warp.dev) (macOS/Linux only) | [Inline images protocol][iip] | ✅ Built-in | +| [Tabby](https://github.com/Eugeny/tabby) | [Inline images protocol][iip] | ✅ Built-in | +| [VSCode](https://github.com/microsoft/vscode) | [Inline images protocol][iip] | ✅ Built-in | +| [Rio](https://github.com/raphamorim/rio) (>= 0.3.9) | [Kitty unicode placeholders][kgp] | ✅ Built-in | +| [Black Box](https://gitlab.gnome.org/raggesilver/blackbox) | [Sixel graphics format][sixel] | ✅ Built-in | +| [Bobcat](https://github.com/ismail-yilmaz/Bobcat) | [Inline images protocol][iip] | ✅ Built-in | +| X11 / Wayland | Window system protocol | ☑️ [Überzug++][ueberzug] required | +| Fallback | [ASCII art (Unicode block)][ascii-art] | ☑️ [Chafa][chafa] required (>= 1.16.0) | See https://yazi-rs.github.io/docs/image-preview for details. diff --git a/cspell.json b/cspell.json index 3fc3d927..e5d69993 100644 --- a/cspell.json +++ b/cspell.json @@ -1 +1 @@ -{"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","treelize","TOCTOU","fellback","watchee","Textlike","sstr"],"flagWords":[],"language":"en","version":"0.2"} \ No newline at end of file +{"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","treelize","TOCTOU","fellback","watchee","Textlike","sstr","pointee"],"version":"0.2","language":"en","flagWords":[]} \ No newline at end of file diff --git a/scripts/validate-form/package-lock.json b/scripts/validate-form/package-lock.json index 5ed84a8b..03743e35 100644 --- a/scripts/validate-form/package-lock.json +++ b/scripts/validate-form/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "dependencies": { "@actions/core": "^3.0.0", - "@actions/github": "^9.0.0" + "@actions/github": "^9.1.0" } }, "node_modules/@actions/core": { @@ -42,9 +42,9 @@ } }, "node_modules/@actions/github": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-9.0.0.tgz", - "integrity": "sha512-yJ0RoswsAaKcvkmpCE4XxBRiy/whH2SdTBHWzs0gi4wkqTDhXMChjSdqBz/F4AeiDlP28rQqL33iHb+kjAMX6w==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-9.1.0.tgz", + "integrity": "sha512-u0hDGQeCS+7VNoLA8hYG65RLdPLMaPGfka0sZ0up7P0AiShqfX6xcuXNteGkQ7X7Tod7AMNwHd4p7DS63i8zzA==", "license": "MIT", "dependencies": { "@actions/http-client": "^3.0.2", diff --git a/scripts/validate-form/package.json b/scripts/validate-form/package.json index 0b6d52c8..4ecb17e8 100644 --- a/scripts/validate-form/package.json +++ b/scripts/validate-form/package.json @@ -7,6 +7,6 @@ "private": true, "dependencies": { "@actions/core": "^3.0.0", - "@actions/github": "^9.0.0" + "@actions/github": "^9.1.0" } } diff --git a/yazi-actor/src/context.rs b/yazi-actor/src/context.rs index 24cd8bc1..febe97a6 100644 --- a/yazi-actor/src/context.rs +++ b/yazi-actor/src/context.rs @@ -27,7 +27,6 @@ impl DerefMut for Ctx<'_> { } impl<'a> Ctx<'a> { - #[inline] pub fn new(action: &Action, core: &'a mut Core, term: &'a mut Option) -> Result { let tab = if let Ok(id) = action.get::("tab") { core @@ -51,7 +50,6 @@ impl<'a> Ctx<'a> { }) } - #[inline] pub fn renew<'b>(cx: &'a mut Ctx<'b>) -> Self { let tab = cx.core.mgr.tabs.cursor; Self { @@ -65,7 +63,6 @@ impl<'a> Ctx<'a> { } } - #[inline] pub fn active(core: &'a mut Core, term: &'a mut Option) -> Self { let tab = core.mgr.tabs.cursor; Self { @@ -119,6 +116,5 @@ impl<'a> Ctx<'a> { self.tab_mut().hovered_folder_mut() } - #[inline] pub fn source(&self) -> Source { if self.level != 1 { Source::Ind } else { self.source } } } diff --git a/yazi-actor/src/lives/file.rs b/yazi-actor/src/lives/file.rs index 578c384c..83ae6ca1 100644 --- a/yazi-actor/src/lives/file.rs +++ b/yazi-actor/src/lives/file.rs @@ -2,7 +2,7 @@ use std::{ops::Deref, ptr}; use mlua::{AnyUserData, IntoLua, UserData, UserDataFields, UserDataMethods, Value}; use yazi_binding::{Range, Style, cached_field}; -use yazi_config::THEME; +use yazi_config::{Selectable, THEME}; use yazi_shared::{path::AsPath, url::UrlLike}; use super::Lives; diff --git a/yazi-actor/src/mgr/bulk_rename.rs b/yazi-actor/src/mgr/bulk_rename.rs index 7443980d..938b2e1c 100644 --- a/yazi-actor/src/mgr/bulk_rename.rs +++ b/yazi-actor/src/mgr/bulk_rename.rs @@ -155,7 +155,7 @@ impl BulkRename { } fn opener() -> Option<&'static OpenerRule> { - YAZI.opener.block(YAZI.open.all(Path::new("bulk-rename.txt"), "text/plain")) + YAZI.opener.block(YAZI.open.all_dummy(Path::new("bulk-rename.txt"), "text/plain")) } fn replace_url(url: &UrlBuf, take: usize, rep: &StrandBuf) -> Result { diff --git a/yazi-actor/src/mgr/download.rs b/yazi-actor/src/mgr/download.rs index ab94dbdb..8e9c174e 100644 --- a/yazi-actor/src/mgr/download.rs +++ b/yazi-actor/src/mgr/download.rs @@ -8,7 +8,7 @@ use yazi_fs::{File, FsScheme, provider::{Provider, local::Local}}; use yazi_macro::succ; use yazi_parser::mgr::DownloadForm; use yazi_proxy::MgrProxy; -use yazi_shared::{data::Data, url::{UrlCow, UrlLike}}; +use yazi_shared::{data::Data, url::{UrlBuf, UrlLike}}; use yazi_vfs::VfsFile; use crate::{Actor, Ctx}; @@ -29,7 +29,7 @@ impl Actor for Download { let mut wg1 = FuturesUnordered::new(); for url in form.urls { - let done = scheduler.file_download(url.to_owned()); + let done = scheduler.file_download(url.clone()); wg1.push(async move { (done.future().await, url) }); } @@ -60,7 +60,7 @@ impl Actor for Download { } if form.open && !urls.is_empty() { MgrProxy::open(OpenOpt { - cwd: Some(cwd.into()), + cwd: Some(cwd), targets: urls, interactive: false, hovered: false, @@ -73,7 +73,7 @@ impl Actor for Download { } impl Download { - async fn prepare(urls: &[UrlCow<'_>]) { + async fn prepare(urls: &[UrlBuf]) { let roots: HashSet<_> = urls.iter().filter_map(|u| u.scheme().cache()).collect(); for mut root in roots { root.push("%lock"); diff --git a/yazi-actor/src/mgr/open.rs b/yazi-actor/src/mgr/open.rs index d49bf177..4a39468c 100644 --- a/yazi-actor/src/mgr/open.rs +++ b/yazi-actor/src/mgr/open.rs @@ -1,4 +1,6 @@ use anyhow::Result; +use futures::StreamExt; +use hashbrown::HashSet; use yazi_boot::ARGS; use yazi_core::mgr::OpenDoOpt; use yazi_fs::File; @@ -31,17 +33,17 @@ impl Actor for Open { if opt.targets.is_empty() { opt.targets = if opt.hovered { - cx.hovered().map(|h| vec![h.url.clone().into()]).unwrap_or_default() + cx.hovered().map(|h| vec![h.url.clone()]).unwrap_or_default() } else { act!(mgr:escape_visual, cx)?; - cx.tab().selected_or_hovered().cloned().map(Into::into).collect() + cx.tab().selected_or_hovered().cloned().collect() }; } if opt.targets.is_empty() { succ!(); } - let todo: Vec<_> = opt + let todo: HashSet<_> = opt .targets .iter() .enumerate() @@ -49,21 +51,28 @@ impl Actor for Open { .map(|(i, _)| i) .collect(); - let cwd = opt.cwd.unwrap_or_else(|| cx.cwd().clone().into()); - if todo.is_empty() { - return act!(mgr:open_do, cx, OpenDoOpt { cwd, targets: opt.targets, interactive: opt.interactive }); - } - + let cwd = opt.cwd.unwrap_or_else(|| cx.cwd().clone()); let scheduler = cx.tasks.scheduler.clone(); tokio::spawn(async move { - let mut files = Vec::with_capacity(todo.len()); - for i in todo { - if let Ok(f) = File::new(&opt.targets[i]).await { - files.push(f); + let mut all = Vec::with_capacity(opt.targets.len()); + let mut part = Vec::with_capacity(todo.len()); + + let it = futures::stream::iter(opt.targets) + .enumerate() + .map(|(i, url)| async move { File::new(url).await.ok().map(|file| (i, file)) }) + .buffered(3) + .filter_map(|item| async move { item }); + + futures::pin_mut!(it); + while let Some((i, file)) = it.next().await { + if todo.contains(&i) { + part.push(file.clone()); } + all.push(file); } - if scheduler.fetch_mimetype(files).await { - MgrProxy::open_do(OpenDoOpt { cwd, targets: opt.targets, interactive: opt.interactive }); + + if !all.is_empty() && scheduler.fetch_mimetype(part).await { + MgrProxy::open_do(OpenDoOpt { cwd, targets: all, interactive: opt.interactive }); } }); succ!(); diff --git a/yazi-actor/src/mgr/open_do.rs b/yazi-actor/src/mgr/open_do.rs index 95d59e00..3af6eac8 100644 --- a/yazi-actor/src/mgr/open_do.rs +++ b/yazi-actor/src/mgr/open_do.rs @@ -5,7 +5,7 @@ use yazi_macro::succ; use yazi_parser::mgr::OpenDoForm; use yazi_proxy::{PickProxy, TasksProxy}; use yazi_scheduler::process::ProcessOpt; -use yazi_shared::{data::Data, url::UrlCow}; +use yazi_shared::{data::Data, url::{UrlBuf, UrlCow}}; use crate::{Actor, Ctx}; @@ -20,9 +20,9 @@ impl Actor for OpenDo { let targets: Vec<_> = opt .targets .into_iter() - .map(|u| { - let m = cx.mgr.mimetype.get(&u).unwrap_or_default(); - (u, m) + .map(|file| { + let mime = cx.mgr.mimetype.get(&file.url).unwrap_or_default(); + (file, mime) }) .filter(|(_, m)| !m.is_empty()) .collect(); @@ -39,8 +39,10 @@ impl Actor for OpenDo { } let pick = PickProxy::show(PickCfg::open(openers.iter().map(|o| o.desc()).collect())); - let urls: Vec<_> = - [UrlCow::default()].into_iter().chain(targets.into_iter().map(|(u, _)| u)).collect(); + let urls: Vec<_> = [UrlCow::default()] + .into_iter() + .chain(targets.into_iter().map(|(file, _)| file.url.into())) + .collect(); tokio::spawn(async move { if let Some(choice) = pick.await { TasksProxy::open_shell_compat(ProcessOpt { @@ -59,11 +61,11 @@ impl Actor for OpenDo { impl OpenDo { // TODO: remove - fn match_and_open(cx: &Ctx, cwd: UrlCow<'static>, targets: Vec<(UrlCow<'static>, &str)>) { + fn match_and_open(cx: &Ctx, cwd: UrlBuf, targets: Vec<(yazi_fs::File, &str)>) { let mut openers = HashMap::new(); - for (url, mime) in targets { - if let Some(opener) = YAZI.opener.first(YAZI.open.all(&url, mime)) { - openers.entry(opener).or_insert_with(|| vec![UrlCow::default()]).push(url); + for (file, mime) in targets { + if let Some(opener) = YAZI.opener.first(YAZI.open.all(&file, mime)) { + openers.entry(opener).or_insert_with(|| vec![UrlCow::default()]).push(file.url.into()); } } for (opener, args) in openers { diff --git a/yazi-actor/src/mgr/seek.rs b/yazi-actor/src/mgr/seek.rs index 6e0ed78d..fde0477a 100644 --- a/yazi-actor/src/mgr/seek.rs +++ b/yazi-actor/src/mgr/seek.rs @@ -25,12 +25,12 @@ impl Actor for Seek { succ!(cx.tab_mut().preview.reset()); }; - let Some(previewer) = YAZI.plugin.previewer(hovered, mime) else { + let Some(previewer) = YAZI.plugin.previewers.matches(hovered, mime) else { succ!(cx.tab_mut().preview.reset()); }; let job = SeekJob { file: hovered.clone(), units: form.units }; - let opt = PluginOpt::new_callback(&*previewer.run.name, move |_, plugin| { + let opt = PluginOpt::new_callback(previewer.name.clone(), move |_, plugin| { plugin.call_method("seek", job) }); act!(app:plugin, cx, opt) diff --git a/yazi-actor/src/mgr/shell.rs b/yazi-actor/src/mgr/shell.rs index eb4a02c6..de091fb9 100644 --- a/yazi-actor/src/mgr/shell.rs +++ b/yazi-actor/src/mgr/shell.rs @@ -21,7 +21,7 @@ impl Actor for Shell { fn act(cx: &mut Ctx, mut form: Self::Form) -> Result { act!(mgr:escape_visual, cx)?; - let cwd = form.cwd.take().unwrap_or(cx.cwd().into()).into_owned(); + let cwd = form.cwd.take().unwrap_or_else(|| cx.cwd().clone()); let selected: Vec<_> = cx.tab().hovered_and_selected().cloned().map(Into::into).collect(); let input = form.interactive.then(|| { @@ -40,7 +40,7 @@ impl Actor for Shell { } TasksProxy::open_shell_compat(ProcessOpt { - cwd: cwd.into(), + cwd, cmd: form.run.to_string().into(), args: selected, block: form.block, diff --git a/yazi-actor/src/mgr/toggle.rs b/yazi-actor/src/mgr/toggle.rs index 59f7a455..b9c129a4 100644 --- a/yazi-actor/src/mgr/toggle.rs +++ b/yazi-actor/src/mgr/toggle.rs @@ -2,7 +2,7 @@ use anyhow::Result; use yazi_macro::{render_and, succ}; use yazi_parser::mgr::ToggleForm; use yazi_scheduler::NotifyProxy; -use yazi_shared::{data::Data, url::UrlCow}; +use yazi_shared::data::Data; use crate::{Actor, Ctx}; @@ -15,7 +15,7 @@ impl Actor for Toggle { fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tab = cx.tab_mut(); - let Some(url) = form.url.or(tab.current.hovered().map(|h| UrlCow::from(&h.url))) else { + let Some(url) = form.url.or_else(|| tab.hovered().map(|h| h.url.clone())) else { succ!(); }; diff --git a/yazi-actor/src/mgr/upload.rs b/yazi-actor/src/mgr/upload.rs index d44fe224..2ba8d8b0 100644 --- a/yazi-actor/src/mgr/upload.rs +++ b/yazi-actor/src/mgr/upload.rs @@ -14,7 +14,7 @@ impl Actor for Upload { fn act(cx: &mut Ctx, form: Self::Form) -> Result { for url in form.urls { - cx.tasks.scheduler.file_upload(url.into_owned()); + cx.tasks.scheduler.file_upload(url); } succ!(); } diff --git a/yazi-adapter/src/adapters.rs b/yazi-adapter/src/adapters.rs index 36b50e71..77912c41 100644 --- a/yazi-adapter/src/adapters.rs +++ b/yazi-adapter/src/adapters.rs @@ -33,7 +33,7 @@ impl From for Adapters { B::Ghostty => vec![A::Kgp], B::Microsoft => vec![A::Sixel], B::Warp => vec![A::Iip, A::KgpOld], - B::Rio => vec![A::Iip, A::Sixel], + B::Rio => vec![A::Kgp], B::BlackBox => vec![A::Sixel], B::VSCode => vec![A::Iip, A::Sixel], B::Tabby => vec![A::Iip, A::Sixel], diff --git a/yazi-binding/src/access.rs b/yazi-binding/src/access.rs index bb8a1d85..1134d982 100644 --- a/yazi-binding/src/access.rs +++ b/yazi-binding/src/access.rs @@ -8,15 +8,15 @@ pub struct Access(yazi_vfs::provider::Gate); impl UserData for Access { fn add_methods>(methods: &mut M) { - methods.add_function_mut("append", |_, (ud, append): (AnyUserData, bool)| { + methods.add_function("append", |_, (ud, append): (AnyUserData, bool)| { ud.borrow_mut::()?.0.append(append); Ok(ud) }); - methods.add_function_mut("create", |_, (ud, create): (AnyUserData, bool)| { + methods.add_function("create", |_, (ud, create): (AnyUserData, bool)| { ud.borrow_mut::()?.0.create(create); Ok(ud) }); - methods.add_function_mut("create_new", |_, (ud, create_new): (AnyUserData, bool)| { + methods.add_function("create_new", |_, (ud, create_new): (AnyUserData, bool)| { ud.borrow_mut::()?.0.create_new(create_new); Ok(ud) }); @@ -26,15 +26,15 @@ impl UserData for Access { Err(e) => (Value::Nil, Error::Io(e)).into_lua_multi(&lua), } }); - methods.add_function_mut("read", |_, (ud, read): (AnyUserData, bool)| { + methods.add_function("read", |_, (ud, read): (AnyUserData, bool)| { ud.borrow_mut::()?.0.read(read); Ok(ud) }); - methods.add_function_mut("truncate", |_, (ud, truncate): (AnyUserData, bool)| { + methods.add_function("truncate", |_, (ud, truncate): (AnyUserData, bool)| { ud.borrow_mut::()?.0.truncate(truncate); Ok(ud) }); - methods.add_function_mut("write", |_, (ud, write): (AnyUserData, bool)| { + methods.add_function("write", |_, (ud, write): (AnyUserData, bool)| { ud.borrow_mut::()?.0.write(write); Ok(ud) }); diff --git a/yazi-binding/src/config/fetcher.rs b/yazi-binding/src/config/fetcher.rs new file mode 100644 index 00000000..eb2d799e --- /dev/null +++ b/yazi-binding/src/config/fetcher.rs @@ -0,0 +1,32 @@ +use std::{ops::Deref, sync::Arc}; + +use mlua::{UserData, UserDataFields, Value}; + +use crate::{Id, cached_field}; + +#[derive(Clone)] +pub struct Fetcher { + inner: Arc, + + v_name: Option, +} + +impl Deref for Fetcher { + type Target = yazi_config::plugin::Fetcher; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +impl Fetcher { + pub fn new(inner: impl Into>) -> Self { + Self { inner: inner.into(), v_name: None } + } +} + +impl UserData for Fetcher { + fn add_fields>(fields: &mut F) { + fields.add_field_method_get("id", |_, me| Ok(Id(me.id))); + + cached_field!(fields, name, |lua, me| lua.create_string(&*me.name)); + } +} diff --git a/yazi-binding/src/config/fetchers.rs b/yazi-binding/src/config/fetchers.rs new file mode 100644 index 00000000..922efc34 --- /dev/null +++ b/yazi-binding/src/config/fetchers.rs @@ -0,0 +1,59 @@ +use mlua::{ExternalError, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; +use yazi_config::YAZI; + +use crate::{FileRef, Id, Iter, config::Fetcher}; + +pub struct Fetchers; + +impl UserData for Fetchers { + fn add_methods>(methods: &mut M) { + methods.add_method("match", |lua, _, matcher: Option| match matcher { + Some(matcher) => matcher.into_lua(lua), + None => FetcherMatcher::new(&YAZI.plugin.fetchers).into_lua(lua), + }); + + methods.add_meta_method(MetaMethod::Len, |_, _, ()| Ok(YAZI.plugin.fetchers.load().len())); + } +} + +// --- Matcher +pub struct FetcherMatcher(yazi_config::plugin::FetcherMatcher<'static>); + +impl FetcherMatcher { + fn new(inner: impl Into>) -> Self { + Self(inner.into()) + } +} + +impl TryFrom for FetcherMatcher { + type Error = mlua::Error; + + fn try_from(value: Table) -> Result { + let id: Id = value.raw_get("id").unwrap_or_default(); + let file: Option = value.raw_get("file")?; + let mime: Option = value.raw_get("mime")?; + + Ok(Self(yazi_config::plugin::FetcherMatcher { + fetchers: YAZI.plugin.fetchers.load_full(), + id: id.0, + file: file.map(|f| f.inner.clone().into()), + mime: mime.map(Into::into), + ..Default::default() + })) + } +} + +impl FromLua for FetcherMatcher { + fn from_lua(value: Value, _: &Lua) -> mlua::Result { + match value { + Value::Table(t) => t.try_into(), + _ => return Err("expected a table of FetcherMatcher".into_lua_err()), + } + } +} + +impl IntoLua for FetcherMatcher { + fn into_lua(self, lua: &Lua) -> mlua::Result { + Iter::new(self.0.into_iter().map(Fetcher::new), None).into_lua(lua) + } +} diff --git a/yazi-binding/src/config/mod.rs b/yazi-binding/src/config/mod.rs new file mode 100644 index 00000000..5d106eb4 --- /dev/null +++ b/yazi-binding/src/config/mod.rs @@ -0,0 +1 @@ +yazi_macro::mod_flat!(fetcher fetchers preloader preloaders previewer previewers spotter spotters); diff --git a/yazi-binding/src/config/preloader.rs b/yazi-binding/src/config/preloader.rs new file mode 100644 index 00000000..08403d5a --- /dev/null +++ b/yazi-binding/src/config/preloader.rs @@ -0,0 +1,32 @@ +use std::{ops::Deref, sync::Arc}; + +use mlua::{UserData, UserDataFields, Value}; + +use crate::{Id, cached_field}; + +#[derive(Clone)] +pub struct Preloader { + inner: Arc, + + v_name: Option, +} + +impl Deref for Preloader { + type Target = yazi_config::plugin::Preloader; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +impl Preloader { + pub fn new(inner: impl Into>) -> Self { + Self { inner: inner.into(), v_name: None } + } +} + +impl UserData for Preloader { + fn add_fields>(fields: &mut F) { + fields.add_field_method_get("id", |_, me| Ok(Id(me.id))); + + cached_field!(fields, name, |lua, me| lua.create_string(&*me.name)); + } +} diff --git a/yazi-binding/src/config/preloaders.rs b/yazi-binding/src/config/preloaders.rs new file mode 100644 index 00000000..dfa87eaf --- /dev/null +++ b/yazi-binding/src/config/preloaders.rs @@ -0,0 +1,59 @@ +use mlua::{ExternalError, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; +use yazi_config::YAZI; + +use crate::{FileRef, Id, Iter, config::Preloader}; + +pub struct Preloaders; + +impl UserData for Preloaders { + fn add_methods>(methods: &mut M) { + methods.add_method("match", |lua, _, matcher: Option| match matcher { + Some(matcher) => matcher.into_lua(lua), + None => PreloaderMatcher::new(&YAZI.plugin.preloaders).into_lua(lua), + }); + + methods.add_meta_method(MetaMethod::Len, |_, _, ()| Ok(YAZI.plugin.preloaders.load().len())); + } +} + +// --- Matcher +pub struct PreloaderMatcher(yazi_config::plugin::PreloaderMatcher<'static>); + +impl PreloaderMatcher { + fn new(inner: impl Into>) -> Self { + Self(inner.into()) + } +} + +impl TryFrom
for PreloaderMatcher { + type Error = mlua::Error; + + fn try_from(value: Table) -> Result { + let id: Id = value.raw_get("id").unwrap_or_default(); + let file: Option = value.raw_get("file")?; + let mime: Option = value.raw_get("mime")?; + + Ok(Self(yazi_config::plugin::PreloaderMatcher { + preloaders: YAZI.plugin.preloaders.load_full(), + id: id.0, + file: file.map(|f| f.inner.clone().into()), + mime: mime.map(Into::into), + ..Default::default() + })) + } +} + +impl FromLua for PreloaderMatcher { + fn from_lua(value: Value, _: &Lua) -> mlua::Result { + match value { + Value::Table(t) => t.try_into(), + _ => return Err("expected a table of PreloaderMatcher".into_lua_err()), + } + } +} + +impl IntoLua for PreloaderMatcher { + fn into_lua(self, lua: &Lua) -> mlua::Result { + Iter::new(self.0.into_iter().map(Preloader::new), None).into_lua(lua) + } +} diff --git a/yazi-binding/src/config/previewer.rs b/yazi-binding/src/config/previewer.rs new file mode 100644 index 00000000..8530c949 --- /dev/null +++ b/yazi-binding/src/config/previewer.rs @@ -0,0 +1,69 @@ +use std::{ops::Deref, sync::Arc}; + +use mlua::{AnyUserData, ExternalError, FromLua, Lua, UserData, UserDataFields, Value}; +use yazi_config::plugin::previewer_id; + +use crate::{Id, Selector, cached_field}; + +const EXPECTED: &str = "expected a table or Previewer"; + +#[derive(Clone)] +pub struct Previewer { + inner: Arc, + + v_name: Option, +} + +impl Deref for Previewer { + type Target = yazi_config::plugin::Previewer; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +impl From for Arc { + fn from(value: Previewer) -> Self { value.inner } +} + +impl Previewer { + pub fn new(inner: impl Into>) -> Self { + Self { inner: inner.into(), v_name: None } + } +} + +impl TryFrom for Previewer { + type Error = mlua::Error; + + fn try_from(t: mlua::Table) -> Result { + Ok(Self::new(yazi_config::plugin::Previewer { + id: previewer_id(), + selector: Selector::try_from(&t)?.into(), + run: t.raw_get::("run")?.to_str()?.parse()?, + })) + } +} + +impl TryFrom for Previewer { + type Error = mlua::Error; + + fn try_from(value: AnyUserData) -> Result { + Ok(Self::new(value.borrow::()?.clone())) + } +} + +impl FromLua for Previewer { + fn from_lua(value: Value, _: &Lua) -> mlua::Result { + match value { + Value::Table(tbl) => Self::try_from(tbl), + Value::UserData(ud) => Self::try_from(ud), + _ => Err(EXPECTED.into_lua_err())?, + } + } +} + +impl UserData for Previewer { + fn add_fields>(fields: &mut F) { + fields.add_field_method_get("id", |_, me| Ok(Id(me.id))); + + cached_field!(fields, name, |lua, me| lua.create_string(&*me.name)); + } +} diff --git a/yazi-binding/src/config/previewers.rs b/yazi-binding/src/config/previewers.rs new file mode 100644 index 00000000..df5835d6 --- /dev/null +++ b/yazi-binding/src/config/previewers.rs @@ -0,0 +1,75 @@ +use mlua::{ExternalError, ExternalResult, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; +use yazi_config::YAZI; + +use crate::{FileRef, Id, Iter, config::Previewer}; + +pub struct Previewers; + +impl UserData for Previewers { + fn add_methods>(methods: &mut M) { + methods.add_method("match", |lua, _, matcher: Option| match matcher { + Some(matcher) => matcher.into_lua(lua), + None => PreviewerMatcher::new(&YAZI.plugin.previewers).into_lua(lua), + }); + + methods.add_method("insert", |_, _, (index, previewer): (isize, Previewer)| { + let index = match index { + 1.. => index - 1, + 0 => return Err("index must be 1-based or negative".into_lua_err()), + _ => index, + }; + + YAZI.plugin.previewers.insert(index, previewer.clone().into()).into_lua_err()?; + Ok(previewer) + }); + + methods.add_method("remove", |_, _, matcher: PreviewerMatcher| { + YAZI.plugin.previewers.remove(matcher.0); + Ok(()) + }); + + methods.add_meta_method(MetaMethod::Len, |_, _, ()| Ok(YAZI.plugin.previewers.load().len())); + } +} + +// --- Matcher +pub struct PreviewerMatcher(yazi_config::plugin::PreviewerMatcher<'static>); + +impl PreviewerMatcher { + fn new(inner: impl Into>) -> Self { + Self(inner.into()) + } +} + +impl TryFrom
for PreviewerMatcher { + type Error = mlua::Error; + + fn try_from(value: Table) -> Result { + let id: Id = value.raw_get("id").unwrap_or_default(); + let file: Option = value.raw_get("file")?; + let mime: Option = value.raw_get("mime")?; + + Ok(Self(yazi_config::plugin::PreviewerMatcher { + previewers: YAZI.plugin.previewers.load_full(), + id: id.0, + file: file.map(|f| f.inner.clone().into()), + mime: mime.map(Into::into), + ..Default::default() + })) + } +} + +impl FromLua for PreviewerMatcher { + fn from_lua(value: Value, _: &Lua) -> mlua::Result { + match value { + Value::Table(t) => t.try_into(), + _ => return Err("expected a table of PreviewerMatcher".into_lua_err()), + } + } +} + +impl IntoLua for PreviewerMatcher { + fn into_lua(self, lua: &Lua) -> mlua::Result { + Iter::new(self.0.into_iter().map(Previewer::new), None).into_lua(lua) + } +} diff --git a/yazi-binding/src/config/spotter.rs b/yazi-binding/src/config/spotter.rs new file mode 100644 index 00000000..be0ea1c4 --- /dev/null +++ b/yazi-binding/src/config/spotter.rs @@ -0,0 +1,32 @@ +use std::{ops::Deref, sync::Arc}; + +use mlua::{UserData, UserDataFields, Value}; + +use crate::{Id, cached_field}; + +#[derive(Clone)] +pub struct Spotter { + inner: Arc, + + v_name: Option, +} + +impl Deref for Spotter { + type Target = yazi_config::plugin::Spotter; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +impl Spotter { + pub fn new(inner: impl Into>) -> Self { + Self { inner: inner.into(), v_name: None } + } +} + +impl UserData for Spotter { + fn add_fields>(fields: &mut F) { + fields.add_field_method_get("id", |_, me| Ok(Id(me.id))); + + cached_field!(fields, name, |lua, me| lua.create_string(&*me.name)); + } +} diff --git a/yazi-binding/src/config/spotters.rs b/yazi-binding/src/config/spotters.rs new file mode 100644 index 00000000..5e4a2d4b --- /dev/null +++ b/yazi-binding/src/config/spotters.rs @@ -0,0 +1,59 @@ +use mlua::{ExternalError, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; +use yazi_config::YAZI; + +use crate::{FileRef, Id, Iter, config::Spotter}; + +pub struct Spotters; + +impl UserData for Spotters { + fn add_methods>(methods: &mut M) { + methods.add_method("match", |lua, _, matcher: Option| match matcher { + Some(matcher) => matcher.into_lua(lua), + None => SpotterMatcher::new(&YAZI.plugin.spotters).into_lua(lua), + }); + + methods.add_meta_method(MetaMethod::Len, |_, _, ()| Ok(YAZI.plugin.spotters.load().len())); + } +} + +// --- Matcher +pub struct SpotterMatcher(yazi_config::plugin::SpotterMatcher<'static>); + +impl SpotterMatcher { + fn new(inner: impl Into>) -> Self { + Self(inner.into()) + } +} + +impl TryFrom
for SpotterMatcher { + type Error = mlua::Error; + + fn try_from(value: Table) -> Result { + let id: Id = value.raw_get("id").unwrap_or_default(); + let file: Option = value.raw_get("file")?; + let mime: Option = value.raw_get("mime")?; + + Ok(Self(yazi_config::plugin::SpotterMatcher { + spotters: YAZI.plugin.spotters.load_full(), + id: id.0, + file: file.map(|f| f.inner.clone().into()), + mime: mime.map(Into::into), + ..Default::default() + })) + } +} + +impl FromLua for SpotterMatcher { + fn from_lua(value: Value, _: &Lua) -> mlua::Result { + match value { + Value::Table(t) => t.try_into(), + _ => return Err("expected a table of SpotterMatcher".into_lua_err()), + } + } +} + +impl IntoLua for SpotterMatcher { + fn into_lua(self, lua: &Lua) -> mlua::Result { + Iter::new(self.0.into_iter().map(Spotter::new), None).into_lua(lua) + } +} diff --git a/yazi-binding/src/elements/bar.rs b/yazi-binding/src/elements/bar.rs index a3eb15a1..eb94303b 100644 --- a/yazi-binding/src/elements/bar.rs +++ b/yazi-binding/src/elements/bar.rs @@ -81,11 +81,11 @@ impl UserData for Bar { crate::impl_area_method!(methods); crate::impl_style_method!(methods, style); - methods.add_function_mut("edge", |_, (ud, edge): (AnyUserData, Edge)| { + methods.add_function("edge", |_, (ud, edge): (AnyUserData, Edge)| { ud.borrow_mut::()?.edge = edge; Ok(ud) }); - methods.add_function_mut("symbol", |_, (ud, symbol): (AnyUserData, String)| { + methods.add_function("symbol", |_, (ud, symbol): (AnyUserData, String)| { ud.borrow_mut::()?.symbol = symbol; Ok(ud) }); diff --git a/yazi-binding/src/elements/border.rs b/yazi-binding/src/elements/border.rs index f32d0038..a56ac58d 100644 --- a/yazi-binding/src/elements/border.rs +++ b/yazi-binding/src/elements/border.rs @@ -79,7 +79,7 @@ impl UserData for Border { crate::impl_area_method!(methods); crate::impl_style_method!(methods, style); - methods.add_function_mut("type", |_, (ud, value): (AnyUserData, u8)| { + methods.add_function("type", |_, (ud, value): (AnyUserData, u8)| { ud.borrow_mut::()?.r#type = match value { ROUNDED => ratatui::widgets::BorderType::Rounded, DOUBLE => ratatui::widgets::BorderType::Double, @@ -90,20 +90,17 @@ impl UserData for Border { }; Ok(ud) }); - methods.add_function_mut( - "title", - |_, (ud, line, position): (AnyUserData, Line, Option)| { - let position = if position == Some(Borders::BOTTOM.bits()) { - ratatui::widgets::TitlePosition::Bottom - } else { - ratatui::widgets::TitlePosition::Top - }; + methods.add_function("title", |_, (ud, line, position): (AnyUserData, Line, Option)| { + let position = if position == Some(Borders::BOTTOM.bits()) { + ratatui::widgets::TitlePosition::Bottom + } else { + ratatui::widgets::TitlePosition::Top + }; - ud.borrow_mut::()?.titles.push((position, line.inner)); - Ok(ud) - }, - ); - methods.add_function_mut("edge", |_, (ud, edge): (AnyUserData, Edge)| { + ud.borrow_mut::()?.titles.push((position, line.inner)); + Ok(ud) + }); + methods.add_function("edge", |_, (ud, edge): (AnyUserData, Edge)| { ud.borrow_mut::()?.edge = edge; Ok(ud) }); diff --git a/yazi-binding/src/elements/gauge.rs b/yazi-binding/src/elements/gauge.rs index c3543a5c..d9eb611c 100644 --- a/yazi-binding/src/elements/gauge.rs +++ b/yazi-binding/src/elements/gauge.rs @@ -57,7 +57,7 @@ impl UserData for Gauge { crate::impl_area_method!(methods); crate::impl_style_method!(methods, style); - methods.add_function_mut("percent", |_, (ud, percent): (AnyUserData, u8)| { + methods.add_function("percent", |_, (ud, percent): (AnyUserData, u8)| { if percent > 100 { return Err("percent must be between 0 and 100".into_lua_err()); } @@ -66,7 +66,7 @@ impl UserData for Gauge { Ok(ud) }); - methods.add_function_mut("ratio", |_, (ud, ratio): (AnyUserData, f64)| { + methods.add_function("ratio", |_, (ud, ratio): (AnyUserData, f64)| { if !(0.0..1.0).contains(&ratio) { return Err("ratio must be between 0 and 1".into_lua_err()); } @@ -75,12 +75,12 @@ impl UserData for Gauge { Ok(ud) }); - methods.add_function_mut("label", |_, (ud, label): (AnyUserData, Span)| { + methods.add_function("label", |_, (ud, label): (AnyUserData, Span)| { ud.borrow_mut::()?.label = Some(label.0); Ok(ud) }); - methods.add_function_mut("gauge_style", |_, (ud, style): (AnyUserData, Style)| { + methods.add_function("gauge_style", |_, (ud, style): (AnyUserData, Style)| { ud.borrow_mut::()?.gauge_style = style.0; Ok(ud) }); diff --git a/yazi-binding/src/elements/layout.rs b/yazi-binding/src/elements/layout.rs index 5449d70e..bf499894 100644 --- a/yazi-binding/src/elements/layout.rs +++ b/yazi-binding/src/elements/layout.rs @@ -25,15 +25,15 @@ impl Layout { impl UserData for Layout { fn add_methods>(methods: &mut M) { - methods.add_function_mut("direction", |_, (ud, value): (AnyUserData, bool)| { + methods.add_function("direction", |_, (ud, value): (AnyUserData, bool)| { ud.borrow_mut::()?.direction = value; Ok(ud) }); - methods.add_function_mut("margin", |_, (ud, value): (AnyUserData, u16)| { + methods.add_function("margin", |_, (ud, value): (AnyUserData, u16)| { ud.borrow_mut::()?.margin = Some(ratatui::layout::Margin::new(value, value)); Ok(ud) }); - methods.add_function_mut("margin_h", |_, (ud, value): (AnyUserData, u16)| { + methods.add_function("margin_h", |_, (ud, value): (AnyUserData, u16)| { { let mut me = ud.borrow_mut::()?; if let Some(margin) = &mut me.margin { @@ -44,7 +44,7 @@ impl UserData for Layout { } Ok(ud) }); - methods.add_function_mut("margin_v", |_, (ud, value): (AnyUserData, u16)| { + methods.add_function("margin_v", |_, (ud, value): (AnyUserData, u16)| { { let mut me = ud.borrow_mut::()?; if let Some(margin) = &mut me.margin { @@ -55,7 +55,7 @@ impl UserData for Layout { } Ok(ud) }); - methods.add_function_mut("constraints", |_, (ud, value): (AnyUserData, Vec)| { + methods.add_function("constraints", |_, (ud, value): (AnyUserData, Vec)| { ud.borrow_mut::()?.constraints = value.into_iter().map(Into::into).collect(); Ok(ud) }); diff --git a/yazi-binding/src/elements/line.rs b/yazi-binding/src/elements/line.rs index 8d23a4a2..7a38dfcb 100644 --- a/yazi-binding/src/elements/line.rs +++ b/yazi-binding/src/elements/line.rs @@ -133,14 +133,14 @@ impl UserData for Line { crate::impl_style_shorthands!(methods, style); methods.add_method("width", |_, me, ()| Ok(me.width())); - methods.add_function_mut("align", |_, (ud, align): (AnyUserData, Align)| { + methods.add_function("align", |_, (ud, align): (AnyUserData, Align)| { ud.borrow_mut::()?.alignment = Some(align.0); Ok(ud) }); methods.add_method("visible", |_, me, ()| { Ok(me.iter().flat_map(|s| s.content.chars()).any(|c| c.width().unwrap_or(0) > 0)) }); - methods.add_function_mut("truncate", |lua, (ud, t): (AnyUserData, Table)| { + methods.add_function("truncate", |lua, (ud, t): (AnyUserData, Table)| { let mut me = ud.borrow_mut::()?; let max = t.raw_get("max")?; diff --git a/yazi-binding/src/elements/pos.rs b/yazi-binding/src/elements/pos.rs index 5912f223..4e701c4c 100644 --- a/yazi-binding/src/elements/pos.rs +++ b/yazi-binding/src/elements/pos.rs @@ -91,7 +91,7 @@ impl UserData for Pos { } fn add_methods>(methods: &mut M) { - methods.add_function_mut("pad", |_, (ud, pad): (AnyUserData, Pad)| { + methods.add_function("pad", |_, (ud, pad): (AnyUserData, Pad)| { ud.borrow_mut::()?.pad = pad; Ok(ud) }); diff --git a/yazi-binding/src/elements/row.rs b/yazi-binding/src/elements/row.rs index 9120eeb7..969f81ef 100644 --- a/yazi-binding/src/elements/row.rs +++ b/yazi-binding/src/elements/row.rs @@ -55,15 +55,15 @@ impl UserData for Row { fn add_methods>(methods: &mut M) { crate::impl_style_method!(methods, style); - methods.add_function_mut("height", |_, (ud, value): (AnyUserData, u16)| { + methods.add_function("height", |_, (ud, value): (AnyUserData, u16)| { ud.borrow_mut::()?.height = value; Ok(ud) }); - methods.add_function_mut("margin_t", |_, (ud, value): (AnyUserData, u16)| { + methods.add_function("margin_t", |_, (ud, value): (AnyUserData, u16)| { ud.borrow_mut::()?.top_margin = value; Ok(ud) }); - methods.add_function_mut("margin_b", |_, (ud, value): (AnyUserData, u16)| { + methods.add_function("margin_b", |_, (ud, value): (AnyUserData, u16)| { ud.borrow_mut::()?.bottom_margin = value; Ok(ud) }); diff --git a/yazi-binding/src/elements/span.rs b/yazi-binding/src/elements/span.rs index 22609808..717a0d73 100644 --- a/yazi-binding/src/elements/span.rs +++ b/yazi-binding/src/elements/span.rs @@ -82,7 +82,7 @@ impl UserData for Span { methods.add_method("visible", |_, Self(me), ()| { Ok(me.content.chars().any(|c| c.width().unwrap_or(0) > 0)) }); - methods.add_function_mut("truncate", |_, (ud, t): (AnyUserData, Table)| { + methods.add_function("truncate", |_, (ud, t): (AnyUserData, Table)| { ud.borrow_mut::()?.truncate(t.raw_get("max")?); Ok(ud) }); diff --git a/yazi-binding/src/elements/table.rs b/yazi-binding/src/elements/table.rs index 9fa5ead1..f7defacf 100644 --- a/yazi-binding/src/elements/table.rs +++ b/yazi-binding/src/elements/table.rs @@ -108,45 +108,45 @@ impl UserData for Table { fn add_methods>(methods: &mut M) { crate::impl_area_method!(methods); - methods.add_function_mut("header", |_, (ud, header): (AnyUserData, Row)| { + methods.add_function("header", |_, (ud, header): (AnyUserData, Row)| { ud.borrow_mut::()?.header = Some(header.into()); Ok(ud) }); - methods.add_function_mut("footer", |_, (ud, footer): (AnyUserData, Row)| { + methods.add_function("footer", |_, (ud, footer): (AnyUserData, Row)| { ud.borrow_mut::()?.footer = Some(footer.into()); Ok(ud) }); - methods.add_function_mut("widths", |_, (ud, widths): (AnyUserData, Vec)| { + methods.add_function("widths", |_, (ud, widths): (AnyUserData, Vec)| { ud.borrow_mut::()?.widths = widths.into_iter().map(Into::into).collect(); Ok(ud) }); - methods.add_function_mut("spacing", |_, (ud, spacing): (AnyUserData, u16)| { + methods.add_function("spacing", |_, (ud, spacing): (AnyUserData, u16)| { ud.borrow_mut::()?.column_spacing = spacing; Ok(ud) }); - methods.add_function_mut("row", |_, (ud, idx): (AnyUserData, Option)| { + methods.add_function("row", |_, (ud, idx): (AnyUserData, Option)| { ud.borrow_mut::()?.state.select(idx); Ok(ud) }); - methods.add_function_mut("col", |_, (ud, idx): (AnyUserData, Option)| { + methods.add_function("col", |_, (ud, idx): (AnyUserData, Option)| { ud.borrow_mut::()?.state.select_column(idx); Ok(ud) }); - methods.add_function_mut("style", |_, (ud, style): (AnyUserData, Style)| { + methods.add_function("style", |_, (ud, style): (AnyUserData, Style)| { ud.borrow_mut::()?.style = style.0; Ok(ud) }); - methods.add_function_mut("row_style", |_, (ud, style): (AnyUserData, Style)| { + methods.add_function("row_style", |_, (ud, style): (AnyUserData, Style)| { ud.borrow_mut::()?.row_highlight_style = style.0; Ok(ud) }); - methods.add_function_mut("col_style", |_, (ud, style): (AnyUserData, Style)| { + methods.add_function("col_style", |_, (ud, style): (AnyUserData, Style)| { ud.borrow_mut::()?.column_highlight_style = style.0; Ok(ud) }); - methods.add_function_mut("cell_style", |_, (ud, style): (AnyUserData, Style)| { + methods.add_function("cell_style", |_, (ud, style): (AnyUserData, Style)| { ud.borrow_mut::()?.cell_highlight_style = style.0; Ok(ud) }); diff --git a/yazi-binding/src/elements/text.rs b/yazi-binding/src/elements/text.rs index 47e824f3..64b0f8cf 100644 --- a/yazi-binding/src/elements/text.rs +++ b/yazi-binding/src/elements/text.rs @@ -124,15 +124,15 @@ impl UserData for Text { crate::impl_style_method!(methods, inner.style); crate::impl_style_shorthands!(methods, inner.style); - methods.add_function_mut("align", |_, (ud, align): (AnyUserData, Align)| { + methods.add_function("align", |_, (ud, align): (AnyUserData, Align)| { ud.borrow_mut::()?.inner.alignment = Some(align.0); Ok(ud) }); - methods.add_function_mut("wrap", |_, (ud, wrap): (AnyUserData, Wrap)| { + methods.add_function("wrap", |_, (ud, wrap): (AnyUserData, Wrap)| { ud.borrow_mut::()?.wrap = wrap; Ok(ud) }); - methods.add_function_mut("scroll", |_, (ud, x, y): (AnyUserData, u16, u16)| { + methods.add_function("scroll", |_, (ud, x, y): (AnyUserData, u16, u16)| { ud.borrow_mut::()?.scroll = ratatui::layout::Position { x, y }; Ok(ud) }); diff --git a/yazi-binding/src/file.rs b/yazi-binding/src/file.rs index d4c5761c..0ef0b640 100644 --- a/yazi-binding/src/file.rs +++ b/yazi-binding/src/file.rs @@ -10,7 +10,7 @@ const EXPECTED: &str = "expected a table, File, or fs::File"; #[derive(Clone)] pub struct File { - inner: yazi_fs::File, + pub(crate) inner: yazi_fs::File, v_cha: Option, v_url: Option, diff --git a/yazi-binding/src/id.rs b/yazi-binding/src/id.rs index 985316b0..1b38b478 100644 --- a/yazi-binding/src/id.rs +++ b/yazi-binding/src/id.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use mlua::{ExternalError, ExternalResult, FromLua, Lua, UserData, Value}; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct Id(pub yazi_shared::Id); impl Deref for Id { diff --git a/yazi-binding/src/lib.rs b/yazi-binding/src/lib.rs index fc046f2d..8dda12e8 100644 --- a/yazi-binding/src/lib.rs +++ b/yazi-binding/src/lib.rs @@ -1,5 +1,5 @@ mod macros; -yazi_macro::mod_pub!(elements process); +yazi_macro::mod_pub!(config elements process); -yazi_macro::mod_flat!(access calculator cha chan chord_cow composer error fd file handle icon id image input iter layer mouse path permit range runtime scheme stage style url utils); +yazi_macro::mod_flat!(access calculator cha chan chord_cow composer error fd file handle icon id image input iter layer mouse path permit range runtime scheme selector stage style url utils); diff --git a/yazi-binding/src/macros.rs b/yazi-binding/src/macros.rs index 69f4d64e..94f7c220 100644 --- a/yazi-binding/src/macros.rs +++ b/yazi-binding/src/macros.rs @@ -88,7 +88,7 @@ macro_rules! cached_field_mut { #[macro_export] macro_rules! impl_area_method { ($methods:ident) => { - $methods.add_function_mut( + $methods.add_function( "area", |lua, (ud, area): (mlua::AnyUserData, Option)| { use mlua::IntoLua; @@ -106,7 +106,7 @@ macro_rules! impl_area_method { #[macro_export] macro_rules! impl_style_method { ($methods:ident, $($field:tt).+) => { - $methods.add_function_mut("style", |_, (ud, style): (mlua::AnyUserData, $crate::Style)| { + $methods.add_function("style", |_, (ud, style): (mlua::AnyUserData, $crate::Style)| { ud.borrow_mut::()?.$($field).+ = style.0; Ok(ud) }); @@ -116,7 +116,7 @@ macro_rules! impl_style_method { #[macro_export] macro_rules! impl_style_shorthands { ($methods:ident, $($field:tt).+) => { - $methods.add_function_mut("fg", |lua, (ud, value): (mlua::AnyUserData, mlua::Value)| { + $methods.add_function("fg", |lua, (ud, value): (mlua::AnyUserData, mlua::Value)| { use $crate::elements::Color; use mlua::FromLua; use ratatui::style::Modifier; @@ -135,7 +135,7 @@ macro_rules! impl_style_shorthands { } } }); - $methods.add_function_mut("bg", |lua, (ud, value): (mlua::AnyUserData, mlua::Value)| { + $methods.add_function("bg", |lua, (ud, value): (mlua::AnyUserData, mlua::Value)| { use $crate::elements::Color; use mlua::FromLua; use ratatui::style::Modifier; @@ -154,7 +154,7 @@ macro_rules! impl_style_shorthands { } } }); - $methods.add_function_mut("bold", |_, (ud, remove): (mlua::AnyUserData, bool)| { + $methods.add_function("bold", |_, (ud, remove): (mlua::AnyUserData, bool)| { let me = &mut ud.borrow_mut::()?.$($field).+; if remove { *me = me.remove_modifier(ratatui::style::Modifier::BOLD); @@ -163,7 +163,7 @@ macro_rules! impl_style_shorthands { } Ok(ud) }); - $methods.add_function_mut("dim", |_, (ud, remove): (mlua::AnyUserData, bool)| { + $methods.add_function("dim", |_, (ud, remove): (mlua::AnyUserData, bool)| { let me = &mut ud.borrow_mut::()?.$($field).+; if remove { *me = me.remove_modifier(ratatui::style::Modifier::DIM); @@ -172,7 +172,7 @@ macro_rules! impl_style_shorthands { } Ok(ud) }); - $methods.add_function_mut("italic", |_, (ud, remove): (mlua::AnyUserData, bool)| { + $methods.add_function("italic", |_, (ud, remove): (mlua::AnyUserData, bool)| { let me = &mut ud.borrow_mut::()?.$($field).+; if remove { *me = me.remove_modifier(ratatui::style::Modifier::ITALIC); @@ -181,7 +181,7 @@ macro_rules! impl_style_shorthands { } Ok(ud) }); - $methods.add_function_mut("underline", |_, (ud, remove): (mlua::AnyUserData, bool)| { + $methods.add_function("underline", |_, (ud, remove): (mlua::AnyUserData, bool)| { let me = &mut ud.borrow_mut::()?.$($field).+; if remove { *me = me.remove_modifier(ratatui::style::Modifier::UNDERLINED); @@ -190,7 +190,7 @@ macro_rules! impl_style_shorthands { } Ok(ud) }); - $methods.add_function_mut("blink", |_, (ud, remove): (mlua::AnyUserData, bool)| { + $methods.add_function("blink", |_, (ud, remove): (mlua::AnyUserData, bool)| { let me = &mut ud.borrow_mut::()?.$($field).+; if remove { *me = me.remove_modifier(ratatui::style::Modifier::SLOW_BLINK); @@ -199,7 +199,7 @@ macro_rules! impl_style_shorthands { } Ok(ud) }); - $methods.add_function_mut("blink_rapid", |_, (ud, remove): (mlua::AnyUserData, bool)| { + $methods.add_function("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); @@ -208,7 +208,7 @@ macro_rules! impl_style_shorthands { } Ok(ud) }); - $methods.add_function_mut("reverse", |_, (ud, remove): (mlua::AnyUserData, bool)| { + $methods.add_function("reverse", |_, (ud, remove): (mlua::AnyUserData, bool)| { let me = &mut ud.borrow_mut::()?.$($field).+; if remove { *me = me.remove_modifier(ratatui::style::Modifier::REVERSED); @@ -217,7 +217,7 @@ macro_rules! impl_style_shorthands { } Ok(ud) }); - $methods.add_function_mut("hidden", |_, (ud, remove): (mlua::AnyUserData, bool)| { + $methods.add_function("hidden", |_, (ud, remove): (mlua::AnyUserData, bool)| { let me = &mut ud.borrow_mut::()?.$($field).+; if remove { *me = me.remove_modifier(ratatui::style::Modifier::HIDDEN); @@ -226,7 +226,7 @@ macro_rules! impl_style_shorthands { } Ok(ud) }); - $methods.add_function_mut("crossed", |_, (ud, remove): (mlua::AnyUserData, bool)| { + $methods.add_function("crossed", |_, (ud, remove): (mlua::AnyUserData, bool)| { let me = &mut ud.borrow_mut::()?.$($field).+; if remove { *me = me.remove_modifier(ratatui::style::Modifier::CROSSED_OUT); @@ -235,7 +235,7 @@ macro_rules! impl_style_shorthands { } Ok(ud) }); - $methods.add_function_mut("reset", |_, ud: mlua::AnyUserData| { + $methods.add_function("reset", |_, ud: mlua::AnyUserData| { ud.borrow_mut::()?.$($field).+ = ratatui::style::Style::reset(); Ok(ud) }); diff --git a/yazi-binding/src/process/child.rs b/yazi-binding/src/process/child.rs index 961cdcb9..b0550167 100644 --- a/yazi-binding/src/process/child.rs +++ b/yazi-binding/src/process/child.rs @@ -3,10 +3,9 @@ use std::{ops::DerefMut, process::ExitStatus, time::Duration}; use futures::future::try_join3; use mlua::{AnyUserData, ExternalError, IntoLua, IntoLuaMulti, Table, UserData, UserDataMethods, Value}; use tokio::{io::{self, AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader, BufWriter}, process::{ChildStderr, ChildStdin, ChildStdout}, select}; -use crate::Error; use super::Status; -use crate::process::Output; +use crate::{Error, process::Output}; pub struct Child { inner: tokio::process::Child, diff --git a/yazi-binding/src/process/command.rs b/yazi-binding/src/process/command.rs index 5dd4fdbc..bc18d5e8 100644 --- a/yazi-binding/src/process/command.rs +++ b/yazi-binding/src/process/command.rs @@ -138,7 +138,7 @@ impl UserData for Command { ) } - methods.add_function_mut("arg", |lua, (ud, arg): (AnyUserData, Value)| { + methods.add_function("arg", |lua, (ud, arg): (AnyUserData, Value)| { let mut me = ud.borrow_mut::()?; match arg { Value::Nil => return lua.create_sequence_from(me.inner.as_std().get_args())?.into_lua(lua), @@ -154,11 +154,11 @@ impl UserData for Command { } ud.into_lua(lua) }); - methods.add_function_mut("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| { + methods.add_function("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| { ud.borrow_mut::()?.inner.current_dir(dir.to_str()?.as_ref()); Ok(ud) }); - methods.add_function_mut( + methods.add_function( "env", |_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| { ud.borrow_mut::()? @@ -167,19 +167,19 @@ impl UserData for Command { Ok(ud) }, ); - methods.add_function_mut("stdin", |_, (ud, stdio): (AnyUserData, Value)| { + methods.add_function("stdin", |_, (ud, stdio): (AnyUserData, Value)| { ud.borrow_mut::()?.inner.stdin(make_stdio(stdio)?); Ok(ud) }); - methods.add_function_mut("stdout", |_, (ud, stdio): (AnyUserData, Value)| { + methods.add_function("stdout", |_, (ud, stdio): (AnyUserData, Value)| { ud.borrow_mut::()?.inner.stdout(make_stdio(stdio)?); Ok(ud) }); - methods.add_function_mut("stderr", |_, (ud, stdio): (AnyUserData, Value)| { + methods.add_function("stderr", |_, (ud, stdio): (AnyUserData, Value)| { ud.borrow_mut::()?.inner.stderr(make_stdio(stdio)?); Ok(ud) }); - methods.add_function_mut("memory", |_, (ud, max): (AnyUserData, usize)| { + methods.add_function("memory", |_, (ud, max): (AnyUserData, usize)| { ud.borrow_mut::()?.memory = Some(max); Ok(ud) }); diff --git a/yazi-binding/src/process/output.rs b/yazi-binding/src/process/output.rs index ad0a05ef..f0892486 100644 --- a/yazi-binding/src/process/output.rs +++ b/yazi-binding/src/process/output.rs @@ -1,9 +1,9 @@ use std::mem; use mlua::{UserData, Value}; -use crate::{cached_field, cached_field_mut}; use super::Status; +use crate::{cached_field, cached_field_mut}; pub struct Output { inner: std::process::Output, diff --git a/yazi-binding/src/selector.rs b/yazi-binding/src/selector.rs new file mode 100644 index 00000000..9b511599 --- /dev/null +++ b/yazi-binding/src/selector.rs @@ -0,0 +1,43 @@ +use std::ops::Deref; + +use mlua::{ExternalError, FromLua, Lua, Table, UserData, Value}; + +pub struct Selector(yazi_config::Selector); + +impl Deref for Selector { + type Target = yazi_config::Selector; + + fn deref(&self) -> &Self::Target { &self.0 } +} + +impl From for yazi_config::Selector { + fn from(value: Selector) -> Self { value.0 } +} + +impl TryFrom<&Table> for Selector { + type Error = mlua::Error; + + fn try_from(t: &Table) -> Result { + Ok(Self(yazi_config::Selector::new( + t.raw_get::>("url")?.map(|s| s.to_str()?.parse()).transpose()?, + t.raw_get::>("mime")?.map(|s| s.to_str()?.parse()).transpose()?, + )?)) + } +} + +impl TryFrom
for Selector { + type Error = mlua::Error; + + fn try_from(value: Table) -> Result { Self::try_from(&value) } +} + +impl FromLua for Selector { + fn from_lua(value: Value, _: &Lua) -> mlua::Result { + Ok(match value { + Value::Table(t) => t.try_into()?, + _ => Err("expected a table of Selector".into_lua_err())?, + }) + } +} + +impl UserData for Selector {} diff --git a/yazi-binding/src/style.rs b/yazi-binding/src/style.rs index 07e325b3..83c0899a 100644 --- a/yazi-binding/src/style.rs +++ b/yazi-binding/src/style.rs @@ -2,6 +2,7 @@ use std::ops::Deref; use mlua::{ExternalError, FromLua, IntoLua, Lua, LuaSerdeExt, MetaMethod, Table, UserData, UserDataMethods, Value}; use ratatui::style::Modifier; +use yazi_shared::SyncCell; use crate::{SER_OPT, elements::Color}; @@ -22,6 +23,10 @@ impl From