mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 14:51:03 +00:00
feat: keymap Lua bindings (#4021)
This commit is contained in:
parent
8e80798984
commit
9bdd6777e4
77 changed files with 1068 additions and 378 deletions
4
.github/pull_request_template.md
vendored
4
.github/pull_request_template.md
vendored
|
|
@ -15,3 +15,7 @@ A clear and concise description of the rationale of the changes, to help our rev
|
|||
|
||||
If it has already been detailed in the associated issue, please skip this section.
|
||||
-->
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] I have read [CONTRIBUTING.md](https://github.com/sxyazi/yazi/blob/main/CONTRIBUTING.md)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
- Drag and drop ([#4005])
|
||||
- Bulk create ([#3793])
|
||||
- Image preview with Überzug++ on Niri ([#3990])
|
||||
- New gait for input `backward` and `forward` actions ([#4012])
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
|||
283
Cargo.lock
generated
283
Cargo.lock
generated
|
|
@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "6b657e772794c6b04730ea897b66a058ccd866c16d1967da05eeeecec39043fe"
|
||||
dependencies = [
|
||||
"crypto-common 0.2.2",
|
||||
"inout 0.2.2",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -165,6 +165,15 @@ version = "1.0.102"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||
|
||||
[[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"
|
||||
|
|
@ -378,9 +387,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.1"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
|
||||
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
|
@ -434,15 +443,6 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
|
||||
dependencies = [
|
||||
"generic-array 0.14.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.4.2"
|
||||
|
|
@ -594,9 +594,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.44"
|
||||
version = "0.4.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
|
||||
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
|
|
@ -614,7 +614,7 @@ checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c"
|
|||
dependencies = [
|
||||
"block-buffer 0.12.0",
|
||||
"crypto-common 0.2.2",
|
||||
"inout 0.2.2",
|
||||
"inout",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
|
|
@ -804,6 +804,12 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.15"
|
||||
|
|
@ -844,7 +850,7 @@ version = "0.28.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"crossterm_winapi",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
|
|
@ -861,7 +867,7 @@ version = "0.29.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"crossterm_winapi",
|
||||
"derive_more",
|
||||
"document-features",
|
||||
|
|
@ -969,12 +975,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "5.0.0-pre.6"
|
||||
version = "5.0.0-rc.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335f1947f241137a14106b6f5acc5918a5ede29c9d71d3f2cb1678d5075d9fc3"
|
||||
checksum = "4f359e08ca85e7bd759e1fd933ff2bccd81864c60a8fba0e259c7f822b0924bf"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures 0.2.17",
|
||||
"cpufeatures 0.3.0",
|
||||
"curve25519-dalek-derive",
|
||||
"digest 0.11.3",
|
||||
"fiat-crypto",
|
||||
|
|
@ -1274,9 +1280,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ed25519-dalek"
|
||||
version = "3.0.0-pre.7"
|
||||
version = "3.0.0-rc.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20449acd54b660981ae5caa2bcb56d1fe7f25f2e37a38ec507400fab034d4bb6"
|
||||
checksum = "b011170fe4f04665565b4110afef66774fe9ffff278f3eb5b81cc73d26e27d60"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"ed25519",
|
||||
|
|
@ -1296,22 +1302,22 @@ checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
|
|||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.14.0-rc.32"
|
||||
version = "0.14.0-rc.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cda94f31325c4275e9706adecbb6f0650dee2f904c915a98e3d81adaaaa757aa"
|
||||
checksum = "102d3643d30dd8b559613c5cced68317199597fffb278cdc88daa2ef7fafc935"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"crypto-bigint",
|
||||
"crypto-common 0.2.2",
|
||||
"digest 0.11.3",
|
||||
"ff",
|
||||
"group",
|
||||
"hkdf",
|
||||
"hybrid-array",
|
||||
"once_cell",
|
||||
"pem-rfc7468",
|
||||
"pkcs8",
|
||||
"rand_core 0.10.1",
|
||||
"rustcrypto-ff",
|
||||
"rustcrypto-group",
|
||||
"sec1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
|
|
@ -1469,6 +1475,16 @@ dependencies = [
|
|||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f"
|
||||
dependencies = [
|
||||
"rand_core 0.10.1",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.3.0"
|
||||
|
|
@ -1663,10 +1679,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1688,11 +1702,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"r-efi 6.0.0",
|
||||
"rand_core 0.10.1",
|
||||
"wasip2",
|
||||
"wasip3",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1733,6 +1749,17 @@ dependencies = [
|
|||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fd1a1c7a5206c5b7a3f5a0d7ccd3ff85d0c8f5133d62a02680255b0004af5f4"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"rand_core 0.10.1",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.7.1"
|
||||
|
|
@ -1946,11 +1973,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.11.1"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199"
|
||||
checksum = "533e68a5842e734946fe159fb03fc9bbbb254f590dd0d8ad321ae5ff7beca2c1"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
|
|
@ -1964,23 +1991,13 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||
dependencies = [
|
||||
"block-padding 0.3.3",
|
||||
"generic-array 0.14.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7"
|
||||
dependencies = [
|
||||
"block-padding 0.4.2",
|
||||
"block-padding",
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
|
|
@ -2020,6 +2037,15 @@ dependencies = [
|
|||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.2"
|
||||
|
|
@ -2110,7 +2136,7 @@ version = "1.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
|
@ -2146,9 +2172,9 @@ checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
|||
|
||||
[[package]]
|
||||
name = "libfuzzer-sys"
|
||||
version = "0.4.12"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d"
|
||||
checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"cc",
|
||||
|
|
@ -2175,7 +2201,7 @@ version = "0.3.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2207,9 +2233,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.30"
|
||||
version = "0.4.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5"
|
||||
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
|
||||
|
||||
[[package]]
|
||||
name = "loop9"
|
||||
|
|
@ -2220,15 +2246,6 @@ dependencies = [
|
|||
"imgref",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.16.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
|
||||
dependencies = [
|
||||
"hashbrown 0.16.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.18.0"
|
||||
|
|
@ -2287,9 +2304,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "md5"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
|
||||
checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
|
|
@ -2438,7 +2455,7 @@ version = "0.29.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
|
|
@ -2451,7 +2468,7 @@ version = "0.31.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
|
|
@ -2497,7 +2514,7 @@ version = "8.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
"kqueue",
|
||||
|
|
@ -2515,7 +2532,7 @@ version = "2.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2630,7 +2647,7 @@ version = "0.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
|
|
@ -2661,7 +2678,7 @@ version = "6.5.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc3cbf698f9438986c11a880c90a6d04b9de27575afd28bbf45b154b6c709e2"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"onig_sys",
|
||||
|
|
@ -2714,9 +2731,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "p256"
|
||||
version = "0.14.0-rc.9"
|
||||
version = "0.14.0-rc.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b97e3bf0465157ae90975ff52dbeb1362ba618924878c9f74c25baa27a65f9a"
|
||||
checksum = "41adc63effe99d48837a8cc0e6d7a77e32ae6a07f6000df466178dbc2193093e"
|
||||
dependencies = [
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
|
|
@ -2727,9 +2744,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "p384"
|
||||
version = "0.14.0-rc.9"
|
||||
version = "0.14.0-rc.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "437f30ebcb1e16ff48acead5f08bd69fbcdbc82421687bb48af5c315a0bfab03"
|
||||
checksum = "9bd5333afa5ae0347f39e6a0f2c9c155da431583fd71fe5555bd0521b4ccaf02"
|
||||
dependencies = [
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
|
|
@ -2741,9 +2758,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "p521"
|
||||
version = "0.14.0-rc.9"
|
||||
version = "0.14.0-rc.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e9fd792bab86ecf6249561752fb5a413511f999887107dd054bbda5143743d7"
|
||||
checksum = "a3a5297f53dc16d35909060ba3032cff7867e8809f01e273ff325579d5f0ceae"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"ecdsa",
|
||||
|
|
@ -2779,6 +2796,7 @@ version = "0.7.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"bytemuck",
|
||||
"fast-srgb8",
|
||||
"libm",
|
||||
|
|
@ -3046,7 +3064,7 @@ version = "0.18.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"crc32fast",
|
||||
"fdeflate",
|
||||
"flate2",
|
||||
|
|
@ -3108,23 +3126,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "primefield"
|
||||
version = "0.14.0-rc.9"
|
||||
version = "0.14.0-rc.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b52e6ee42db392378a95622b463c9740631171d1efce43fa445a569c1600cb6"
|
||||
checksum = "f845ec3240cd5ed5e1e31cf3ff633a5bf47c698dc4092ba9e767415b3d393406"
|
||||
dependencies = [
|
||||
"crypto-bigint",
|
||||
"crypto-common 0.2.2",
|
||||
"ff",
|
||||
"rand_core 0.10.1",
|
||||
"rustcrypto-ff",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "primeorder"
|
||||
version = "0.14.0-rc.9"
|
||||
version = "0.14.0-rc.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0556580e42c19833f5d232aca11a7687a503ee41f937b54f5ae1d50fc2a6a36a"
|
||||
checksum = "7d2793f22b9b6fd11ef3ac1d59bf003c2573593e4968702341605c2748fd90bf"
|
||||
dependencies = [
|
||||
"elliptic-curve",
|
||||
]
|
||||
|
|
@ -3334,19 +3352,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ratatui-core"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293"
|
||||
checksum = "42d3603f354bba8c595fa47860e60142d7372b7210c27044c6a7d0e1a4336b44"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"compact_str",
|
||||
"hashbrown 0.16.1",
|
||||
"critical-section",
|
||||
"hashbrown 0.17.1",
|
||||
"indoc",
|
||||
"itertools",
|
||||
"kasuari",
|
||||
"lru 0.16.4",
|
||||
"lru",
|
||||
"palette",
|
||||
"serde",
|
||||
"strum 0.27.2",
|
||||
"strum 0.28.0",
|
||||
"thiserror 2.0.18",
|
||||
"unicode-segmentation",
|
||||
"unicode-truncate",
|
||||
|
|
@ -3355,9 +3375,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ratatui-crossterm"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3"
|
||||
checksum = "2b2867bedcbd6a690ca4f8672a687b730ec07660c79844517b084311b529980c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossterm 0.28.1",
|
||||
|
|
@ -3368,9 +3388,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ratatui-termion"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cade85a8591fbc911e147951422f0d6fd40f4948b271b6216c7dc01838996f8"
|
||||
checksum = "5c16cc35a9d9114e0b2bb4b22018b96ae7f5fe60e2595dc73e622b4e78624835"
|
||||
dependencies = [
|
||||
"instability",
|
||||
"ratatui-core",
|
||||
|
|
@ -3379,9 +3399,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ratatui-termwiz"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f76fe0bd0ed4295f0321b1676732e2454024c15a35d01904ddb315afd3d545c"
|
||||
checksum = "386b8ff8f74ed749509391c56d549761a2fcdb408e1f42e467286bcb7dac8967"
|
||||
dependencies = [
|
||||
"ratatui-core",
|
||||
"termwiz",
|
||||
|
|
@ -3393,7 +3413,7 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"hashbrown 0.16.1",
|
||||
"indoc",
|
||||
"instability",
|
||||
|
|
@ -3482,7 +3502,7 @@ version = "0.5.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3596,13 +3616,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "russh"
|
||||
version = "0.61.1"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f67013f080c226e5a34db1c71f2567f44d95a6300005bb6cd4e2c8fe3c326d1b"
|
||||
checksum = "bbf893f64684e58da8a68d56a5e84d1cf0440226274c515770fe267707a7d0b0"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bitflags 2.11.1",
|
||||
"block-padding 0.4.2",
|
||||
"bitflags 2.13.0",
|
||||
"block-padding",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"cbc",
|
||||
|
|
@ -3620,12 +3640,11 @@ dependencies = [
|
|||
"enum_dispatch",
|
||||
"futures",
|
||||
"generic-array 1.4.3",
|
||||
"getrandom 0.2.17",
|
||||
"getrandom 0.4.2",
|
||||
"ghash",
|
||||
"hex-literal",
|
||||
"hkdf",
|
||||
"hmac",
|
||||
"inout 0.1.4",
|
||||
"inout",
|
||||
"internal-russh-num-bigint",
|
||||
"keccak",
|
||||
"log",
|
||||
|
|
@ -3711,34 +3730,13 @@ dependencies = [
|
|||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustcrypto-ff"
|
||||
version = "0.14.0-rc.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd2a8adb347447693cd2ba0d218c4b66c62da9b0a5672b17b981e4291ec65ff6"
|
||||
dependencies = [
|
||||
"rand_core 0.10.1",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustcrypto-group"
|
||||
version = "0.14.0-rc.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "369f9b61aa45933c062c9f6b5c3c50ab710687eca83dd3802653b140b43f85ed"
|
||||
dependencies = [
|
||||
"rand_core 0.10.1",
|
||||
"rustcrypto-ff",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
|
|
@ -3751,7 +3749,7 @@ version = "1.1.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.12.1",
|
||||
|
|
@ -3924,9 +3922,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.20.0"
|
||||
version = "3.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2"
|
||||
checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bs58",
|
||||
|
|
@ -3944,9 +3942,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.20.0"
|
||||
version = "3.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac"
|
||||
checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660"
|
||||
dependencies = [
|
||||
"darling 0.23.0",
|
||||
"proc-macro2",
|
||||
|
|
@ -4378,7 +4376,7 @@ checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"fancy-regex",
|
||||
"filedescriptor",
|
||||
"finl_unicode",
|
||||
|
|
@ -4779,9 +4777,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.13.2"
|
||||
version = "1.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
|
||||
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-truncate"
|
||||
|
|
@ -5045,7 +5043,7 @@ version = "0.244.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"hashbrown 0.15.5",
|
||||
"indexmap 2.14.0",
|
||||
"semver",
|
||||
|
|
@ -5142,9 +5140,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wide"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a7714cd0430a663154667c74da5d09325c2387695bee18b3f7f72825aa3693a"
|
||||
checksum = "dfdfe6a32973f2d1b268b8895845a8a96cac2f0191e72c27cc929036060dbf89"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"safe_arch",
|
||||
|
|
@ -5579,7 +5577,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"indexmap 2.14.0",
|
||||
"log",
|
||||
"serde",
|
||||
|
|
@ -5790,10 +5788,11 @@ version = "26.5.6"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"globset",
|
||||
"hashbrown 0.17.1",
|
||||
"indexmap 2.14.0",
|
||||
"mlua",
|
||||
"ratatui",
|
||||
"regex",
|
||||
"serde",
|
||||
|
|
@ -5855,6 +5854,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"hashbrown 0.17.1",
|
||||
"indexmap 2.14.0",
|
||||
"inventory",
|
||||
"mlua",
|
||||
"ordered-float 5.3.0",
|
||||
"parking_lot",
|
||||
|
|
@ -5951,13 +5951,14 @@ version = "26.5.6"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"core-foundation-sys",
|
||||
"dirs",
|
||||
"either",
|
||||
"foldhash 0.2.0",
|
||||
"hashbrown 0.17.1",
|
||||
"libc",
|
||||
"mlua",
|
||||
"objc2",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
|
|
@ -5991,7 +5992,7 @@ name = "yazi-parser"
|
|||
version = "26.5.6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"hashbrown 0.17.1",
|
||||
"mlua",
|
||||
"paste",
|
||||
|
|
@ -6021,9 +6022,9 @@ dependencies = [
|
|||
"ansi-to-tui",
|
||||
"anyhow",
|
||||
"futures",
|
||||
"inventory",
|
||||
"libc",
|
||||
"mlua",
|
||||
"paste",
|
||||
"percent-encoding",
|
||||
"ratatui",
|
||||
"serde_json",
|
||||
|
|
@ -6036,6 +6037,7 @@ dependencies = [
|
|||
"yazi-adapter",
|
||||
"yazi-binding",
|
||||
"yazi-boot",
|
||||
"yazi-codegen",
|
||||
"yazi-config",
|
||||
"yazi-core",
|
||||
"yazi-dds",
|
||||
|
|
@ -6104,7 +6106,7 @@ dependencies = [
|
|||
"foldhash 0.2.0",
|
||||
"hashbrown 0.17.1",
|
||||
"libc",
|
||||
"lru 0.18.0",
|
||||
"lru",
|
||||
"mlua",
|
||||
"ordered-float 5.3.0",
|
||||
"parking_lot",
|
||||
|
|
@ -6127,7 +6129,7 @@ dependencies = [
|
|||
name = "yazi-sftp"
|
||||
version = "26.5.6"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"parking_lot",
|
||||
"russh",
|
||||
"serde",
|
||||
|
|
@ -6144,8 +6146,10 @@ dependencies = [
|
|||
"foldhash 0.2.0",
|
||||
"futures",
|
||||
"hashbrown 0.17.1",
|
||||
"inventory",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mlua",
|
||||
"ordered-float 5.3.0",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
|
|
@ -6188,11 +6192,12 @@ version = "26.5.6"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
"bitflags 2.11.1",
|
||||
"bitflags 2.13.0",
|
||||
"futures",
|
||||
"parking_lot",
|
||||
"ratatui",
|
||||
"rustix 1.1.4",
|
||||
"serde",
|
||||
"signal-hook 0.4.4",
|
||||
"strum 0.28.0",
|
||||
"thiserror 2.0.18",
|
||||
|
|
|
|||
11
Cargo.toml
11
Cargo.toml
|
|
@ -39,8 +39,8 @@ ansi-to-tui = "8.0.1"
|
|||
anyhow = "1.0.102"
|
||||
arc-swap = { version = "1.9.1", features = [ "serde" ] }
|
||||
base64 = "0.22.1"
|
||||
bitflags = { version = "2.11.1", features = [ "serde" ] }
|
||||
chrono = "0.4.44"
|
||||
bitflags = { version = "2.13.0", features = [ "serde" ] }
|
||||
chrono = "0.4.45"
|
||||
clap = { version = "4.6.1", features = [ "derive" ] }
|
||||
core-foundation-sys = "0.8.7"
|
||||
dirs = "6.0.0"
|
||||
|
|
@ -51,6 +51,7 @@ futures = "0.3.32"
|
|||
globset = "0.4.18"
|
||||
hashbrown = { version = "0.17.1", features = [ "serde" ] }
|
||||
indexmap = { version = "2.14.0", features = [ "serde" ] }
|
||||
inventory = "0.3.24"
|
||||
libc = "0.2.186"
|
||||
lru = "0.18.0"
|
||||
mlua = { version = "0.11.6", features = [ "anyhow", "async", "error-send", "lua55", "macros", "serde" ] }
|
||||
|
|
@ -60,13 +61,13 @@ parking_lot = "0.12.5"
|
|||
paste = "1.0.15"
|
||||
percent-encoding = "2.3.2"
|
||||
rand = { version = "0.10.1", default-features = false, features = [ "std", "sys_rng" ] }
|
||||
ratatui = { version = "0.30.0", default-features = false, features = [ "layout-cache", "serde", "underline-color", "unstable-rendered-line-info", "unstable-widget-ref" ] }
|
||||
ratatui = { version = "=0.30.0", default-features = false, features = [ "layout-cache", "serde", "underline-color", "unstable-rendered-line-info", "unstable-widget-ref" ] }
|
||||
regex = "1.12.3"
|
||||
russh = { version = "0.61.1", default-features = false, features = [ "ring", "rsa" ] }
|
||||
russh = { version = "0.61.2", default-features = false, features = [ "ring", "rsa" ] }
|
||||
scopeguard = "1.2.0"
|
||||
serde = { version = "1.0.228", features = [ "derive" ] }
|
||||
serde_json = "1.0.150"
|
||||
serde_with = "3.20.0"
|
||||
serde_with = "3.21.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"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ impl UserData for Which {
|
|||
cached_field!(fields, tx, |_, me| Ok(me.tx.clone().map(yazi_binding::MpscUnboundedTx)));
|
||||
fields.add_field_method_get("times", |_, me| Ok(me.inner.times));
|
||||
cached_field!(fields, cands, |lua, me| {
|
||||
lua.create_sequence_from(me.inner.cands.iter().cloned().map(yazi_binding::ChordCow))
|
||||
lua.create_sequence_from(me.inner.cands.iter().cloned().map(yazi_binding::keymap::ChordCow))
|
||||
});
|
||||
|
||||
fields.add_field_method_get("active", |_, me| Ok(me.inner.active));
|
||||
|
|
|
|||
16
yazi-binding/src/data/any.rs
Normal file
16
yazi-binding/src/data/any.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
use mlua::UserData;
|
||||
use yazi_codegen::FromLuaOwned;
|
||||
|
||||
#[derive(FromLuaOwned)]
|
||||
pub struct DataAny(Box<dyn yazi_shared::data::DataAny>);
|
||||
|
||||
impl DataAny {
|
||||
pub fn new<T>(value: T) -> Self
|
||||
where
|
||||
T: yazi_shared::data::DataAny,
|
||||
{
|
||||
Self(Box::new(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for DataAny {}
|
||||
1
yazi-binding/src/data/mod.rs
Normal file
1
yazi-binding/src/data/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
yazi_macro::mod_flat!(any);
|
||||
19
yazi-binding/src/event/action.rs
Normal file
19
yazi-binding/src/event/action.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::UserData;
|
||||
|
||||
pub struct Action {
|
||||
inner: yazi_shared::event::Action,
|
||||
}
|
||||
|
||||
impl Deref for Action {
|
||||
type Target = yazi_shared::event::Action;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Action {
|
||||
pub fn new(inner: impl Into<yazi_shared::event::Action>) -> Self { Self { inner: inner.into() } }
|
||||
}
|
||||
|
||||
impl UserData for Action {}
|
||||
19
yazi-binding/src/event/cmd.rs
Normal file
19
yazi-binding/src/event/cmd.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::UserData;
|
||||
|
||||
pub struct Cmd {
|
||||
inner: yazi_shared::event::Cmd,
|
||||
}
|
||||
|
||||
impl Deref for Cmd {
|
||||
type Target = yazi_shared::event::Cmd;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
pub fn new(inner: impl Into<yazi_shared::event::Cmd>) -> Self { Self { inner: inner.into() } }
|
||||
}
|
||||
|
||||
impl UserData for Cmd {}
|
||||
1
yazi-binding/src/event/mod.rs
Normal file
1
yazi-binding/src/event/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
yazi_macro::mod_flat!(action cmd);
|
||||
80
yazi-binding/src/keymap/chord.rs
Normal file
80
yazi-binding/src/keymap/chord.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, LuaSerdeExt, Table, UserData, UserDataFields, Value};
|
||||
|
||||
use crate::{Id, Iter, cached_field, event::Action, keymap::Key};
|
||||
|
||||
pub struct Chord {
|
||||
inner: Arc<yazi_config::keymap::Chord>,
|
||||
|
||||
v_on: Option<Value>,
|
||||
v_run: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Chord {
|
||||
type Target = Arc<yazi_config::keymap::Chord>;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl From<Chord> for Arc<yazi_config::keymap::Chord> {
|
||||
fn from(value: Chord) -> Self { value.inner }
|
||||
}
|
||||
|
||||
impl Chord {
|
||||
pub fn new(inner: impl Into<Arc<yazi_config::keymap::Chord>>) -> Self {
|
||||
Self { inner: inner.into(), v_on: None, v_run: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for Chord {
|
||||
fn from_lua(value: Value, lua: &Lua) -> mlua::Result<Self> {
|
||||
Ok(Self::new(lua.from_value::<yazi_config::keymap::Chord>(value)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Chord {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("id", |_, me| Ok(Id(me.inner.id)));
|
||||
|
||||
cached_field!(fields, on, |lua, me| lua.create_sequence_from(me.on.iter().copied().map(Key)));
|
||||
|
||||
cached_field!(fields, run, |lua, me| lua
|
||||
.create_sequence_from(me.run.iter().cloned().map(Action::new)));
|
||||
}
|
||||
}
|
||||
|
||||
// --- Matcher
|
||||
pub struct ChordMatcher(pub(super) yazi_config::keymap::ChordMatcher);
|
||||
|
||||
impl TryFrom<Table> for ChordMatcher {
|
||||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(value: Table) -> Result<Self, Self::Error> {
|
||||
let id: Id = value.raw_get("id").unwrap_or_default();
|
||||
|
||||
Ok(Self(yazi_config::keymap::ChordMatcher { id: id.0, ..Default::default() }))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for ChordMatcher {
|
||||
fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
|
||||
match value {
|
||||
Value::Table(t) => t.try_into(),
|
||||
_ => Err("expected a table of ChordMatcher".into_lua_err()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- ChordIter
|
||||
pub struct ChordIter(pub(super) yazi_config::keymap::ChordIter);
|
||||
|
||||
impl ChordIter {
|
||||
pub fn new(inner: impl Into<yazi_config::keymap::ChordIter>) -> Self { Self(inner.into()) }
|
||||
}
|
||||
|
||||
impl IntoLua for ChordIter {
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
Iter::new(self.0.map(Chord::new), None).into_lua(lua)
|
||||
}
|
||||
}
|
||||
53
yazi-binding/src/keymap/chords.rs
Normal file
53
yazi-binding/src/keymap/chords.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{ExternalError, ExternalResult, MetaMethod, UserData, UserDataMethods};
|
||||
|
||||
use super::{Chord, ChordMatcher};
|
||||
use crate::keymap::ChordIter;
|
||||
|
||||
pub struct Chords {
|
||||
inner: &'static yazi_config::keymap::Chords,
|
||||
}
|
||||
|
||||
impl Deref for Chords {
|
||||
type Target = yazi_config::keymap::Chords;
|
||||
|
||||
fn deref(&self) -> &Self::Target { self.inner }
|
||||
}
|
||||
|
||||
impl Chords {
|
||||
pub fn new(inner: &'static yazi_config::keymap::Chords) -> Self { Self { inner } }
|
||||
}
|
||||
|
||||
impl UserData for Chords {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_method("match", |_, me, matcher: Option<ChordMatcher>| {
|
||||
Ok(match matcher {
|
||||
Some(matcher) => ChordIter::new(yazi_config::keymap::ChordIter {
|
||||
chords: me.as_erased(),
|
||||
matcher: matcher.0,
|
||||
..Default::default()
|
||||
}),
|
||||
None => ChordIter::new(&*me.inner),
|
||||
})
|
||||
});
|
||||
|
||||
methods.add_method("insert", |_, me, (index, chord): (isize, Chord)| {
|
||||
let index = match index {
|
||||
1.. => index - 1,
|
||||
0 => return Err("index must be 1-based or negative".into_lua_err()),
|
||||
_ => index,
|
||||
};
|
||||
|
||||
me.insert(index, chord.clone()).into_lua_err()?;
|
||||
Ok(chord)
|
||||
});
|
||||
|
||||
methods.add_method("remove", |_, me, matcher: ChordMatcher| {
|
||||
me.remove(matcher.0);
|
||||
Ok(())
|
||||
});
|
||||
|
||||
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.load().len()));
|
||||
}
|
||||
}
|
||||
18
yazi-binding/src/keymap/key.rs
Normal file
18
yazi-binding/src/keymap/key.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{FromLua, IntoLua, Lua, LuaSerdeExt, Value};
|
||||
|
||||
use crate::SER_OPT;
|
||||
|
||||
#[derive(Clone, Copy, Default, FromLua)]
|
||||
pub struct Key(pub yazi_config::keymap::Key);
|
||||
|
||||
impl Deref for Key {
|
||||
type Target = yazi_config::keymap::Key;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.0 }
|
||||
}
|
||||
|
||||
impl IntoLua for Key {
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> { lua.to_value_with(&self.0, SER_OPT) }
|
||||
}
|
||||
1
yazi-binding/src/keymap/mod.rs
Normal file
1
yazi-binding/src/keymap/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
yazi_macro::mod_flat!(chord chord_cow chords key section);
|
||||
48
yazi-binding/src/keymap/section.rs
Normal file
48
yazi-binding/src/keymap/section.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use anyhow::bail;
|
||||
use mlua::{UserData, UserDataFields, Value};
|
||||
use yazi_config::KEYMAP;
|
||||
use yazi_shared::Layer;
|
||||
|
||||
use crate::{cached_field, keymap::Chords};
|
||||
|
||||
pub struct KeymapSection {
|
||||
inner: &'static yazi_config::keymap::KeymapSection,
|
||||
|
||||
v_rules: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for KeymapSection {
|
||||
type Target = yazi_config::keymap::KeymapSection;
|
||||
|
||||
fn deref(&self) -> &Self::Target { self.inner }
|
||||
}
|
||||
|
||||
impl TryFrom<Layer> for KeymapSection {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: Layer) -> Result<Self, Self::Error> {
|
||||
let inner = match value {
|
||||
Layer::Null | Layer::App => bail!("invalid layer"),
|
||||
Layer::Mgr => KEYMAP.mgr.as_erased(),
|
||||
Layer::Tasks => KEYMAP.tasks.as_erased(),
|
||||
Layer::Spot => KEYMAP.spot.as_erased(),
|
||||
Layer::Pick => KEYMAP.pick.as_erased(),
|
||||
Layer::Input => KEYMAP.input.as_erased(),
|
||||
Layer::Confirm => KEYMAP.confirm.as_erased(),
|
||||
Layer::Help => KEYMAP.help.as_erased(),
|
||||
Layer::Cmp => KEYMAP.cmp.as_erased(),
|
||||
Layer::Which => bail!("invalid layer"),
|
||||
Layer::Notify => bail!("invalid layer"),
|
||||
};
|
||||
|
||||
Ok(Self { inner, v_rules: None })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for KeymapSection {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
cached_field!(fields, rules, |_, me| Ok(Chords::new(me.inner)));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
mod macros;
|
||||
|
||||
yazi_macro::mod_pub!(config elements process theme);
|
||||
yazi_macro::mod_pub!(config data elements event keymap process theme);
|
||||
|
||||
yazi_macro::mod_flat!(access calculator cha chan chord_cow composer dnd error fd file handle icon id image input iter layer mouse path permit range runtime scheme selector stage style tty url utils);
|
||||
yazi_macro::mod_flat!(access calculator cha chan composer dnd error fd file handle icon id image input iter layer mouse path permit range runtime scheme selector stage style tty url utils);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ bitflags = { workspace = true }
|
|||
globset = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
ratatui = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
use std::{borrow::Cow, hash::{Hash, Hasher}, sync::OnceLock};
|
||||
use std::{borrow::Cow, hash::{Hash, Hasher}, sync::{Arc, OnceLock}};
|
||||
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Deserializer, de};
|
||||
use serde_with::{DeserializeAs, DisplayFromStr, OneOrMany};
|
||||
use yazi_shared::{Layer, Source, event::Action};
|
||||
use yazi_shared::{Id, Layer, Source, event::Action};
|
||||
|
||||
use super::Key;
|
||||
use crate::{Mixable, Platform};
|
||||
use super::{Key, ids::chord_id};
|
||||
use crate::{Mixable, Platform, keymap::Chords};
|
||||
|
||||
static RE: OnceLock<Regex> = OnceLock::new();
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
pub struct Chord<const L: u8 = { Layer::App as u8 }> {
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct Chord<const L: u8 = { Layer::Null as u8 }> {
|
||||
#[serde(skip, default = "chord_id")]
|
||||
pub id: Id,
|
||||
#[serde(deserialize_with = "deserialize_on")]
|
||||
pub on: Vec<Key>,
|
||||
#[serde(deserialize_with = "deserialize_run::<L, _>")]
|
||||
|
|
@ -22,6 +24,18 @@ pub struct Chord<const L: u8 = { Layer::App as u8 }> {
|
|||
pub r#for: Platform,
|
||||
}
|
||||
|
||||
impl<const L: u8> Clone for Chord<L> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
id: chord_id(),
|
||||
on: self.on.clone(),
|
||||
run: self.run.clone(),
|
||||
desc: self.desc.clone(),
|
||||
r#for: self.r#for,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const L: u8> PartialEq for Chord<L> {
|
||||
fn eq(&self, other: &Self) -> bool { self.on == other.on }
|
||||
}
|
||||
|
|
@ -33,6 +47,10 @@ impl<const L: u8> Hash for Chord<L> {
|
|||
}
|
||||
|
||||
impl<const L: u8> Chord<L> {
|
||||
pub fn as_erased<const M: u8>(self: &Arc<Self>) -> &Arc<Chord<M>> {
|
||||
unsafe { &*(self as *const Arc<Chord<L>> as *const Arc<Chord<M>>) }
|
||||
}
|
||||
|
||||
pub fn on(&self) -> String { self.on.iter().map(ToString::to_string).collect() }
|
||||
|
||||
pub fn run(&self) -> String {
|
||||
|
|
@ -81,12 +99,12 @@ fn deserialize_run<'de, const L: u8, D>(deserializer: D) -> Result<Vec<Action>,
|
|||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let mut actions: Vec<Action> = OneOrMany::<DisplayFromStr>::deserialize_as(deserializer)?;
|
||||
|
||||
let Some(layer) = Layer::from_repr(L) else {
|
||||
return Err(de::Error::custom(format!("invalid keymap layer const: {L}")));
|
||||
};
|
||||
|
||||
let mut actions: Vec<Action> = OneOrMany::<DisplayFromStr>::deserialize_as(deserializer)?;
|
||||
|
||||
for action in &mut actions {
|
||||
action.source = Source::Key;
|
||||
if action.layer == Layer::Null {
|
||||
|
|
@ -96,3 +114,54 @@ where
|
|||
|
||||
Ok(actions)
|
||||
}
|
||||
|
||||
// --- Matcher
|
||||
#[derive(Default)]
|
||||
pub struct ChordMatcher {
|
||||
pub id: Id,
|
||||
pub all: bool,
|
||||
}
|
||||
|
||||
impl ChordMatcher {
|
||||
pub fn matches(&self, chord: &Chord) -> bool {
|
||||
if self.all {
|
||||
true
|
||||
} else if self.id != Id::ZERO {
|
||||
chord.id == self.id
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Iter
|
||||
#[derive(Default)]
|
||||
pub struct ChordIter {
|
||||
pub chords: Arc<Vec<Arc<Chord>>>,
|
||||
pub matcher: ChordMatcher,
|
||||
pub offset: usize,
|
||||
}
|
||||
|
||||
impl From<&Chords> for ChordIter {
|
||||
fn from(chords: &Chords) -> Self {
|
||||
Self {
|
||||
chords: chords.load_full(),
|
||||
matcher: ChordMatcher { all: true, ..Default::default() },
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ChordIter {
|
||||
type Item = Arc<Chord>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(chord) = self.chords.get(self.offset) {
|
||||
self.offset += 1;
|
||||
if self.matcher.matches(chord) {
|
||||
return Some(chord.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
|||
57
yazi-config/src/keymap/chords.rs
Normal file
57
yazi-config/src/keymap/chords.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use arc_swap::ArcSwap;
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::Layer;
|
||||
use yazi_shim::{arc_swap::{ArcSwapExt, IntoPointee}, vec::{IndexAtError, VecExt}};
|
||||
|
||||
use super::Chord;
|
||||
use crate::keymap::ChordMatcher;
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct Chords<const L: u8 = { Layer::Null as u8 }>(ArcSwap<Vec<Arc<Chord<L>>>>);
|
||||
|
||||
impl<const L: u8> Deref for Chords<L> {
|
||||
type Target = ArcSwap<Vec<Arc<Chord<L>>>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.0 }
|
||||
}
|
||||
|
||||
impl<const L: u8> From<Vec<Arc<Chord<L>>>> for Chords<L> {
|
||||
fn from(inner: Vec<Arc<Chord<L>>>) -> Self { Self(inner.into_pointee()) }
|
||||
}
|
||||
|
||||
impl<const L: u8> Chords<L> {
|
||||
pub fn as_erased<const M: u8>(&self) -> Arc<Vec<Arc<Chord<M>>>> {
|
||||
let chords = self.0.load_full();
|
||||
unsafe { Arc::from_raw(Arc::into_raw(chords) as *const Vec<Arc<Chord<M>>>) }
|
||||
}
|
||||
|
||||
pub fn insert(&self, index: isize, rule: Arc<Chord>) -> Result<(), IndexAtError> {
|
||||
self.0.try_rcu(|rules| {
|
||||
let (before, after) = rules.split_at(rules.index_at(index)?);
|
||||
Ok(
|
||||
before
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain([rule.as_erased().clone()])
|
||||
.chain(after.iter().cloned())
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove(&self, matcher: ChordMatcher) {
|
||||
self.0.rcu(|chords| {
|
||||
let mut next = Vec::clone(chords);
|
||||
next.retain(|chord| !matcher.matches(chord.as_erased()));
|
||||
next
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn unwrap_unchecked(self) -> Vec<Arc<Chord<L>>> {
|
||||
Arc::try_unwrap(self.0.into_inner()).expect("unique chords arc")
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,25 @@
|
|||
use std::ops::Deref;
|
||||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use yazi_shared::{Layer, event::ActionCow};
|
||||
|
||||
use super::Chord;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ChordCow<const L: u8 = { Layer::App as u8 }> {
|
||||
pub enum ChordCow<const L: u8 = { Layer::Null as u8 }> {
|
||||
Owned(Chord<L>),
|
||||
Borrowed(&'static Chord<L>),
|
||||
Borrowed(Arc<Chord<L>>),
|
||||
}
|
||||
|
||||
impl<const L: u8> From<Chord<L>> for ChordCow<L> {
|
||||
fn from(c: Chord<L>) -> Self { Self::Owned(c) }
|
||||
}
|
||||
|
||||
impl<const L: u8> From<&'static Chord<L>> for ChordCow<L> {
|
||||
fn from(c: &'static Chord<L>) -> Self { Self::Borrowed(c) }
|
||||
impl<const L: u8> From<Arc<Chord<L>>> for ChordCow<L> {
|
||||
fn from(c: Arc<Chord<L>>) -> Self { Self::Borrowed(c) }
|
||||
}
|
||||
|
||||
impl<const L: u8> From<&Arc<Chord<L>>> for ChordCow<L> {
|
||||
fn from(c: &Arc<Chord<L>>) -> Self { Self::Borrowed(c.clone()) }
|
||||
}
|
||||
|
||||
impl<const L: u8> Deref for ChordCow<L> {
|
||||
|
|
@ -37,7 +41,7 @@ impl<const L: u8> ChordCow<L> {
|
|||
pub fn into_seq(self) -> Vec<ActionCow> {
|
||||
match self {
|
||||
Self::Owned(c) => c.run.into_iter().rev().map(Into::into).collect(),
|
||||
Self::Borrowed(c) => c.run.iter().rev().map(Into::into).collect(),
|
||||
Self::Borrowed(c) => c.run.iter().rev().cloned().map(Into::into).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
yazi-config/src/keymap/ids.rs
Normal file
6
yazi-config/src/keymap/ids.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
use yazi_shared::{Id, Ids};
|
||||
|
||||
pub fn chord_id() -> Id {
|
||||
static IDS: Ids = Ids::new();
|
||||
IDS.next()
|
||||
}
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
use std::{fmt::{Display, Write}, str::FromStr};
|
||||
|
||||
use anyhow::bail;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_term::event::{KeyCode, KeyEvent, Modifiers};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct Key {
|
||||
#[serde(flatten)]
|
||||
pub code: KeyCode,
|
||||
pub shift: bool,
|
||||
pub ctrl: bool,
|
||||
pub alt: bool,
|
||||
#[serde(rename = "super")]
|
||||
pub super_: bool,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,37 +1,39 @@
|
|||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use serde::Deserialize;
|
||||
use yazi_codegen::{DeserializeOver, DeserializeOver1};
|
||||
use yazi_fs::{Xdg, ok_or_not_found};
|
||||
use yazi_shared::Layer;
|
||||
|
||||
use super::{Chord, KeymapRules};
|
||||
use super::{Chord, KeymapSection};
|
||||
|
||||
#[derive(Deserialize, DeserializeOver, DeserializeOver1)]
|
||||
pub struct Keymap {
|
||||
pub mgr: KeymapRules<{ Layer::Mgr as u8 }>,
|
||||
pub tasks: KeymapRules<{ Layer::Tasks as u8 }>,
|
||||
pub spot: KeymapRules<{ Layer::Spot as u8 }>,
|
||||
pub pick: KeymapRules<{ Layer::Pick as u8 }>,
|
||||
pub input: KeymapRules<{ Layer::Input as u8 }>,
|
||||
pub confirm: KeymapRules<{ Layer::Confirm as u8 }>,
|
||||
pub help: KeymapRules<{ Layer::Help as u8 }>,
|
||||
pub cmp: KeymapRules<{ Layer::Cmp as u8 }>,
|
||||
pub mgr: KeymapSection<{ Layer::Mgr as u8 }>,
|
||||
pub tasks: KeymapSection<{ Layer::Tasks as u8 }>,
|
||||
pub spot: KeymapSection<{ Layer::Spot as u8 }>,
|
||||
pub pick: KeymapSection<{ Layer::Pick as u8 }>,
|
||||
pub input: KeymapSection<{ Layer::Input as u8 }>,
|
||||
pub confirm: KeymapSection<{ Layer::Confirm as u8 }>,
|
||||
pub help: KeymapSection<{ Layer::Help as u8 }>,
|
||||
pub cmp: KeymapSection<{ Layer::Cmp as u8 }>,
|
||||
}
|
||||
|
||||
impl Keymap {
|
||||
pub fn get(&self, layer: Layer) -> &[Chord] {
|
||||
pub fn get(&self, layer: Layer) -> Arc<Vec<Arc<Chord>>> {
|
||||
match layer {
|
||||
Layer::Null | Layer::App => &[],
|
||||
Layer::Mgr => self.mgr.as_erased_slice(),
|
||||
Layer::Tasks => self.tasks.as_erased_slice(),
|
||||
Layer::Spot => self.spot.as_erased_slice(),
|
||||
Layer::Pick => self.pick.as_erased_slice(),
|
||||
Layer::Input => self.input.as_erased_slice(),
|
||||
Layer::Confirm => self.confirm.as_erased_slice(),
|
||||
Layer::Help => self.help.as_erased_slice(),
|
||||
Layer::Cmp => self.cmp.as_erased_slice(),
|
||||
Layer::Which => &[],
|
||||
Layer::Notify => &[],
|
||||
Layer::Null | Layer::App => Arc::new(Vec::new()),
|
||||
Layer::Mgr => self.mgr.deref().as_erased(),
|
||||
Layer::Tasks => self.tasks.deref().as_erased(),
|
||||
Layer::Spot => self.spot.deref().as_erased(),
|
||||
Layer::Pick => self.pick.deref().as_erased(),
|
||||
Layer::Input => self.input.deref().as_erased(),
|
||||
Layer::Confirm => self.confirm.deref().as_erased(),
|
||||
Layer::Help => self.help.deref().as_erased(),
|
||||
Layer::Cmp => self.cmp.deref().as_erased(),
|
||||
Layer::Which => Arc::new(Vec::new()),
|
||||
Layer::Notify => Arc::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(chord cow key keymap rules);
|
||||
yazi_macro::mod_flat!(chord chords cow ids key keymap section);
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use serde::Deserialize;
|
||||
use yazi_codegen::DeserializeOver2;
|
||||
use yazi_shim::toml::DeserializeOverHook;
|
||||
|
||||
use super::{Chord, Key};
|
||||
use crate::mix;
|
||||
|
||||
#[derive(Default, Deserialize, DeserializeOver2)]
|
||||
pub struct KeymapRules<const L: u8> {
|
||||
keymap: Vec<Chord<L>>,
|
||||
#[serde(default)]
|
||||
prepend_keymap: Vec<Chord<L>>,
|
||||
#[serde(default)]
|
||||
append_keymap: Vec<Chord<L>>,
|
||||
}
|
||||
|
||||
impl<const L: u8> Deref for KeymapRules<L> {
|
||||
type Target = [Chord];
|
||||
|
||||
fn deref(&self) -> &Self::Target { self.as_erased_slice() }
|
||||
}
|
||||
|
||||
impl<const L: u8> KeymapRules<L> {
|
||||
pub(super) fn as_erased_slice(&self) -> &[Chord] {
|
||||
// Safety: `Chord<L>` only changes deserialization behavior; the const parameter
|
||||
// does not participate in layout, so a shared slice can be reinterpreted as
|
||||
// the default `Chord` view.
|
||||
unsafe { &*(self.keymap.as_slice() as *const [Chord<L>] as *const [Chord]) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<const L: u8> DeserializeOverHook for KeymapRules<L> {
|
||||
fn deserialize_over_hook(self) -> Result<Self, toml::de::Error> {
|
||||
#[inline]
|
||||
fn on<const L: u8>(Chord { on, .. }: &Chord<L>) -> [Key; 2] {
|
||||
[on.first().copied().unwrap_or_default(), on.get(1).copied().unwrap_or_default()]
|
||||
}
|
||||
|
||||
let a_seen: HashSet<_> = self.prepend_keymap.iter().map(on).collect();
|
||||
let b_seen: HashSet<_> = self.keymap.iter().map(on).collect();
|
||||
|
||||
let keymap = mix(
|
||||
self.prepend_keymap,
|
||||
self.keymap.into_iter().filter(|v| !a_seen.contains(&on(v))),
|
||||
self.append_keymap.into_iter().filter(|v| !b_seen.contains(&on(v))),
|
||||
);
|
||||
|
||||
Ok(Self { keymap, ..Default::default() })
|
||||
}
|
||||
}
|
||||
52
yazi-config/src/keymap/section.rs
Normal file
52
yazi-config/src/keymap/section.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use serde::Deserialize;
|
||||
use yazi_codegen::DeserializeOver2;
|
||||
use yazi_shared::Layer;
|
||||
use yazi_shim::toml::DeserializeOverHook;
|
||||
|
||||
use super::{Chord, Chords, Key};
|
||||
use crate::mix;
|
||||
|
||||
#[derive(Default, Deserialize, DeserializeOver2)]
|
||||
pub struct KeymapSection<const L: u8 = { Layer::Null as u8 }> {
|
||||
keymap: Chords<L>,
|
||||
#[serde(default)]
|
||||
prepend_keymap: Vec<Chord<L>>,
|
||||
#[serde(default)]
|
||||
append_keymap: Vec<Chord<L>>,
|
||||
}
|
||||
|
||||
impl<const L: u8> Deref for KeymapSection<L> {
|
||||
type Target = Chords<L>;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.keymap }
|
||||
}
|
||||
|
||||
impl<const L: u8> KeymapSection<L> {
|
||||
pub fn as_erased<const M: u8>(&self) -> &KeymapSection<M> {
|
||||
unsafe { &*(self as *const Self as *const KeymapSection<M>) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<const L: u8> DeserializeOverHook for KeymapSection<L> {
|
||||
fn deserialize_over_hook(self) -> Result<Self, toml::de::Error> {
|
||||
#[inline]
|
||||
fn on<const L: u8>(Chord { on, .. }: &Chord<L>) -> [Key; 2] {
|
||||
[on.first().copied().unwrap_or_default(), on.get(1).copied().unwrap_or_default()]
|
||||
}
|
||||
|
||||
let keymap = self.keymap.unwrap_unchecked();
|
||||
let a_seen: HashSet<_> = self.prepend_keymap.iter().map(on).collect();
|
||||
let b_seen: HashSet<_> = keymap.iter().map(|c| on(c)).collect();
|
||||
|
||||
let keymap: Vec<Arc<Chord<L>>> = mix(
|
||||
self.prepend_keymap,
|
||||
keymap.into_iter().filter(|v| !a_seen.contains(&on(v))),
|
||||
self.append_keymap.into_iter().filter(|v| !b_seen.contains(&on(v))),
|
||||
);
|
||||
|
||||
Ok(Self { keymap: keymap.into(), ..Default::default() })
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme which vfs);
|
||||
yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme vfs which);
|
||||
|
||||
yazi_macro::mod_flat!(icon layout mixing pattern platform preset priority selectable selector style utils yazi);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
use ratatui::{text::{Line, Text}, widgets::{Paragraph, Wrap}};
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::{scheme::Encode as EncodeScheme, strand::ToStrand, url::{Url, UrlBuf}};
|
||||
|
||||
use super::{Offset, Position};
|
||||
use crate::{YAZI, popup::Origin};
|
||||
|
||||
// --- InputCfg
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct InputCfg {
|
||||
pub title: String,
|
||||
|
|
@ -15,20 +17,7 @@ pub struct InputCfg {
|
|||
pub completion: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct PickCfg {
|
||||
pub title: String,
|
||||
pub items: Vec<String>,
|
||||
pub position: Position,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ConfirmCfg {
|
||||
pub position: Position,
|
||||
pub title: Line<'static>,
|
||||
pub body: Paragraph<'static>,
|
||||
pub list: Paragraph<'static>,
|
||||
}
|
||||
impl_data_any!(InputCfg);
|
||||
|
||||
impl InputCfg {
|
||||
pub fn cd(cwd: Url) -> Self {
|
||||
|
|
@ -117,6 +106,45 @@ impl InputCfg {
|
|||
}
|
||||
}
|
||||
|
||||
// --- PickCfg
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct PickCfg {
|
||||
pub title: String,
|
||||
pub items: Vec<String>,
|
||||
pub position: Position,
|
||||
}
|
||||
|
||||
impl_data_any!(PickCfg);
|
||||
|
||||
impl PickCfg {
|
||||
fn max_height(len: usize) -> u16 {
|
||||
YAZI.pick.open_offset.height.min(YAZI.pick.border().saturating_add(len as u16))
|
||||
}
|
||||
|
||||
pub fn open(items: Vec<String>) -> Self {
|
||||
let max_height = Self::max_height(items.len());
|
||||
Self {
|
||||
title: YAZI.pick.open_title.clone(),
|
||||
items,
|
||||
position: Position::new(YAZI.pick.open_origin, Offset {
|
||||
height: max_height,
|
||||
..YAZI.pick.open_offset
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- ConfirmCfg
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ConfirmCfg {
|
||||
pub position: Position,
|
||||
pub title: Line<'static>,
|
||||
pub body: Paragraph<'static>,
|
||||
pub list: Paragraph<'static>,
|
||||
}
|
||||
|
||||
impl_data_any!(ConfirmCfg);
|
||||
|
||||
impl ConfirmCfg {
|
||||
fn new(
|
||||
title: String,
|
||||
|
|
@ -188,21 +216,3 @@ impl ConfirmCfg {
|
|||
Some(Text::from_iter(lines))
|
||||
}
|
||||
}
|
||||
|
||||
impl PickCfg {
|
||||
fn max_height(len: usize) -> u16 {
|
||||
YAZI.pick.open_offset.height.min(YAZI.pick.border().saturating_add(len as u16))
|
||||
}
|
||||
|
||||
pub fn open(items: Vec<String>) -> Self {
|
||||
let max_height = Self::max_height(items.len());
|
||||
Self {
|
||||
title: YAZI.pick.open_title.clone(),
|
||||
items,
|
||||
position: Position::new(YAZI.pick.open_origin, Offset {
|
||||
height: max_height,
|
||||
..YAZI.pick.open_offset
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ use hashbrown::HashMap;
|
|||
use mlua::{Lua, Table};
|
||||
use serde::Deserialize;
|
||||
use strum::EnumString;
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_scheduler::plugin::PluginInEntry;
|
||||
use yazi_shared::{SStr, data::{Data, DataKey}, event::{ActionCow, Cmd}};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct PluginOpt {
|
||||
pub id: SStr,
|
||||
|
|
@ -17,6 +17,8 @@ pub struct PluginOpt {
|
|||
pub callback: Option<Box<dyn PluginCallback>>,
|
||||
}
|
||||
|
||||
impl_data_any!(PluginOpt);
|
||||
|
||||
impl TryFrom<ActionCow> for PluginOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use mlua::{FromLua, IntoLua, Lua, LuaSerdeExt, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_binding::SER_OPT;
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::{event::ActionCow, strand::StrandBuf};
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
|
|
@ -13,6 +14,8 @@ pub struct QuitOpt {
|
|||
pub no_cwd_file: bool,
|
||||
}
|
||||
|
||||
impl_data_any!(QuitOpt);
|
||||
|
||||
impl TryFrom<ActionCow> for QuitOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::{Id, path::PathBufDyn, url::UrlBuf};
|
||||
|
||||
use crate::cmp::CmpItem;
|
||||
|
|
@ -9,3 +10,5 @@ pub struct CmpOpt {
|
|||
pub word: PathBufDyn,
|
||||
pub ticket: Id,
|
||||
}
|
||||
|
||||
impl_data_any!(CmpOpt);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
use yazi_config::{KEYMAP, YAZI, keymap::{Chord, Key}};
|
||||
|
|
@ -12,7 +14,7 @@ use crate::help::HELP_MARGIN;
|
|||
pub struct Help {
|
||||
pub visible: bool,
|
||||
pub layer: Layer,
|
||||
pub(super) bindings: Vec<&'static Chord>,
|
||||
pub(super) bindings: Vec<Arc<Chord>>,
|
||||
|
||||
// Filter
|
||||
pub keyword: String,
|
||||
|
|
@ -51,10 +53,10 @@ impl Help {
|
|||
|
||||
if kw.is_empty() {
|
||||
self.keyword = String::new();
|
||||
self.bindings = KEYMAP.get(self.layer).iter().collect();
|
||||
self.bindings = KEYMAP.get(self.layer).iter().cloned().collect();
|
||||
} else if self.keyword != kw {
|
||||
self.keyword = kw.to_owned();
|
||||
self.bindings = KEYMAP.get(self.layer).iter().filter(|&c| c.contains(kw)).collect();
|
||||
self.bindings = KEYMAP.get(self.layer).iter().filter(|&c| c.contains(kw)).cloned().collect();
|
||||
}
|
||||
|
||||
render!(self.scroll(0));
|
||||
|
|
@ -73,7 +75,7 @@ impl Help {
|
|||
}
|
||||
|
||||
// --- Bindings
|
||||
pub fn window(&self) -> &[&Chord] {
|
||||
pub fn window(&self) -> &[Arc<Chord>] {
|
||||
let end = (self.offset + self.limit()).min(self.bindings.len());
|
||||
&self.bindings[self.offset..end]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::url::UrlBuf;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -5,3 +6,5 @@ pub struct DisplaceOpt {
|
|||
pub to: Result<UrlBuf, yazi_fs::error::Error>,
|
||||
pub from: UrlBuf,
|
||||
}
|
||||
|
||||
impl_data_any!(DisplaceOpt);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use yazi_fs::FilterCase;
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::{SStr, event::ActionCow};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
|
|
@ -8,6 +9,8 @@ pub struct FilterOpt {
|
|||
pub done: bool,
|
||||
}
|
||||
|
||||
impl_data_any!(FilterOpt);
|
||||
|
||||
impl TryFrom<ActionCow> for FilterOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use anyhow::bail;
|
||||
use yazi_fs::FilterCase;
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::{SStr, event::ActionCow};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -9,6 +10,8 @@ pub struct FindDoOpt {
|
|||
pub case: FilterCase,
|
||||
}
|
||||
|
||||
impl_data_any!(FindDoOpt);
|
||||
|
||||
impl TryFrom<ActionCow> for FindDoOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use yazi_fs::File;
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::{event::ActionCow, url::UrlBuf};
|
||||
|
||||
// --- OpenOpt
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOpt {
|
||||
pub cwd: Option<UrlBuf>,
|
||||
|
|
@ -9,6 +11,8 @@ pub struct OpenOpt {
|
|||
pub hovered: bool,
|
||||
}
|
||||
|
||||
impl_data_any!(OpenOpt);
|
||||
|
||||
impl TryFrom<ActionCow> for OpenOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
|
|
@ -22,10 +26,12 @@ impl TryFrom<ActionCow> for OpenOpt {
|
|||
}
|
||||
}
|
||||
|
||||
// OpenDoOpt
|
||||
// --- OpenDoOpt
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct OpenDoOpt {
|
||||
pub cwd: UrlBuf,
|
||||
pub targets: Vec<File>,
|
||||
pub interactive: bool,
|
||||
}
|
||||
|
||||
impl_data_any!(OpenDoOpt);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use anyhow::bail;
|
||||
use serde::Deserialize;
|
||||
use strum::{EnumString, IntoStaticStr};
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::{SStr, event::ActionCow, url::{UrlBuf, UrlLike}};
|
||||
|
||||
// --- SearchOpt
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SearchOpt {
|
||||
pub via: SearchVia,
|
||||
|
|
@ -12,6 +14,8 @@ pub struct SearchOpt {
|
|||
pub r#in: Option<UrlBuf>,
|
||||
}
|
||||
|
||||
impl_data_any!(SearchOpt);
|
||||
|
||||
impl TryFrom<ActionCow> for SearchOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
|
|
@ -37,7 +41,7 @@ impl TryFrom<ActionCow> for SearchOpt {
|
|||
}
|
||||
}
|
||||
|
||||
// Via
|
||||
// --- Via
|
||||
#[derive(Clone, Copy, Debug, Deserialize, EnumString, Eq, IntoStaticStr, PartialEq)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[strum(serialize_all = "kebab-case")]
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use mlua::{FromLua, IntoLua, Lua, LuaSerdeExt, Value};
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::{DurationSecondsWithFrac, serde_as};
|
||||
use yazi_binding::SER_OPT;
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
use crate::notify::MessageLevel;
|
||||
|
|
@ -21,6 +22,8 @@ pub struct MessageOpt {
|
|||
pub timeout: Duration,
|
||||
}
|
||||
|
||||
impl_data_any!(MessageOpt);
|
||||
|
||||
impl TryFrom<ActionCow> for MessageOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use mlua::Table;
|
||||
use yazi_binding::{FileRef, elements::Renderable};
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::Id;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -13,6 +14,8 @@ pub struct SpotLock {
|
|||
pub data: Vec<Renderable>,
|
||||
}
|
||||
|
||||
impl_data_any!(SpotLock);
|
||||
|
||||
impl TryFrom<Table> for SpotLock {
|
||||
type Error = mlua::Error;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use mlua::Table;
|
||||
use yazi_binding::{FileRef, elements::{Rect, Renderable}};
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::pool::{InternStr, Symbol};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
|
|
@ -13,6 +14,8 @@ pub struct PreviewLock {
|
|||
pub data: Vec<Renderable>,
|
||||
}
|
||||
|
||||
impl_data_any!(PreviewLock);
|
||||
|
||||
impl TryFrom<Table> for PreviewLock {
|
||||
type Error = mlua::Error;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_scheduler::{TaskIn, file::FileInCut, plugin::PluginInEntry};
|
||||
use yazi_shared::{Id, SStr};
|
||||
|
||||
|
|
@ -10,6 +11,8 @@ pub enum TaskOpt {
|
|||
Plugin(PluginInEntry),
|
||||
}
|
||||
|
||||
impl_data_any!(TaskOpt);
|
||||
|
||||
impl TaskIn for TaskOpt {
|
||||
type Prog = ();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, Value};
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_config::{KEYMAP, keymap::{ChordCow, Key}};
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::{Layer, event::ActionCow};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WhichOpt {
|
||||
pub tx: Option<mpsc::UnboundedSender<Option<yazi_binding::ChordCow>>>,
|
||||
pub tx: Option<mpsc::UnboundedSender<Option<yazi_binding::keymap::ChordCow>>>,
|
||||
pub cands: Vec<ChordCow>,
|
||||
pub silent: bool,
|
||||
pub times: usize,
|
||||
}
|
||||
|
||||
impl_data_any!(WhichOpt);
|
||||
|
||||
impl TryFrom<ActionCow> for WhichOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
|
|
@ -21,7 +24,7 @@ impl TryFrom<ActionCow> for WhichOpt {
|
|||
|
||||
Ok(Self {
|
||||
tx: a.take_any2("tx").transpose()?,
|
||||
cands: a.take_any_iter::<yazi_binding::ChordCow>().map(Into::into).collect(),
|
||||
cands: a.take_any_iter::<yazi_binding::keymap::ChordCow>().map(Into::into).collect(),
|
||||
silent: a.bool("silent"),
|
||||
times: a.get("times").unwrap_or(0),
|
||||
})
|
||||
|
|
@ -35,7 +38,7 @@ impl From<(Layer, Key)> for WhichOpt {
|
|||
cands: KEYMAP
|
||||
.get(layer)
|
||||
.iter()
|
||||
.filter(|c| c.on.len() > 1 && c.on[0] == key)
|
||||
.filter(|&c| c.on.len() > 1 && c.on[0] == key)
|
||||
.map(Into::into)
|
||||
.collect(),
|
||||
times: 1,
|
||||
|
|
@ -54,7 +57,7 @@ impl FromLua for WhichOpt {
|
|||
tx: t.raw_get::<yazi_binding::MpscUnboundedTx<_>>("tx").ok().map(|t| t.0),
|
||||
cands: t
|
||||
.raw_get::<Table>("cands")?
|
||||
.sequence_values::<yazi_binding::ChordCow>()
|
||||
.sequence_values::<yazi_binding::keymap::ChordCow>()
|
||||
.map(|c| c.map(Into::into))
|
||||
.collect::<mlua::Result<Vec<_>>>()?,
|
||||
times: t.raw_get("times").unwrap_or_default(),
|
||||
|
|
@ -69,7 +72,7 @@ impl IntoLua for WhichOpt {
|
|||
lua
|
||||
.create_table_from([
|
||||
("tx", self.tx.map(yazi_binding::MpscUnboundedTx).into_lua(lua)?),
|
||||
("cands", lua.create_sequence_from(self.cands.into_iter().map(yazi_binding::ChordCow))?.into_lua(lua)?),
|
||||
("cands", lua.create_sequence_from(self.cands.into_iter().map(yazi_binding::keymap::ChordCow))?.into_lua(lua)?),
|
||||
("times", self.times.into_lua(lua)?),
|
||||
("silent", self.silent.into_lua(lua)?),
|
||||
])?
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use yazi_macro::{emit, render_and};
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct Which {
|
||||
pub tx: Option<mpsc::UnboundedSender<Option<yazi_binding::ChordCow>>>,
|
||||
pub tx: Option<mpsc::UnboundedSender<Option<yazi_binding::keymap::ChordCow>>>,
|
||||
pub times: usize,
|
||||
pub cands: Vec<ChordCow>,
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ yazi-version = { path = "../yazi-version", version = "26.5.6" }
|
|||
anyhow = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
inventory = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
ordered-float = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use indexmap::IndexSet;
|
||||
use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, MultiValue, ObjectLike, UserData, UserDataFields, UserDataMethods, Value};
|
||||
use mlua::{AnyUserData, FromLua, IntoLua, Lua, MetaMethod, MultiValue, ObjectLike, UserData, UserDataFields, UserDataMethods, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_binding::get_metatable;
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::url::UrlBufCov;
|
||||
|
||||
use super::Ember;
|
||||
|
|
@ -19,6 +20,8 @@ pub struct EmberYank<'a> {
|
|||
pub urls: Cow<'a, IndexSet<UrlBufCov>>,
|
||||
}
|
||||
|
||||
impl_data_any!(EmberYank<'static>, from_into_lua = inherit);
|
||||
|
||||
impl<'a> EmberYank<'a> {
|
||||
pub fn borrowed(cut: bool, urls: &'a IndexSet<UrlBufCov>) -> Ember<'a> {
|
||||
Self { cut, urls: Cow::Borrowed(urls) }.into()
|
||||
|
|
@ -35,6 +38,19 @@ impl<'a> From<EmberYank<'a>> for Ember<'a> {
|
|||
fn from(value: EmberYank<'a>) -> Self { Self::Yank(value) }
|
||||
}
|
||||
|
||||
impl FromLua for EmberYank<'static> {
|
||||
fn from_lua(value: Value, lua: &Lua) -> mlua::Result<Self> {
|
||||
match value {
|
||||
Value::UserData(ud) => ud.take::<EmberYankIter>()?.collect(lua),
|
||||
_ => Err(mlua::Error::FromLuaConversionError {
|
||||
from: value.type_name(),
|
||||
to: "EmberYank".to_owned(),
|
||||
message: Some("expected EmberYankIter userdata".to_owned()),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoLua for EmberYank<'_> {
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
let len = self.urls.len();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::{fmt::Display, io::Write, str::FromStr};
|
|||
use anyhow::{Result, anyhow};
|
||||
use mlua::{IntoLua, Lua, Value};
|
||||
use yazi_boot::BOOT;
|
||||
use yazi_macro::{emit, relay};
|
||||
use yazi_macro::{emit, impl_data_any, relay};
|
||||
use yazi_shared::{Id, event::ActionCow};
|
||||
|
||||
use crate::{ID, ember::Ember};
|
||||
|
|
@ -15,6 +15,8 @@ pub struct Payload<'a> {
|
|||
pub body: Ember<'a>,
|
||||
}
|
||||
|
||||
impl_data_any!(Payload<'static>);
|
||||
|
||||
impl<'a> Payload<'a> {
|
||||
pub fn new(body: Ember<'a>) -> Self { Self { receiver: Id::ZERO, sender: *ID, body } }
|
||||
|
||||
|
|
|
|||
|
|
@ -3,26 +3,23 @@ use std::{any::TypeId, borrow::Cow};
|
|||
use hashbrown::HashMap;
|
||||
use mlua::{ExternalError, IntoLua, Lua, MultiValue, Table, Value};
|
||||
use ordered_float::OrderedFloat;
|
||||
use yazi_shared::{data::{Data, DataKey}, replace_cow};
|
||||
|
||||
use crate::ember;
|
||||
use yazi_shared::{any_data::AnyData, data::{Data, DataInventory, DataKey}, replace_cow};
|
||||
|
||||
pub struct Sendable;
|
||||
|
||||
impl Sendable {
|
||||
pub fn value_to_data(lua: &Lua, value: Value) -> mlua::Result<Data> {
|
||||
Ok(match value {
|
||||
Value::Nil => Data::Nil,
|
||||
Value::Boolean(b) => Data::Boolean(b),
|
||||
Value::LightUserData(_) => Err("light userdata is not supported".into_lua_err())?,
|
||||
Value::Integer(i) => Data::Integer(i),
|
||||
Value::Number(n) => Data::Number(n),
|
||||
match &value {
|
||||
Value::Nil => return Ok(Data::Nil),
|
||||
Value::Boolean(b) => return Ok(Data::Boolean(*b)),
|
||||
Value::Integer(i) => return Ok(Data::Integer(*i)),
|
||||
Value::Number(n) => return Ok(Data::Number(*n)),
|
||||
Value::String(b) => {
|
||||
if let Ok(s) = b.to_str() {
|
||||
return Ok(if let Ok(s) = b.to_str() {
|
||||
Data::String(s.to_owned().into())
|
||||
} else {
|
||||
Data::Bytes(b.as_bytes().to_owned())
|
||||
}
|
||||
});
|
||||
}
|
||||
Value::Table(t) => {
|
||||
let (mut i, mut map) = (1, HashMap::with_capacity(t.raw_len()));
|
||||
|
|
@ -36,38 +33,40 @@ impl Sendable {
|
|||
map.insert(k, Self::value_to_data(lua, v)?);
|
||||
}
|
||||
|
||||
if map.len() == i as usize - 1 {
|
||||
return Ok(if map.len() == i as usize - 1 {
|
||||
Data::List((1..i).map(|i| map.remove(&DataKey::Integer(i)).unwrap()).collect())
|
||||
} else {
|
||||
Data::Dict(map)
|
||||
}
|
||||
});
|
||||
}
|
||||
Value::Function(_) => Err("function is not supported".into_lua_err())?,
|
||||
Value::Thread(_) => Err("thread is not supported".into_lua_err())?,
|
||||
Value::UserData(ud) => match ud.type_id() {
|
||||
Some(t) if t == TypeId::of::<yazi_binding::Url>() => {
|
||||
Data::Url(ud.take::<yazi_binding::Url>()?.into())
|
||||
return Ok(Data::Url(ud.take::<yazi_binding::Url>()?.into()));
|
||||
}
|
||||
Some(t) if t == TypeId::of::<yazi_binding::Path>() => {
|
||||
Data::Path(ud.take::<yazi_binding::Path>()?.into())
|
||||
return Ok(Data::Path(ud.take::<yazi_binding::Path>()?.into()));
|
||||
}
|
||||
Some(t) if t == TypeId::of::<yazi_binding::Id>() => {
|
||||
Data::Id(**ud.borrow::<yazi_binding::Id>()?)
|
||||
return Ok(Data::Id(**ud.borrow::<yazi_binding::Id>()?));
|
||||
}
|
||||
Some(t) if t == TypeId::of::<yazi_fs::FilesOp>() => {
|
||||
Data::Any(Box::new(ud.take::<yazi_fs::FilesOp>()?))
|
||||
}
|
||||
Some(t) if t == TypeId::of::<ember::EmberYankIter>() => {
|
||||
Data::Any(Box::new(ud.take::<ember::EmberYankIter>()?.collect(lua)?))
|
||||
}
|
||||
Some(t) if t == TypeId::of::<yazi_binding::ChordCow>() => {
|
||||
Data::Any(Box::new(ud.take::<yazi_binding::ChordCow>()?))
|
||||
}
|
||||
_ => Err(format!("unsupported userdata included: {ud:?}").into_lua_err())?,
|
||||
Some(t) if t == TypeId::of::<AnyData>() => return Ok(Data::Any(ud.take::<AnyData>()?.0)),
|
||||
_ => {}
|
||||
},
|
||||
Value::Error(_) => Err("error is not supported".into_lua_err())?,
|
||||
Value::Other(..) => Err("unknown data is not supported".into_lua_err())?,
|
||||
})
|
||||
Value::LightUserData(_) => {}
|
||||
Value::Function(_) => {}
|
||||
Value::Thread(_) => {}
|
||||
Value::Error(_) => {}
|
||||
Value::Other(_) => {}
|
||||
}
|
||||
|
||||
for inv in inventory::iter::<DataInventory> {
|
||||
match (inv.from_lua)(value.clone(), lua) {
|
||||
Ok(data) => return Ok(Data::Any(data)),
|
||||
Err(mlua::Error::UserDataTypeMismatch) => continue,
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Err(format!("unsupported value included: {value:?}").into_lua_err())?
|
||||
}
|
||||
|
||||
pub fn data_to_value(lua: &Lua, data: Data) -> mlua::Result<Value> {
|
||||
|
|
@ -91,23 +90,7 @@ impl Sendable {
|
|||
Data::Url(u) => yazi_binding::Url::new(u).into_lua(lua)?,
|
||||
Data::Path(u) => yazi_binding::Path::new(u).into_lua(lua)?,
|
||||
Data::Bytes(b) => Value::String(lua.create_external_string(b)?),
|
||||
Data::Any(b) => {
|
||||
let mut b = b.into_any();
|
||||
macro_rules! try_cast {
|
||||
($f:expr) => {
|
||||
match b.downcast() {
|
||||
Ok(v) => return $f(*v)?.into_lua(lua),
|
||||
#[allow(unused_assignments)]
|
||||
Err(e) => b = e,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
try_cast!(|v: yazi_fs::FilesOp| lua.create_any_userdata(v));
|
||||
try_cast!(|v: ember::EmberYank| v.into_lua(lua));
|
||||
try_cast!(|v: yazi_binding::ChordCow| v.into_lua(lua));
|
||||
Err("unsupported DataAny included".into_lua_err())?
|
||||
}
|
||||
Data::Any(a) => a.into_lua(lua)?,
|
||||
_ => Self::data_to_value_ref(lua, &data)?,
|
||||
})
|
||||
}
|
||||
|
|
@ -138,20 +121,7 @@ impl Sendable {
|
|||
Data::Url(u) => yazi_binding::Url::new(u).into_lua(lua)?,
|
||||
Data::Path(u) => yazi_binding::Path::new(u).into_lua(lua)?,
|
||||
Data::Bytes(b) => Value::String(lua.create_string(b)?),
|
||||
Data::Any(b) => {
|
||||
macro_rules! try_cast {
|
||||
($f:expr) => {
|
||||
if let Some(v) = b.as_any().downcast_ref() {
|
||||
return $f(Clone::clone(v))?.into_lua(lua);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
try_cast!(|v: yazi_fs::FilesOp| lua.create_any_userdata(v));
|
||||
try_cast!(|v: ember::EmberYank| v.into_lua(lua));
|
||||
try_cast!(|v: yazi_binding::ChordCow| v.into_lua(lua));
|
||||
Err("unsupported DataAny included".into_lua_err())?
|
||||
}
|
||||
Data::Any(a) => a.to_lua(lua)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl<'a> Help<'a> {
|
|||
pub fn new(core: &'a Core) -> Self { Self { core } }
|
||||
|
||||
fn tips() -> String {
|
||||
match KEYMAP.help.iter().find(|&c| c.run.iter().any(|c| c.name == "filter")) {
|
||||
match KEYMAP.help.load().iter().find(|&c| c.run.iter().any(|a| a.name == "filter")) {
|
||||
Some(c) => format!(" (Press `{}` to filter)", c.on()),
|
||||
None => String::new(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ impl<'a> Router<'a> {
|
|||
}
|
||||
|
||||
fn matches(&mut self, layer: Layer, key: Key) -> bool {
|
||||
for chord @ Chord { on, .. } in KEYMAP.get(layer) {
|
||||
for chord in &*KEYMAP.get(layer) {
|
||||
let Chord { on, .. } = &**chord;
|
||||
if on.is_empty() || on[0] != key {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ either = { workspace = true }
|
|||
foldhash = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
libc = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
percent-encoding = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::path::Path;
|
||||
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use yazi_macro::relay;
|
||||
use yazi_macro::{impl_data_any, relay};
|
||||
use yazi_shared::{Id, Ids, path::PathBufDyn, url::{UrlBuf, UrlLike, UrlMapExt}};
|
||||
|
||||
use super::File;
|
||||
|
|
@ -23,6 +23,8 @@ pub enum FilesOp {
|
|||
Upserting(UrlBuf, HashMap<PathBufDyn, File>),
|
||||
}
|
||||
|
||||
impl_data_any!(FilesOp);
|
||||
|
||||
impl FilesOp {
|
||||
#[inline]
|
||||
pub fn cwd(&self) -> &UrlBuf {
|
||||
|
|
|
|||
116
yazi-macro/src/data.rs
Normal file
116
yazi-macro/src/data.rs
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
#[macro_export]
|
||||
macro_rules! impl_data_any {
|
||||
($ty:ty) => {
|
||||
impl ::yazi_shared::data::DataAny for $ty {
|
||||
$crate::impl_data_any!(@core);
|
||||
$crate::impl_data_any!(@into_lua_default);
|
||||
}
|
||||
};
|
||||
($ty:ty => $($target:ty),+) => {
|
||||
impl ::yazi_shared::data::DataAny for $ty {
|
||||
$crate::impl_data_any!(@core $($target),+);
|
||||
$crate::impl_data_any!(@into_lua_default);
|
||||
}
|
||||
};
|
||||
// --- from_into_lua
|
||||
($ty:ty, from_into_lua = inherit) => {
|
||||
impl ::yazi_shared::data::DataAny for $ty {
|
||||
$crate::impl_data_any!(@core);
|
||||
$crate::impl_data_any!(@from_lua_inherit);
|
||||
$crate::impl_data_any!(@into_lua_inherit);
|
||||
}
|
||||
$crate::impl_data_any!(@from_lua_register $ty);
|
||||
};
|
||||
($ty:ty => $($target:ty),+ ; from_into_lua = inherit) => {
|
||||
impl ::yazi_shared::data::DataAny for $ty {
|
||||
$crate::impl_data_any!(@core $($target),+);
|
||||
$crate::impl_data_any!(@from_lua_inherit);
|
||||
$crate::impl_data_any!(@into_lua_inherit);
|
||||
}
|
||||
$crate::impl_data_any!(@from_lua_register $ty);
|
||||
};
|
||||
// --- to_lua
|
||||
($ty:ty, to_lua = $body:expr) => {
|
||||
impl ::yazi_shared::data::DataAny for $ty {
|
||||
$crate::impl_data_any!(@core);
|
||||
$crate::impl_data_any!(@from_lua_inherit);
|
||||
$crate::impl_data_any!(@into_lua_default);
|
||||
$crate::impl_data_any!(@to_lua $body);
|
||||
}
|
||||
$crate::impl_data_any!(@from_lua_register $ty);
|
||||
};
|
||||
($ty:ty => $($target:ty),+ ; to_lua = $body:expr) => {
|
||||
impl ::yazi_shared::data::DataAny for $ty {
|
||||
$crate::impl_data_any!(@core $($target),+);
|
||||
$crate::impl_data_any!(@from_lua_inherit);
|
||||
$crate::impl_data_any!(@into_lua_default);
|
||||
$crate::impl_data_any!(@to_lua $body);
|
||||
}
|
||||
$crate::impl_data_any!(@from_lua_register $ty);
|
||||
};
|
||||
|
||||
(@core $($target:ty),*) => {
|
||||
fn as_any(&self, id: std::any::TypeId) -> Option<&dyn std::any::Any> {
|
||||
use std::any::{TypeId, Any};
|
||||
|
||||
if id == TypeId::of::<Self>() {
|
||||
return Some(self as &dyn Any);
|
||||
}
|
||||
$(
|
||||
if id == TypeId::of::<$target>() {
|
||||
return Some(<Self as AsRef<$target>>::as_ref(self) as &dyn Any);
|
||||
}
|
||||
)*
|
||||
None
|
||||
}
|
||||
|
||||
fn into_any(self: Box<Self>, id: std::any::TypeId) -> Result<Box<dyn std::any::Any>, Box<dyn ::yazi_shared::data::DataAny>> {
|
||||
use std::any::TypeId;
|
||||
|
||||
if id == TypeId::of::<Self>() { return Ok(self); }
|
||||
$(
|
||||
if id == TypeId::of::<$target>() {
|
||||
return Ok(Box::new(<Self as Into<$target>>::into(*self)));
|
||||
}
|
||||
)*
|
||||
Err(self)
|
||||
}
|
||||
};
|
||||
(@into_lua_default) => {
|
||||
fn into_lua(self: Box<Self>, lua: &mlua::Lua) -> mlua::Result<mlua::Value> {
|
||||
use ::yazi_shared::any_data::AnyData;
|
||||
use mlua::IntoLua;
|
||||
|
||||
AnyData(self).into_lua(lua)
|
||||
}
|
||||
};
|
||||
(@into_lua_inherit) => {
|
||||
fn into_lua(self: Box<Self>, lua: &mlua::Lua) -> mlua::Result<mlua::Value> {
|
||||
use mlua::IntoLua;
|
||||
|
||||
IntoLua::into_lua(*self, lua)
|
||||
}
|
||||
};
|
||||
(@to_lua $body:expr) => {
|
||||
fn to_lua(&self, lua: &mlua::Lua) -> mlua::Result<mlua::Value> {
|
||||
use mlua::{self, Lua, Value};
|
||||
|
||||
($body as fn(&Self, &Lua) -> mlua::Result<Value>)(self, lua)
|
||||
}
|
||||
};
|
||||
(@from_lua_inherit) => {
|
||||
fn from_lua(value: mlua::Value, lua: &mlua::Lua) -> mlua::Result<Box<dyn ::yazi_shared::data::DataAny>> {
|
||||
use mlua::FromLua;
|
||||
|
||||
<Self as FromLua>::from_lua(value, lua)
|
||||
.map(|v| Box::new(v) as Box<dyn ::yazi_shared::data::DataAny>)
|
||||
}
|
||||
};
|
||||
(@from_lua_register $ty:ty) => {
|
||||
::inventory::submit! {
|
||||
::yazi_shared::data::DataInventory {
|
||||
from_lua: <$ty as ::yazi_shared::data::DataAny>::from_lua,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ mod actor;
|
|||
mod asset;
|
||||
mod confirm;
|
||||
mod context;
|
||||
mod data;
|
||||
mod event;
|
||||
mod fmt;
|
||||
mod fs;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ vendored-lua = [ "mlua/vendored" ]
|
|||
yazi-adapter = { path = "../yazi-adapter", version = "26.5.6" }
|
||||
yazi-binding = { path = "../yazi-binding", version = "26.5.6" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "26.5.6" }
|
||||
yazi-codegen = { path = "../yazi-codegen", version = "26.5.6" }
|
||||
yazi-config = { path = "../yazi-config", version = "26.5.6" }
|
||||
yazi-core = { path = "../yazi-core", version = "26.5.6" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "26.5.6" }
|
||||
|
|
@ -39,8 +40,8 @@ yazi-widgets = { path = "../yazi-widgets", version = "26.5.6" }
|
|||
ansi-to-tui = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
inventory = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
percent-encoding = { workspace = true }
|
||||
ratatui = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,8 +1,21 @@
|
|||
use mlua::{IntoLua, Lua, Table, Value};
|
||||
use mlua::{Lua, Table, UserData};
|
||||
use yazi_binding::{Cha, File, Id, Path, Url};
|
||||
use yazi_codegen::FromLuaOwned;
|
||||
use yazi_macro::impl_data_any;
|
||||
|
||||
#[derive(Clone, FromLuaOwned)]
|
||||
pub(super) struct FilesOp(yazi_fs::FilesOp);
|
||||
|
||||
impl_data_any!(FilesOp => yazi_fs::FilesOp; from_into_lua = inherit);
|
||||
|
||||
impl From<FilesOp> for yazi_fs::FilesOp {
|
||||
fn from(op: FilesOp) -> Self { op.0 }
|
||||
}
|
||||
|
||||
impl AsRef<yazi_fs::FilesOp> for FilesOp {
|
||||
fn as_ref(&self) -> &yazi_fs::FilesOp { &self.0 }
|
||||
}
|
||||
|
||||
impl FilesOp {
|
||||
pub(super) fn part(_: &Lua, t: Table) -> mlua::Result<Self> {
|
||||
let id: Id = t.raw_get("id")?;
|
||||
|
|
@ -41,8 +54,4 @@ impl FilesOp {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoLua for FilesOp {
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
lua.create_any_userdata(self.0)?.into_lua(lua)
|
||||
}
|
||||
}
|
||||
impl UserData for FilesOp {}
|
||||
|
|
|
|||
23
yazi-plugin/src/keymap/keymap.rs
Normal file
23
yazi-plugin/src/keymap/keymap.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
use mlua::{IntoLua, Lua, Value};
|
||||
use yazi_binding::{Composer, ComposerGet, ComposerSet, keymap::KeymapSection};
|
||||
use yazi_shared::Layer;
|
||||
|
||||
pub fn compose() -> Composer<ComposerGet, ComposerSet> {
|
||||
fn get(lua: &Lua, key: &[u8]) -> mlua::Result<Value> {
|
||||
match key {
|
||||
b"mgr" => KeymapSection::try_from(Layer::Mgr)?.into_lua(lua),
|
||||
b"tasks" => KeymapSection::try_from(Layer::Tasks)?.into_lua(lua),
|
||||
b"spot" => KeymapSection::try_from(Layer::Spot)?.into_lua(lua),
|
||||
b"pick" => KeymapSection::try_from(Layer::Pick)?.into_lua(lua),
|
||||
b"input" => KeymapSection::try_from(Layer::Input)?.into_lua(lua),
|
||||
b"confirm" => KeymapSection::try_from(Layer::Confirm)?.into_lua(lua),
|
||||
b"cmp" => KeymapSection::try_from(Layer::Cmp)?.into_lua(lua),
|
||||
b"help" => KeymapSection::try_from(Layer::Help)?.into_lua(lua),
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
}
|
||||
|
||||
fn set(_: &Lua, _: &[u8], value: Value) -> mlua::Result<Value> { Ok(value) }
|
||||
|
||||
Composer::new(get, set)
|
||||
}
|
||||
1
yazi-plugin/src/keymap/mod.rs
Normal file
1
yazi-plugin/src/keymap/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
yazi_macro::mod_flat!(keymap);
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
yazi_macro::mod_pub!(elements external fs pubsub runtime tasks theme utils);
|
||||
yazi_macro::mod_pub!(elements external fs keymap pubsub runtime tasks theme utils);
|
||||
|
||||
yazi_macro::mod_flat!(slim standard);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ pub fn slim_lua(lua: &Lua) -> mlua::Result<()> {
|
|||
globals.raw_set("ya", crate::utils::compose(true))?;
|
||||
globals.raw_set("fs", crate::fs::compose())?;
|
||||
globals.raw_set("rt", crate::runtime::compose())?;
|
||||
globals.raw_set("km", crate::keymap::compose())?;
|
||||
globals.raw_set("th", crate::theme::compose().into_lua(lua)?)?;
|
||||
|
||||
yazi_binding::Cha::install(lua)?;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ fn stage_1(lua: &Lua) -> Result<()> {
|
|||
globals.raw_set("fs", crate::fs::compose())?;
|
||||
globals.raw_set("ps", crate::pubsub::compose())?;
|
||||
globals.raw_set("rt", crate::runtime::compose())?;
|
||||
globals.raw_set("km", crate::keymap::compose())?;
|
||||
globals.raw_set("th", crate::theme::compose())?;
|
||||
|
||||
yazi_binding::Error::install(lua)?;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ impl Utils {
|
|||
.map(|(i, cand)| {
|
||||
let cand = cand?;
|
||||
Ok(ChordCow::Owned(Chord {
|
||||
id: yazi_config::keymap::chord_id(),
|
||||
on: Self::parse_keys(cand.raw_get("on")?)?,
|
||||
run: vec![relay!(which:callback, [i + 1])],
|
||||
desc: cand.raw_get("desc").unwrap_or_default(),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::ffi::OsString;
|
||||
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::url::{UrlBuf, UrlCow};
|
||||
|
||||
// TODO: remove in favor of ShellForm
|
||||
|
|
@ -13,3 +14,5 @@ pub struct ProcessOpt {
|
|||
|
||||
pub spread: bool, // TODO: remove
|
||||
}
|
||||
|
||||
impl_data_any!(ProcessOpt);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use ordered_float::OrderedFloat;
|
||||
use serde::Serialize;
|
||||
use yazi_macro::impl_data_any;
|
||||
|
||||
use crate::{Ongoing, Progress};
|
||||
|
||||
|
|
@ -11,6 +12,8 @@ pub struct TaskSummary {
|
|||
pub percent: Option<OrderedFloat<f32>>,
|
||||
}
|
||||
|
||||
impl_data_any!(TaskSummary);
|
||||
|
||||
impl From<&Ongoing> for TaskSummary {
|
||||
fn from(value: &Ongoing) -> Self {
|
||||
let mut summary = Self::default();
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ dyn-clone = { workspace = true }
|
|||
foldhash = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
inventory = { workspace = true }
|
||||
memchr = "2.8.1"
|
||||
mlua = { workspace = true }
|
||||
ordered-float = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
|
|
|
|||
8
yazi-shared/src/any_data.rs
Normal file
8
yazi-shared/src/any_data.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
use mlua::UserData;
|
||||
|
||||
use crate::data::DataAny;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AnyData(pub Box<dyn DataAny>);
|
||||
|
||||
impl UserData for AnyData {}
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
use std::sync::{Arc, atomic::{AtomicU8, Ordering}};
|
||||
|
||||
use tokio::sync::Notify;
|
||||
use yazi_macro::impl_data_any;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct CompletionToken {
|
||||
inner: Arc<(AtomicU8, Notify)>,
|
||||
}
|
||||
|
||||
impl_data_any!(CompletionToken);
|
||||
|
||||
impl CompletionToken {
|
||||
pub fn complete(&self, success: bool) {
|
||||
let new = if success { 1 } else { 2 };
|
||||
|
|
|
|||
|
|
@ -1,20 +1,39 @@
|
|||
use std::{any::Any, fmt::{self, Debug}};
|
||||
use std::{any::{self, Any, TypeId}, fmt::{self, Debug}};
|
||||
|
||||
use dyn_clone::DynClone;
|
||||
use mlua::{IntoLua, Lua, Value};
|
||||
|
||||
use crate::any_data::AnyData;
|
||||
|
||||
pub trait DataAny: Any + Send + Sync + DynClone {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn as_any(&self, id: TypeId) -> Option<&dyn Any>;
|
||||
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any>;
|
||||
fn into_any(self: Box<Self>, id: TypeId) -> Result<Box<dyn Any>, Box<dyn DataAny>>;
|
||||
|
||||
fn into_lua(self: Box<Self>, lua: &Lua) -> mlua::Result<Value>;
|
||||
|
||||
fn to_lua(&self, lua: &Lua) -> mlua::Result<Value> { dyn_clone::clone_box(self).into_lua(lua) }
|
||||
|
||||
fn from_lua(_value: Value, _lua: &Lua) -> mlua::Result<Box<dyn DataAny>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Err(mlua::Error::runtime(format!(
|
||||
"DataAny::from_lua is not implemented for `{}`",
|
||||
any::type_name::<Self>(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DataAny for T
|
||||
where
|
||||
T: Any + Send + Sync + DynClone,
|
||||
{
|
||||
fn as_any(&self) -> &dyn Any { self }
|
||||
impl dyn DataAny {
|
||||
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
|
||||
self.as_any(TypeId::of::<T>()).and_then(|a| a.downcast_ref::<T>())
|
||||
}
|
||||
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> { self }
|
||||
pub fn downcast<T: 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Any>> {
|
||||
let id = TypeId::of::<T>();
|
||||
self.into_any(id).map_or_else(|me| Err(me as Box<dyn Any>), |a| a.downcast::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Box<dyn DataAny> {
|
||||
|
|
@ -26,3 +45,27 @@ impl Debug for dyn DataAny {
|
|||
f.debug_struct("DataAny").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + Send + Sync + 'static> DataAny for Vec<T> {
|
||||
fn as_any(&self, id: TypeId) -> Option<&dyn Any> {
|
||||
(id == TypeId::of::<Self>()).then(|| self as &dyn Any)
|
||||
}
|
||||
|
||||
fn into_any(self: Box<Self>, id: TypeId) -> Result<Box<dyn Any>, Box<dyn DataAny>> {
|
||||
if id == TypeId::of::<Self>() { Ok(self) } else { Err(self) }
|
||||
}
|
||||
|
||||
fn into_lua(self: Box<Self>, lua: &Lua) -> mlua::Result<Value> { AnyData(self).into_lua(lua) }
|
||||
}
|
||||
|
||||
impl<T: Send + 'static> DataAny for tokio::sync::mpsc::UnboundedSender<T> {
|
||||
fn as_any(&self, id: TypeId) -> Option<&dyn Any> {
|
||||
(id == TypeId::of::<Self>()).then(|| self as &dyn Any)
|
||||
}
|
||||
|
||||
fn into_any(self: Box<Self>, id: TypeId) -> Result<Box<dyn Any>, Box<dyn DataAny>> {
|
||||
if id == TypeId::of::<Self>() { Ok(self) } else { Err(self) }
|
||||
}
|
||||
|
||||
fn into_lua(self: Box<Self>, lua: &Lua) -> mlua::Result<Value> { AnyData(self).into_lua(lua) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ impl Data {
|
|||
|
||||
pub fn as_any<T: 'static>(&self) -> Option<&T> {
|
||||
match self {
|
||||
Self::Any(b) => (**b).as_any().downcast_ref::<T>(),
|
||||
Self::Any(a) => a.downcast_ref::<T>(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -271,15 +271,15 @@ impl Data {
|
|||
|
||||
pub fn into_any<T: 'static>(self) -> Option<T> {
|
||||
match self {
|
||||
Self::Any(b) => b.into_any().downcast::<T>().ok().map(|b| *b),
|
||||
Self::Any(a) => a.downcast::<T>().ok().map(|b| *b),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: find a better name
|
||||
pub fn into_any2<T: 'static>(self) -> Result<T> {
|
||||
if let Self::Any(b) = self
|
||||
&& let Ok(t) = b.into_any().downcast::<T>()
|
||||
if let Self::Any(a) = self
|
||||
&& let Ok(t) = a.downcast::<T>()
|
||||
{
|
||||
Ok(*t)
|
||||
} else {
|
||||
|
|
|
|||
9
yazi-shared/src/data/inventory.rs
Normal file
9
yazi-shared/src/data/inventory.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
use mlua::{Lua, Value};
|
||||
|
||||
use crate::data::DataAny;
|
||||
|
||||
pub struct DataInventory {
|
||||
pub from_lua: fn(Value, &Lua) -> mlua::Result<Box<dyn DataAny>>,
|
||||
}
|
||||
|
||||
inventory::collect!(DataInventory);
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
yazi_macro::mod_flat!(any data de de_bytes de_key de_owned key);
|
||||
yazi_macro::mod_flat!(any data de de_bytes de_key de_owned inventory key);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
yazi_macro::mod_pub!(data event loc path pool scheme shell strand translit url wtf8);
|
||||
extern crate self as yazi_shared;
|
||||
|
||||
yazi_macro::mod_pub!(any_data data event loc path pool scheme shell strand translit url wtf8);
|
||||
|
||||
yazi_macro::mod_flat!(alias bytes chars completion_token condition debounce env id kebab_cased_string last_value layer localset natsort non_empty_string os predictor snake_cased_string source tests throttle time);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use std::{borrow::Cow, fmt::{Debug, Formatter}, hash::{Hash, Hasher}, path::{Pat
|
|||
|
||||
use anyhow::Result;
|
||||
use serde::{Deserialize, Serialize, de::{self, IntoDeserializer}};
|
||||
use yazi_macro::impl_data_any;
|
||||
|
||||
use crate::{loc::LocBuf, path::{PathBufDyn, PathDynError, SetNameError}, pool::{InternStr, Pool, Symbol}, scheme::{Scheme, SchemeLike}, strand::AsStrand, url::{AsUrl, Url, UrlCow, UrlDeserializer, UrlLike}};
|
||||
|
||||
|
|
@ -13,6 +14,8 @@ pub enum UrlBuf {
|
|||
Sftp { loc: LocBuf<typed_path::UnixPathBuf>, domain: Symbol<str> },
|
||||
}
|
||||
|
||||
impl_data_any!(UrlBuf);
|
||||
|
||||
// FIXME: remove
|
||||
impl Default for UrlBuf {
|
||||
fn default() -> Self { Self::Regular(Default::default()) }
|
||||
|
|
|
|||
|
|
@ -33,4 +33,4 @@ twox-hash = { workspace = true }
|
|||
unicode-width = { workspace = true }
|
||||
|
||||
[dependencies.unicode-segmentation]
|
||||
version = "1.13.2"
|
||||
version = "1.13.3"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ pub trait DeserializeOverLua: DeserializeOverWith {
|
|||
|
||||
impl<T: DeserializeOverWith> DeserializeOverLua for T {}
|
||||
|
||||
// --- IntoLua
|
||||
// --- LuaTableExt
|
||||
pub trait LuaTableExt {
|
||||
fn sequence_iter<V: FromLua>(&self, lua: &Lua) -> SequenceIter<V>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ bitflags = { workspace = true }
|
|||
futures = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
ratatui = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use bitflags::bitflags;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{ParseError, Result, bail, event::Modifiers};
|
||||
|
||||
|
|
@ -71,7 +72,8 @@ impl KeyEventState {
|
|||
}
|
||||
|
||||
// --- Code
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
#[serde(tag = "type", content = "value")]
|
||||
pub enum KeyCode {
|
||||
Char(char),
|
||||
Enter,
|
||||
|
|
@ -217,7 +219,8 @@ impl KeyCode {
|
|||
}
|
||||
|
||||
// --- Modifier key
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum ModifierKeyCode {
|
||||
LeftShift,
|
||||
LeftControl,
|
||||
|
|
@ -250,7 +253,8 @@ impl ModifierKeyCode {
|
|||
}
|
||||
|
||||
// --- Media key
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum MediaKeyCode {
|
||||
Play,
|
||||
Pause,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue