mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 14:51:03 +00:00
feat: experimental %y, %Y, %t, %T, %yN, %YN, %tN, %TN shell formatting parameters (#4108)
This commit is contained in:
parent
aa850f9a3b
commit
dbb0cc0d55
89 changed files with 561 additions and 649 deletions
|
|
@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
- Bulk create ([#3793])
|
||||
- Make help menu a command palette ([#4074])
|
||||
- Input history ([#4104])
|
||||
- Experimental `%y`, `%Y`, `%t`, `%T`, `%yN`, `%YN`, `%tN`, `%TN` shell formatting parameters ([#4108])
|
||||
- Make visual mode support wraparound scrolling ([#4101])
|
||||
- H/M/L Vim-like motion for moving cursor relative to viewport ([#3970])
|
||||
- Context-aware icons for inputs ([#4080])
|
||||
|
|
@ -1773,3 +1774,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
[#4096]: https://github.com/sxyazi/yazi/pull/4096
|
||||
[#4101]: https://github.com/sxyazi/yazi/pull/4101
|
||||
[#4104]: https://github.com/sxyazi/yazi/pull/4104
|
||||
[#4108]: https://github.com/sxyazi/yazi/pull/4108
|
||||
|
|
|
|||
171
Cargo.lock
generated
171
Cargo.lock
generated
|
|
@ -543,9 +543,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.65"
|
||||
version = "1.2.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
|
||||
checksum = "f5d6cac793997bd970000024b2934968efe83b382de4fdcf4fcb46b6ee4ad996"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
|
|
@ -780,18 +780,18 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.15"
|
||||
version = "0.5.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
|
||||
checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
|
|
@ -799,18 +799,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
version = "0.9.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
version = "0.8.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
|
|
@ -1194,14 +1194,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "exr"
|
||||
version = "1.74.0"
|
||||
version = "1.74.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be"
|
||||
checksum = "6be87932f10230a4339ab394edd8e4611fcb72553d8295b4d52ea55249b3daa5"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"half",
|
||||
"lebe",
|
||||
"miniz_oxide",
|
||||
"num-complex",
|
||||
"pulp",
|
||||
"smallvec",
|
||||
"zune-inflate",
|
||||
]
|
||||
|
|
@ -1695,9 +1697,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "533e68a5842e734946fe159fb03fc9bbbb254f590dd0d8ad321ae5ff7beca2c1"
|
||||
checksum = "dd854a95a4ac672fed8c054136039fd32c22cf039ff09ead7280afe920486483"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"inotify-sys",
|
||||
|
|
@ -1706,9 +1708,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "inotify-sys"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ea94e891b3606826e9c998be69ddca42247dad8ad50b1649a5cb7e1c9ae06fd"
|
||||
checksum = "c033f80b2c113cdf91ab7a33faa9cbc014726dcad99880c8609af2a370edf37d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
@ -1791,11 +1793,11 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.34"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||
checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"getrandom 0.4.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
|
@ -1954,18 +1956,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lua-src"
|
||||
version = "550.0.0"
|
||||
version = "550.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e836dc8ae16806c9bdcf42003a88da27d163433e3f9684c52f0301258004a4fb"
|
||||
checksum = "75c110c2fa33f34e0de05448e1f3eb2e0631e7a69e2d8ae1586cffc9fc9f9949"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "luajit-src"
|
||||
version = "210.6.6+707c12b"
|
||||
version = "210.7.2+b925b3e"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a86cc925d4053d0526ae7f5bc765dbd0d7a5d1a63d43974f4966cb349ca63295"
|
||||
checksum = "920cf654b23d217c550ceea57c32cd2a413ea27b6d47ed77b5ee0cf655adefa6"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"which",
|
||||
|
|
@ -1997,9 +1999,9 @@ checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0"
|
|||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.2"
|
||||
version = "2.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
|
|
@ -2048,31 +2050,31 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mlua"
|
||||
version = "0.11.6"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccd36acfa49ce6ee56d1307a061dd302c564eee757e6e4cd67eb4f7204846fab"
|
||||
checksum = "ad72ffa037cf5970c9860674f32f703fda25d86cf217475fe7a79c5f9961bcaa"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bstr",
|
||||
"either",
|
||||
"erased-serde",
|
||||
"futures-util",
|
||||
"inventory",
|
||||
"libc",
|
||||
"mlua-sys",
|
||||
"mlua_derive",
|
||||
"num-traits",
|
||||
"parking_lot",
|
||||
"rustc-hash",
|
||||
"rustversion",
|
||||
"serde",
|
||||
"serde-value",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mlua-sys"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f1c3a7fc7580227ece249fd90aa2fa3b39eb2b49d3aec5e103b3e85f2c3dfc8"
|
||||
checksum = "92136787b906d4e55cfe96cd6c62e010bb1a56889d0d6cf83eb016dbad07576b"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
|
|
@ -2084,16 +2086,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mlua_derive"
|
||||
version = "0.11.0"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "465bddde514c4eb3b50b543250e97c1d4b284fa3ef7dc0ba2992c77545dbceb2"
|
||||
checksum = "0232231813b214d44b57c7678e7dbbcfaac35bd1a01acef0dad7c5dfdc1b1973"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"once_cell",
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
|
@ -2206,6 +2204,16 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.2.2"
|
||||
|
|
@ -2694,28 +2702,6 @@ dependencies = [
|
|||
"wnaf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
|
|
@ -2745,10 +2731,33 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "pxfm"
|
||||
version = "0.1.29"
|
||||
name = "pulp"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f"
|
||||
checksum = "046aa45b989642ec2e4717c8e72d677b13edd831a4d3b6cf37d9a3e54912496a"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"cfg-if",
|
||||
"libm",
|
||||
"num-complex",
|
||||
"paste",
|
||||
"pulp-wasm-simd-flag",
|
||||
"raw-cpuid",
|
||||
"reborrow",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulp-wasm-simd-flag"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d8f70e07b9c3962945a74e59ca1c511bba65b6419468acc217c457d93f3c740"
|
||||
|
||||
[[package]]
|
||||
name = "pxfm"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
|
||||
|
||||
[[package]]
|
||||
name = "qoi"
|
||||
|
|
@ -2973,6 +2982,15 @@ dependencies = [
|
|||
"rgb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-cpuid"
|
||||
version = "11.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.12.0"
|
||||
|
|
@ -2993,6 +3011,12 @@ dependencies = [
|
|||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reborrow"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.18"
|
||||
|
|
@ -3113,9 +3137,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "russh"
|
||||
version = "0.62.1"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20d2039c3e50abb1ec3bdadea27098679da12a33befa9ab4e62adad9a13ebcb2"
|
||||
checksum = "ca6c3c1dd0a9ad3a9915a2f6e907d158f9a7e9ac32ddc772b003faafc027d9a8"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bitflags",
|
||||
|
|
@ -3242,9 +3266,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
|
|
@ -3813,9 +3837,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tikv-jemalloc-sys"
|
||||
version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7"
|
||||
version = "0.7.1+5.3.1-0-g81034ce1f1373e37dc865038e1bc8eeecf559ce8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b"
|
||||
checksum = "1a2825c78386b4ae0314074867860ba9577875de945f05992c38815cbec327f0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
|
|
@ -3823,9 +3847,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tikv-jemallocator"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0359b4327f954e0567e69fb191cf1436617748813819c94b8cd4a431422d053a"
|
||||
checksum = "249f09e49ab1609436f34c776e84231bead18d6a955f119f939bdc1d847561bd"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"tikv-jemalloc-sys",
|
||||
|
|
@ -5287,6 +5311,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"base64",
|
||||
"bitflags",
|
||||
"compact_str",
|
||||
"futures",
|
||||
"mlua",
|
||||
"parking_lot",
|
||||
|
|
@ -5421,18 +5446,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.52"
|
||||
version = "0.8.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f"
|
||||
checksum = "75726053136156d419e285b9b7eddaaea9e3fea6ce32eed44a89901f0bd98de1"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.52"
|
||||
version = "0.8.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930"
|
||||
checksum = "4714fd92cf900833d49538023a9b3915155210801d1c1169eba513b2addefd71"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ base64 = "0.22.1"
|
|||
bitflags = { version = "2.13.0", features = [ "serde" ] }
|
||||
chrono = "0.4.45"
|
||||
clap = { version = "4.6.1", features = [ "derive" ] }
|
||||
compact_str = { version = "0.9.1", features = [ "serde" ] }
|
||||
core-foundation-sys = "0.8.7"
|
||||
dirs = "6.0.0"
|
||||
dyn-clone = "1.0.20"
|
||||
|
|
@ -55,7 +56,7 @@ 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" ] }
|
||||
mlua = { version = "0.12.0", features = [ "anyhow", "async", "error-send", "lua55", "macros", "serde" ] }
|
||||
objc2 = "0.6.4"
|
||||
ordered-float = { version = "5.3.0", features = [ "serde" ] }
|
||||
parking_lot = "0.12.5"
|
||||
|
|
@ -65,7 +66,7 @@ rand = { version = "0.10.2", default-features = false, features =
|
|||
ratatui-core = { version = "0.1.2", default-features = false, features = [ "std", "layout-cache", "serde", "underline-color" ] }
|
||||
ratatui-widgets = { version = "0.3.2", default-features = false, features = [ "std", "unstable-rendered-line-info" ] }
|
||||
regex = "1.12.4"
|
||||
russh = { version = "0.62.1", default-features = false, features = [ "ring", "rsa" ] }
|
||||
russh = { version = "0.62.2", default-features = false, features = [ "ring", "rsa" ] }
|
||||
scopeguard = "1.2.0"
|
||||
serde = { version = "1.0.228", features = [ "derive" ] }
|
||||
serde_json = "1.0.150"
|
||||
|
|
|
|||
12
flake.lock
generated
12
flake.lock
generated
|
|
@ -20,11 +20,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1779877693,
|
||||
"narHash": "sha256-NOF9NAREhxr50bbBfVcVOq+ArCMSoe8dP79Pk2uyARk=",
|
||||
"lastModified": 1783279667,
|
||||
"narHash": "sha256-/NAkDSsve+GNM0Bt6tleJdCGfsTlK89nPjkVOzZMo0s=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4100e830e085863741bc69b156ec4ccd53ab5be0",
|
||||
"rev": "f205b5574fd0cb7da5b702a2da51507b7f4fdd1b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -48,11 +48,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779851998,
|
||||
"narHash": "sha256-UkkMh3bX9QW4Luqkm98nUaOqKWrU6i65mUnph3WeSSw=",
|
||||
"lastModified": 1783320166,
|
||||
"narHash": "sha256-l7C/OsjcnWDOk2K3ssj+SBduwL67LashjBqis9+t468=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "6cddd512fa2bf7231f098d3a2f92f6e4cff71e0a",
|
||||
"rev": "20ee15370c9256669d66968b89ee20a4b0a4e673",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use mlua::Value;
|
||||
use mlua::{LuaString, Value};
|
||||
use ratatui_core::layout::Position;
|
||||
use tracing::error;
|
||||
use yazi_actor::lives::Lives;
|
||||
|
|
@ -30,7 +30,7 @@ impl Actor for Reflow {
|
|||
continue;
|
||||
};
|
||||
|
||||
let id: mlua::String = t.get("_id")?;
|
||||
let id: LuaString = t.get("_id")?;
|
||||
match &*id.as_bytes() {
|
||||
b"current" => layout.current = *t.raw_get::<yazi_binding::elements::Rect>("_area")?,
|
||||
b"preview" => layout.preview = *t.raw_get::<yazi_binding::elements::Rect>("_area")?,
|
||||
|
|
|
|||
|
|
@ -108,6 +108,9 @@ impl<'a> Ctx<'a> {
|
|||
#[inline]
|
||||
pub fn hovered(&self) -> Option<&File> { self.tab().hovered() }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_url(&self) -> Option<&UrlBuf> { self.tab().hovered_url() }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_folder(&self) -> Option<&Folder> { self.tab().hovered_folder() }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, IntoLua, MetaMethod, UserData, UserDataMethods, UserDataRef, Value};
|
||||
use mlua::{AnyUserData, IntoLua, LuaString, MetaMethod, UserData, UserDataMethods, UserDataRef, Value};
|
||||
use paste::paste;
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
|
|
@ -43,7 +43,7 @@ impl Core {
|
|||
|
||||
impl UserData for Core {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method_mut(MetaMethod::Index, |lua, me, key: mlua::String| {
|
||||
methods.add_meta_method_mut(MetaMethod::Index, |lua, me, key: LuaString| {
|
||||
macro_rules! reuse {
|
||||
($key:ident, $value:expr) => {
|
||||
match paste! { &me.[<c_ $key>] } {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use yazi_fs::{FilesOp, Splatter, file::File, provider::{Provider, local::Local}}
|
|||
use yazi_macro::{succ, writef};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_proxy::TasksProxy;
|
||||
use yazi_scheduler::{AppProxy, NotifyProxy};
|
||||
use yazi_shared::{data::Data, strand::Strand, url::{AsUrl, UrlBuf, UrlCow, UrlLike}};
|
||||
use yazi_scheduler::{AppProxy, NotifyProxy, process::ShellOpt};
|
||||
use yazi_shared::{data::Data, strand::Strand, url::{AsUrl, UrlBuf, UrlLike}};
|
||||
use yazi_shim::path::CROSS_SEPARATOR;
|
||||
use yazi_term::YIELD_TO_SUBPROCESS;
|
||||
use yazi_tty::{TTY, sequence::EraseScreen};
|
||||
|
|
@ -40,13 +40,12 @@ impl Actor for BulkCreate {
|
|||
});
|
||||
}
|
||||
|
||||
TasksProxy::process_exec(
|
||||
cwd.clone(),
|
||||
Splatter::new(&[UrlCow::default(), tmp.as_url().into()]).splat(&opener.run),
|
||||
vec![UrlCow::default(), UrlBuf::from(&tmp).into()],
|
||||
opener.block,
|
||||
opener.orphan,
|
||||
)
|
||||
TasksProxy::process_exec(ShellOpt {
|
||||
cwd: cwd.clone(),
|
||||
cmd: Splatter::new(&[tmp.as_url()]).splat(&opener.run),
|
||||
block: opener.block,
|
||||
orphan: opener.orphan,
|
||||
})
|
||||
.await;
|
||||
|
||||
let _permit = Permit::new(YIELD_TO_SUBPROCESS.acquire().await.unwrap(), AppProxy::resume());
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ use yazi_fs::{FilesOp, Splatter, file::File, max_common_root, path::skip_url, pr
|
|||
use yazi_macro::{err, succ, writef};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_proxy::TasksProxy;
|
||||
use yazi_scheduler::{AppProxy, NotifyProxy};
|
||||
use yazi_shared::{data::Data, path::PathDyn, strand::{AsStrand, AsStrandJoin, Strand, StrandBuf, StrandLike}, url::{AsUrl, UrlBuf, UrlCow, UrlLike}};
|
||||
use yazi_scheduler::{AppProxy, NotifyProxy, process::ShellOpt};
|
||||
use yazi_shared::{data::Data, path::PathDyn, strand::{AsStrand, AsStrandJoin, Strand, StrandBuf, StrandLike}, url::{AsUrl, UrlBuf, UrlLike}};
|
||||
use yazi_term::YIELD_TO_SUBPROCESS;
|
||||
use yazi_tty::{TTY, sequence::EraseScreen};
|
||||
use yazi_vfs::{VfsFile, maybe_exists, provider};
|
||||
|
|
@ -63,13 +63,12 @@ impl Actor for BulkRename {
|
|||
}
|
||||
|
||||
batcher.prime(&tmp);
|
||||
TasksProxy::process_exec(
|
||||
TasksProxy::process_exec(ShellOpt {
|
||||
cwd,
|
||||
Splatter::new(&[UrlCow::default(), tmp.as_url().into()]).splat(&opener.run),
|
||||
vec![UrlCow::default(), UrlBuf::from(&tmp).into()],
|
||||
opener.block,
|
||||
opener.orphan,
|
||||
)
|
||||
cmd: Splatter::new(&[tmp.as_url()]).splat(&opener.run),
|
||||
block: opener.block,
|
||||
orphan: opener.orphan,
|
||||
})
|
||||
.await;
|
||||
|
||||
let _permit = Permit::new(YIELD_TO_SUBPROCESS.acquire().await.unwrap(), AppProxy::resume());
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ impl Actor for Copy {
|
|||
|
||||
let mut s = Vec::<u8>::new();
|
||||
let mut it = if form.hovered {
|
||||
Box::new(cx.hovered().map(|h| &h.url).into_iter())
|
||||
Box::new(cx.hovered_url().into_iter())
|
||||
} else {
|
||||
cx.tab().selected_or_hovered_urls()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ impl Actor for Hover {
|
|||
|
||||
// Publish through DDS
|
||||
let tab = tab!(cx);
|
||||
err!(Pubsub::pub_after_hover(tab.id, tab.hovered().map(|h| &h.url)));
|
||||
err!(Pubsub::pub_after_hover(tab.id, tab.hovered_url()));
|
||||
succ!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ impl Actor for Open {
|
|||
succ!(if !opt.targets.is_empty() {
|
||||
Quit::with_selected(opt.targets)
|
||||
} else if opt.hovered {
|
||||
Quit::with_selected(cx.hovered().map(|h| &h.url))
|
||||
Quit::with_selected(cx.hovered_url())
|
||||
} else {
|
||||
act!(mgr:escape_visual, cx)?;
|
||||
Quit::with_selected(cx.tab().selected_or_hovered_urls())
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use anyhow::Result;
|
||||
use hashbrown::HashMap;
|
||||
use indexmap::IndexSet;
|
||||
use yazi_config::YAZI;
|
||||
use yazi_fs::file::File;
|
||||
use yazi_config::{YAZI, opener::OpenerRule};
|
||||
use yazi_fs::{Splatter, file::File};
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::mgr::OpenDoForm;
|
||||
use yazi_proxy::{PickProxy, TasksProxy};
|
||||
use yazi_scheduler::process::ProcessOpt;
|
||||
use yazi_shared::{data::Data, url::{UrlBuf, UrlCow}};
|
||||
use yazi_scheduler::process::ShellOpt;
|
||||
use yazi_shared::{data::Data, url::UrlBuf};
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ impl Actor for OpenDo {
|
|||
if targets.is_empty() {
|
||||
succ!();
|
||||
} else if !opt.interactive {
|
||||
succ!(Self::match_and_open(cx, opt.cwd, targets));
|
||||
succ!(Self::match_and_open(opt.cwd, targets));
|
||||
}
|
||||
|
||||
let openers: IndexSet<_> =
|
||||
|
|
@ -42,20 +42,10 @@ impl Actor for OpenDo {
|
|||
}
|
||||
|
||||
let pick = PickProxy::show(YAZI.pick.open(openers.iter().map(|o| o.desc()).collect()));
|
||||
let urls: Vec<_> = [UrlCow::default()]
|
||||
.into_iter()
|
||||
.chain(targets.into_iter().map(|(file, _)| file.url.into()))
|
||||
.collect();
|
||||
let urls: Vec<_> = targets.into_iter().map(|(file, _)| file.url).collect();
|
||||
tokio::spawn(async move {
|
||||
if let Some(choice) = pick.await {
|
||||
TasksProxy::open_shell_compat(ProcessOpt {
|
||||
cwd: opt.cwd,
|
||||
cmd: openers[choice].run.clone().into(),
|
||||
args: urls,
|
||||
block: openers[choice].block,
|
||||
orphan: openers[choice].orphan,
|
||||
spread: openers[choice].spread,
|
||||
});
|
||||
Self::open_with(&openers[choice], &opt.cwd, &urls);
|
||||
}
|
||||
});
|
||||
succ!();
|
||||
|
|
@ -63,24 +53,28 @@ impl Actor for OpenDo {
|
|||
}
|
||||
|
||||
impl OpenDo {
|
||||
// TODO: remove
|
||||
fn match_and_open(cx: &Ctx, cwd: UrlBuf, targets: Vec<(File, &str)>) {
|
||||
let mut openers = HashMap::new();
|
||||
fn match_and_open(cwd: UrlBuf, targets: Vec<(File, &str)>) {
|
||||
let mut openers: HashMap<_, Vec<_>> = Default::default();
|
||||
for (file, mime) in targets {
|
||||
if let Some(open) = YAZI.open.matches(&file, mime)
|
||||
&& let Some(opener) = YAZI.opener.first(&open)
|
||||
{
|
||||
openers.entry(opener).or_insert_with(|| vec![UrlCow::default()]).push(file.url.into());
|
||||
openers.entry(opener).or_default().push(file.url);
|
||||
}
|
||||
}
|
||||
for (opener, args) in openers {
|
||||
cx.tasks.open_shell_compat(ProcessOpt {
|
||||
cwd: cwd.clone(),
|
||||
cmd: opener.run.clone().into(),
|
||||
args,
|
||||
block: opener.block,
|
||||
for (opener, urls) in openers {
|
||||
Self::open_with(&opener, &cwd, &urls);
|
||||
}
|
||||
}
|
||||
|
||||
fn open_with(opener: &OpenerRule, cwd: &UrlBuf, urls: &[UrlBuf]) {
|
||||
let size = if opener.spread { urls.len().max(1) } else { 1 };
|
||||
for urls in urls.chunks(size) {
|
||||
TasksProxy::process_open(ShellOpt {
|
||||
cwd: cwd.clone(),
|
||||
cmd: Splatter::new(urls).splat(&opener.run),
|
||||
block: opener.block,
|
||||
orphan: opener.orphan,
|
||||
spread: opener.spread,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ use std::borrow::Cow;
|
|||
|
||||
use anyhow::Result;
|
||||
use yazi_config::YAZI;
|
||||
use yazi_core::mgr::MgrSnap;
|
||||
use yazi_fs::Splatter;
|
||||
use yazi_macro::{act, input, succ};
|
||||
use yazi_parser::mgr::ShellForm;
|
||||
use yazi_proxy::TasksProxy;
|
||||
use yazi_scheduler::process::ProcessOpt;
|
||||
use yazi_scheduler::process::ShellOpt;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_widgets::input::InputEvent;
|
||||
|
||||
|
|
@ -22,7 +24,7 @@ impl Actor for Shell {
|
|||
act!(mgr:escape_visual, cx)?;
|
||||
|
||||
let cwd = form.cwd.take().unwrap_or_else(|| cx.cwd().clone());
|
||||
let selected: Vec<_> = cx.tab().hovered_and_selected().cloned().map(Into::into).collect();
|
||||
let snap = MgrSnap::from(&cx.mgr);
|
||||
|
||||
let input = if form.interactive {
|
||||
Some(input!(
|
||||
|
|
@ -44,13 +46,11 @@ impl Actor for Shell {
|
|||
return;
|
||||
}
|
||||
|
||||
TasksProxy::open_shell_compat(ProcessOpt {
|
||||
TasksProxy::process_open(ShellOpt {
|
||||
cwd,
|
||||
cmd: form.run.to_string().into(),
|
||||
args: selected,
|
||||
cmd: Splatter::new(snap).splat(&*form.run),
|
||||
block: form.block,
|
||||
orphan: form.orphan,
|
||||
spread: true,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ impl Actor for UpdatePeeked {
|
|||
const NAME: &str = "update_peeked";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let Some(hovered) = cx.hovered().map(|h| &h.url) else {
|
||||
let Some(hovered) = cx.hovered_url() else {
|
||||
succ!(cx.tab_mut().preview.reset());
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl Actor for UpdateSpotted {
|
|||
|
||||
fn act(cx: &mut Ctx, mut form: Self::Form) -> Result<Data> {
|
||||
let tab = cx.tab_mut();
|
||||
let Some(hovered) = tab.hovered().map(|h| &h.url) else {
|
||||
let Some(hovered) = tab.hovered_url() else {
|
||||
succ!(tab.spot.reset());
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(arrow cancel close inspect open_shell_compat process_open show spawn update_succeed);
|
||||
yazi_macro::mod_flat!(arrow cancel close inspect process_open show spawn update_succeed);
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::tasks::ProcessOpenForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct OpenShellCompat;
|
||||
|
||||
// TODO: remove
|
||||
impl Actor for OpenShellCompat {
|
||||
type Form = ProcessOpenForm;
|
||||
|
||||
const NAME: &str = "open_shell_compat";
|
||||
|
||||
fn act(cx: &mut Ctx, Self::Form { opt, .. }: Self::Form) -> Result<Data> {
|
||||
succ!(cx.tasks.open_shell_compat(opt));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, IntoLuaMulti, UserData, UserDataMethods, Value};
|
||||
use mlua::{FromLua, IntoLua, IntoLuaMulti, UserData, UserDataMethods, Value};
|
||||
use yazi_codegen::FromLuaOwned;
|
||||
|
||||
use crate::Error;
|
||||
|
|
@ -54,16 +54,13 @@ impl<T: IntoLua + 'static> UserData for MpscUnboundedRx<T> {
|
|||
}
|
||||
|
||||
#[derive(FromLuaOwned)]
|
||||
pub struct OneshotTx<T: FromLua + 'static>(pub Option<tokio::sync::oneshot::Sender<T>>);
|
||||
pub struct OneshotRx<T: IntoLua + 'static>(pub Option<tokio::sync::oneshot::Receiver<T>>);
|
||||
pub struct OneshotTx<T: FromLua + 'static>(pub tokio::sync::oneshot::Sender<T>);
|
||||
pub struct OneshotRx<T: IntoLua + 'static>(pub tokio::sync::oneshot::Receiver<T>);
|
||||
|
||||
impl<T: FromLua> UserData for OneshotTx<T> {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_method_mut("send", |lua, me, value: Value| {
|
||||
let Some(tx) = me.0.take() else {
|
||||
return Err("Oneshot sender already used".into_lua_err());
|
||||
};
|
||||
match tx.send(T::from_lua(value, lua)?) {
|
||||
methods.add_method_once("send", |lua, me, value: Value| {
|
||||
match me.0.send(T::from_lua(value, lua)?) {
|
||||
Ok(()) => true.into_lua_multi(lua),
|
||||
Err(_) => (false, Error::custom("Oneshot receiver closed")).into_lua_multi(lua),
|
||||
}
|
||||
|
|
@ -73,11 +70,8 @@ impl<T: FromLua> UserData for OneshotTx<T> {
|
|||
|
||||
impl<T: IntoLua + 'static> UserData for OneshotRx<T> {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_async_method_mut("recv", |lua, mut me, ()| async move {
|
||||
let Some(rx) = me.0.take() else {
|
||||
return Err("Oneshot receiver already used".into_lua_err());
|
||||
};
|
||||
match rx.await {
|
||||
methods.add_async_method_once("recv", |lua, me, ()| async move {
|
||||
match me.0.await {
|
||||
Ok(value) => value.into_lua_multi(&lua),
|
||||
Err(e) => (Value::Nil, Error::custom(e.to_string())).into_lua_multi(&lua),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use hashbrown::HashMap;
|
||||
use mlua::{Lua, MetaMethod, UserData, UserDataMethods, Value};
|
||||
use mlua::{Lua, LuaString, MetaMethod, UserData, UserDataMethods, Value};
|
||||
|
||||
pub type ComposerGet = fn(&Lua, &[u8]) -> mlua::Result<Value>;
|
||||
pub type ComposerSet = fn(&Lua, &[u8], Value) -> mlua::Result<Value>;
|
||||
|
|
@ -24,7 +24,7 @@ where
|
|||
S: Fn(&Lua, &[u8], Value) -> mlua::Result<Value> + 'static,
|
||||
{
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method_mut(MetaMethod::Index, |lua, me, key: mlua::String| {
|
||||
methods.add_meta_method_mut(MetaMethod::Index, |lua, me, key: LuaString| {
|
||||
let key = key.as_bytes();
|
||||
if let Some(v) = me.cache.get(key.as_ref()) {
|
||||
return Ok(v.clone());
|
||||
|
|
@ -38,7 +38,7 @@ where
|
|||
|
||||
methods.add_meta_method_mut(
|
||||
MetaMethod::NewIndex,
|
||||
|lua, me, (key, value): (mlua::String, Value)| {
|
||||
|lua, me, (key, value): (LuaString, Value)| {
|
||||
let key = key.as_bytes();
|
||||
let value = (me.set)(lua, key.as_ref(), value)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::str::FromStr;
|
|||
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
#[derive(Clone, Copy, Default, UserData)]
|
||||
pub struct Color(pub ratatui_core::style::Color);
|
||||
|
||||
impl Color {
|
||||
|
|
@ -32,5 +32,3 @@ impl FromLua for Color {
|
|||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Color {}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use mlua::{FromLua, IntoLua, Lua, UserData, Value};
|
||||
|
||||
#[derive(Clone, Copy, Default, FromLua)]
|
||||
#[derive(Clone, Copy, Default, FromLua, UserData)]
|
||||
pub struct Constraint(pub(super) ratatui_core::layout::Constraint);
|
||||
|
||||
impl Constraint {
|
||||
|
|
@ -23,5 +23,3 @@ impl Constraint {
|
|||
impl From<Constraint> for ratatui_core::layout::Constraint {
|
||||
fn from(value: Constraint) -> Self { value.0 }
|
||||
}
|
||||
|
||||
impl UserData for Constraint {}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{borrow::Cow, mem, ops::{Deref, DerefMut}};
|
||||
|
||||
use ansi_to_tui::IntoText;
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, Function, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, Function, IntoLua, Lua, LuaString, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use ratatui_core::widgets::Widget;
|
||||
use unicode_width::UnicodeWidthChar;
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ impl Line {
|
|||
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||
let new = lua.create_function(|_, (_, line): (Table, Self)| Ok(line))?;
|
||||
|
||||
let parse = lua.create_function(|_, code: mlua::String| {
|
||||
let parse = lua.create_function(|_, code: LuaString| {
|
||||
let code = code.as_bytes();
|
||||
let Some(line) = code.split_inclusive(|&b| b == b'\n').next() else {
|
||||
return Ok(Self::default());
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{any::TypeId, mem};
|
||||
|
||||
use ansi_to_tui::IntoText;
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, LuaString, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use ratatui_core::widgets::Widget;
|
||||
use yazi_shim::SStr;
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ impl Text {
|
|||
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||
let new = lua.create_function(|_, (_, text): (Table, Self)| Ok(text))?;
|
||||
|
||||
let parse = lua.create_function(|_, code: mlua::String| {
|
||||
let parse = lua.create_function(|_, code: LuaString| {
|
||||
Ok(Self { inner: code.as_bytes().into_text().into_lua_err()?, ..Default::default() })
|
||||
})?;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::{borrow::Cow, fmt::Display};
|
||||
|
||||
use mlua::{ExternalError, Lua, MetaMethod, UserData, UserDataFields, UserDataMethods, Value};
|
||||
use mlua::{ExternalError, Lua, LuaString, MetaMethod, UserData, UserDataFields, UserDataMethods, Value};
|
||||
use yazi_codegen::FromLuaOwned;
|
||||
use yazi_shim::SStr;
|
||||
|
||||
|
|
@ -19,9 +19,9 @@ impl Error {
|
|||
let fs = lua.create_function(|_, value: Value| {
|
||||
Ok(Self::Fs(match value {
|
||||
Value::Table(t) => yazi_shim::fs::Error::custom(
|
||||
&t.raw_get::<mlua::String>("kind")?.to_str()?,
|
||||
&t.raw_get::<LuaString>("kind")?.to_str()?,
|
||||
t.raw_get("code")?,
|
||||
&t.raw_get::<mlua::String>("message")?.to_str()?,
|
||||
&t.raw_get::<LuaString>("message")?.to_str()?,
|
||||
)?,
|
||||
_ => Err("expected a table".into_lua_err())?,
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -46,6 +46,6 @@ impl Drop for Permit {
|
|||
|
||||
impl UserData for Permit {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_async_method_mut("drop", |_, mut me, ()| async move { Ok(me.dropping().await) });
|
||||
methods.add_async_method_once("drop", |_, mut me, ()| async move { Ok(me.dropping().await) });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataFields, UserDataMethods, Value};
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, LuaString, MetaMethod, Table, UserData, UserDataFields, UserDataMethods, Value};
|
||||
use yazi_shim::strum::IntoStr;
|
||||
|
||||
use crate::{elements::Pad, position::{Offset, Origin, Position}};
|
||||
|
|
@ -20,7 +20,7 @@ impl TryFrom<Table> for Position {
|
|||
|
||||
fn try_from(t: Table) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
origin: Origin::from_str(&t.raw_get::<mlua::String>(1)?.to_str()?).into_lua_err()?,
|
||||
origin: Origin::from_str(&t.raw_get::<LuaString>(1)?.to_str()?).into_lua_err()?,
|
||||
offset: Offset {
|
||||
x: t.raw_get("x").unwrap_or_default(),
|
||||
y: t.raw_get("y").unwrap_or_default(),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{ops::DerefMut, process::ExitStatus, time::Duration};
|
||||
|
||||
use futures::future::try_join3;
|
||||
use mlua::{AnyUserData, ExternalError, IntoLua, IntoLuaMulti, Table, UserData, UserDataMethods, Value};
|
||||
use mlua::{ExternalError, IntoLua, IntoLuaMulti, LuaString, Table, UserData, UserDataMethods, Value};
|
||||
use tokio::{io::{self, AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader, BufWriter}, process::{ChildStderr, ChildStdin, ChildStdout}, select};
|
||||
|
||||
use super::Status;
|
||||
|
|
@ -133,7 +133,7 @@ impl UserData for Child {
|
|||
}
|
||||
});
|
||||
|
||||
methods.add_async_method_mut("write_all", |lua, mut me, src: mlua::String| async move {
|
||||
methods.add_async_method_mut("write_all", |lua, mut me, src: LuaString| async move {
|
||||
let Some(stdin) = &mut me.stdin else {
|
||||
return Err("stdin is not piped".into_lua_err());
|
||||
};
|
||||
|
|
@ -158,8 +158,8 @@ impl UserData for Child {
|
|||
Err(e) => (Value::Nil, Error::Io(e)).into_lua_multi(&lua),
|
||||
}
|
||||
});
|
||||
methods.add_async_function("wait_with_output", |lua, ud: AnyUserData| async move {
|
||||
match ud.take::<Self>()?.wait_with_output().await {
|
||||
methods.add_async_method_once("wait_with_output", |lua, me, ()| async move {
|
||||
match me.wait_with_output().await {
|
||||
Ok(output) => Output::new(output).into_lua_multi(&lua),
|
||||
Err(e) => (Value::Nil, Error::Io(e)).into_lua_multi(&lua),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::{any::TypeId, ffi::OsStr, io, process::Stdio};
|
||||
|
||||
use mlua::{AnyUserData, ExternalError, IntoLua, IntoLuaMulti, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use mlua::{AnyUserData, ExternalError, IntoLua, IntoLuaMulti, Lua, LuaString, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use tokio::process::{ChildStderr, ChildStdin, ChildStdout};
|
||||
use yazi_shim::wtf8::FromWtf8;
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ impl UserData for Command {
|
|||
me.inner.arg(OsStr::from_wtf8(&s.as_bytes())?);
|
||||
}
|
||||
Value::Table(t) => {
|
||||
for s in t.sequence_values::<mlua::String>() {
|
||||
for s in t.sequence_values::<LuaString>() {
|
||||
me.inner.arg(OsStr::from_wtf8(&s?.as_bytes())?);
|
||||
}
|
||||
}
|
||||
|
|
@ -160,19 +160,16 @@ impl UserData for Command {
|
|||
}
|
||||
ud.into_lua(lua)
|
||||
});
|
||||
methods.add_function("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| {
|
||||
methods.add_function("cwd", |_, (ud, dir): (AnyUserData, LuaString)| {
|
||||
ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?.as_ref());
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function(
|
||||
"env",
|
||||
|_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?
|
||||
.inner
|
||||
.env(OsStr::from_wtf8(&key.as_bytes())?, OsStr::from_wtf8(&value.as_bytes())?);
|
||||
Ok(ud)
|
||||
},
|
||||
);
|
||||
methods.add_function("env", |_, (ud, key, value): (AnyUserData, LuaString, LuaString)| {
|
||||
ud.borrow_mut::<Self>()?
|
||||
.inner
|
||||
.env(OsStr::from_wtf8(&key.as_bytes())?, OsStr::from_wtf8(&value.as_bytes())?);
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function("stdin", |_, (ud, stdio): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stdin(make_stdio(stdio)?);
|
||||
Ok(ud)
|
||||
|
|
|
|||
|
|
@ -196,21 +196,13 @@ pub fn overlay(input: TokenStream) -> TokenStream {
|
|||
pub fn from_lua(input: TokenStream) -> TokenStream {
|
||||
let DeriveInput { ident, generics, .. } = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let ident_str = ident.to_string();
|
||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
||||
|
||||
quote! {
|
||||
impl #impl_generics ::mlua::FromLua for #ident #ty_generics #where_clause {
|
||||
#[inline]
|
||||
fn from_lua(value: ::mlua::Value, _: &::mlua::Lua) -> ::mlua::Result<Self> {
|
||||
match value {
|
||||
::mlua::Value::UserData(ud) => ud.take::<Self>(),
|
||||
_ => Err(::mlua::Error::FromLuaConversionError {
|
||||
from: value.type_name(),
|
||||
to: #ident_str.to_owned(),
|
||||
message: None,
|
||||
}),
|
||||
}
|
||||
fn from_lua(value: ::mlua::Value, lua: &::mlua::Lua) -> ::mlua::Result<Self> {
|
||||
<::mlua::UserDataOwned<Self> as ::mlua::FromLua>::from_lua(value, lua).map(|ud| ud.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,14 @@ pub struct Key {
|
|||
|
||||
impl Key {
|
||||
pub fn plain(&self) -> Option<char> {
|
||||
match self.code {
|
||||
KeyCode::Char(c) if !self.ctrl && !self.alt && !self.super_ => Some(c),
|
||||
_ => None,
|
||||
if self.ctrl || self.alt || self.super_ {
|
||||
None
|
||||
} else if self.shift && !self.code.implies_shift() {
|
||||
None
|
||||
} else if let KeyCode::Char(c) = self.code {
|
||||
Some(c)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -130,7 +135,7 @@ impl Display for Key {
|
|||
if self.alt {
|
||||
write!(f, "A-")?;
|
||||
}
|
||||
if self.shift && !matches!(self.code, KeyCode::Char(_)) {
|
||||
if self.shift && !self.code.implies_shift() {
|
||||
write!(f, "S-")?;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::{mem, ops::Deref, sync::Arc};
|
|||
|
||||
use arc_swap::ArcSwap;
|
||||
use hashbrown::HashMap;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, IntoLuaMulti, MetaMethod, UserData, UserDataMethods, Value};
|
||||
use mlua::{ExternalError, FromLua, IntoLua, IntoLuaMulti, LuaString, MetaMethod, UserData, UserDataMethods, Value};
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use yazi_shim::{arc_swap::IntoPointee, toml::{DeserializeOverHook, DeserializeOverWith}};
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ impl DeserializeOverWith for Opener {
|
|||
|
||||
impl UserData for &'static Opener {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::Index, |lua, &me, key: mlua::String| {
|
||||
methods.add_meta_method(MetaMethod::Index, |lua, &me, key: LuaString| {
|
||||
let key = key.to_str()?;
|
||||
match me.load().get(&*key) {
|
||||
Some(rules) => rules.clone().into_lua(lua),
|
||||
|
|
@ -94,22 +94,19 @@ impl UserData for &'static Opener {
|
|||
}
|
||||
});
|
||||
|
||||
methods.add_meta_method(
|
||||
MetaMethod::NewIndex,
|
||||
|lua, &me, (key, value): (mlua::String, Value)| {
|
||||
let key = key.to_str()?;
|
||||
match value {
|
||||
t @ Value::Table(_) => {
|
||||
me.insert(&key, &OpenerRulesArc::from_lua(t, lua)?);
|
||||
}
|
||||
Value::Nil => {
|
||||
me.remove(&key);
|
||||
}
|
||||
_ => return Err("expected a table or nil".into_lua_err()),
|
||||
methods.add_meta_method(MetaMethod::NewIndex, |lua, &me, (key, value): (LuaString, Value)| {
|
||||
let key = key.to_str()?;
|
||||
match value {
|
||||
t @ Value::Table(_) => {
|
||||
me.insert(&key, &OpenerRulesArc::from_lua(t, lua)?);
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
Value::Nil => {
|
||||
me.remove(&key);
|
||||
}
|
||||
_ => return Err("expected a table or nil".into_lua_err()),
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
||||
methods.add_meta_method(MetaMethod::Pairs, |lua, &me, ()| {
|
||||
let mut matcher = OpenerRulesMatcher::from(me);
|
||||
|
|
|
|||
|
|
@ -32,15 +32,5 @@ impl OpenerRule {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn fill(&mut self) {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
self.spread =
|
||||
Splatter::<()>::spread(&self.run) || self.run.contains("$@") || self.run.contains("$*");
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
self.spread = Splatter::<()>::spread(&self.run) || self.run.contains("%*");
|
||||
}
|
||||
}
|
||||
pub fn fill(&mut self) { self.spread = Splatter::<()>::spread(&self.run); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use mlua::{MetaMethod, UserData, UserDataMethods};
|
||||
use mlua::{LuaString, MetaMethod, UserData, UserDataMethods};
|
||||
use yazi_shared::SnakeCasedString;
|
||||
|
||||
use crate::theme::{CustomField, CustomSection};
|
||||
|
|
@ -20,7 +20,7 @@ impl From<&CustomSection> for CustomSectionArc {
|
|||
|
||||
impl UserData for CustomSectionArc {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::Index, |_, me, key: mlua::String| {
|
||||
methods.add_meta_method(MetaMethod::Index, |_, me, key: LuaString| {
|
||||
Ok(me.get(&*key.to_str()?).cloned())
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub struct Help {
|
|||
}
|
||||
|
||||
impl Help {
|
||||
pub fn r#type(&mut self, key: KeyEvent) -> Result<bool> {
|
||||
pub fn r#type(&mut self, key: &KeyEvent) -> Result<bool> {
|
||||
if !self.input.r#type(key)? {
|
||||
return Ok(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
use std::iter;
|
||||
|
||||
use ratatui_core::layout::Rect;
|
||||
use yazi_binding::position::{Origin, Position};
|
||||
use yazi_fs::Splatable;
|
||||
use yazi_shared::url::{AsUrl, Url, UrlBuf};
|
||||
use yazi_shared::url::UrlBuf;
|
||||
use yazi_term::TERM;
|
||||
use yazi_watcher::Watcher;
|
||||
|
||||
|
|
@ -52,35 +49,12 @@ impl Mgr {
|
|||
#[inline]
|
||||
pub fn active_mut(&mut self) -> &mut Tab { self.tabs.active_mut() }
|
||||
|
||||
#[inline]
|
||||
pub fn current(&self) -> &Folder { &self.active().current }
|
||||
|
||||
#[inline]
|
||||
pub fn current_mut(&mut self) -> &mut Folder { &mut self.active_mut().current }
|
||||
|
||||
#[inline]
|
||||
pub fn parent_mut(&mut self) -> Option<&mut Folder> { self.active_mut().parent.as_mut() }
|
||||
}
|
||||
|
||||
impl Splatable for Mgr {
|
||||
fn tab(&self) -> usize { self.tabs.cursor }
|
||||
|
||||
fn selected(&self, tab: usize, mut idx: Option<usize>) -> impl Iterator<Item = Url<'_>> {
|
||||
idx = idx.and_then(|i| i.checked_sub(1));
|
||||
tab
|
||||
.checked_sub(1)
|
||||
.and_then(|tab| self.tabs.get(tab))
|
||||
.map(|tab| tab.selected_or_hovered_urls())
|
||||
.unwrap_or_else(|| Box::new(iter::empty()))
|
||||
.skip(idx.unwrap_or(0))
|
||||
.take(if idx.is_some() { 1 } else { usize::MAX })
|
||||
.map(|u| u.as_url())
|
||||
}
|
||||
|
||||
fn hovered(&self, tab: usize) -> Option<Url<'_>> {
|
||||
tab
|
||||
.checked_sub(1)
|
||||
.and_then(|tab| self.tabs.get(tab))
|
||||
.and_then(|tab| tab.hovered())
|
||||
.map(|h| h.url.as_url())
|
||||
}
|
||||
|
||||
fn yanked(&self) -> impl Iterator<Item = Url<'_>> { self.yanked.iter().map(|f| f.url.as_url()) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(batcher cd displace filter find mgr mimetype open search tabs yanked);
|
||||
yazi_macro::mod_flat!(batcher cd displace filter find mgr mimetype open search snap tabs yanked);
|
||||
|
|
|
|||
54
yazi-core/src/mgr/snap.rs
Normal file
54
yazi-core/src/mgr/snap.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
use yazi_fs::Splatable;
|
||||
use yazi_shared::url::{AsUrl, Url, UrlBuf};
|
||||
|
||||
use crate::{mgr::Mgr, tab::TabSnap};
|
||||
|
||||
pub struct MgrSnap {
|
||||
tab: usize,
|
||||
tabs: Vec<TabSnap>,
|
||||
yanked: Vec<UrlBuf>,
|
||||
}
|
||||
|
||||
impl From<&Mgr> for MgrSnap {
|
||||
fn from(value: &Mgr) -> Self {
|
||||
Self {
|
||||
tab: value.tabs.cursor,
|
||||
tabs: value.tabs.iter().map(Into::into).collect(),
|
||||
yanked: value.yanked.urls().cloned().collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Splatable for MgrSnap {
|
||||
fn tab(&self) -> usize { self.tab + 1 }
|
||||
|
||||
fn selected(&self, tab: usize, mut idx: Option<usize>) -> impl Iterator<Item = Url<'_>> {
|
||||
idx = idx.and_then(|i| i.checked_sub(1));
|
||||
tab
|
||||
.checked_sub(1)
|
||||
.and_then(|tab| self.tabs.get(tab))
|
||||
.map_or_else(|| &[][..], |s| &s.selected)
|
||||
.into_iter()
|
||||
.skip(idx.unwrap_or(0))
|
||||
.take(if idx.is_some() { 1 } else { usize::MAX })
|
||||
.map(AsUrl::as_url)
|
||||
}
|
||||
|
||||
fn hovered(&self, tab: usize) -> Option<Url<'_>> {
|
||||
tab
|
||||
.checked_sub(1)
|
||||
.and_then(|tab| self.tabs.get(tab))
|
||||
.and_then(|tab| tab.hovered.as_ref())
|
||||
.map(AsUrl::as_url)
|
||||
}
|
||||
|
||||
fn yanked(&self, mut idx: Option<usize>) -> impl Iterator<Item = Url<'_>> {
|
||||
idx = idx.and_then(|i| i.checked_sub(1));
|
||||
self
|
||||
.yanked
|
||||
.iter()
|
||||
.skip(idx.unwrap_or(0))
|
||||
.take(if idx.is_some() { 1 } else { usize::MAX })
|
||||
.map(AsUrl::as_url)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
use mlua::Table;
|
||||
use yazi_fs::file::FileRef;
|
||||
use yazi_fs::{cha::Cha, file::FileRef};
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::id::Id;
|
||||
use yazi_shared::{id::Id, url::UrlBuf};
|
||||
use yazi_widgets::Renderable;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SpotLock {
|
||||
pub url: yazi_shared::url::UrlBuf,
|
||||
pub cha: yazi_fs::cha::Cha,
|
||||
pub url: UrlBuf,
|
||||
pub cha: Cha,
|
||||
pub mime: String,
|
||||
|
||||
pub id: Id,
|
||||
|
|
|
|||
|
|
@ -169,6 +169,9 @@ impl Folder {
|
|||
#[inline]
|
||||
pub fn hovered_mut(&mut self) -> Option<&mut File> { self.entries.get_mut(self.cursor) }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_url(&self) -> Option<&UrlBuf> { self.hovered().map(|f| &f.url) }
|
||||
|
||||
pub fn paginate(&self, page: usize) -> &[File] {
|
||||
let len = self.entries.len();
|
||||
let limit = LAYOUT.get().folder_limit();
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(backstack finder folder history visual mode preference preview preview_lock selected tab);
|
||||
yazi_macro::mod_flat!(backstack finder folder history mode preference preview preview_lock selected snap tab visual);
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use mlua::Table;
|
||||
use mlua::{LuaString, Table};
|
||||
use yazi_binding::elements::Rect;
|
||||
use yazi_fs::file::FileRef;
|
||||
use yazi_fs::{cha::Cha, file::FileRef};
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::pool::{InternStr, Symbol};
|
||||
use yazi_shared::{pool::{InternStr, Symbol}, url::UrlBuf};
|
||||
use yazi_widgets::Renderable;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct PreviewLock {
|
||||
pub url: yazi_shared::url::UrlBuf,
|
||||
pub cha: yazi_fs::cha::Cha,
|
||||
pub url: UrlBuf,
|
||||
pub cha: Cha,
|
||||
pub mime: Symbol<str>,
|
||||
|
||||
pub skip: usize,
|
||||
|
|
@ -27,7 +27,7 @@ impl TryFrom<Table> for PreviewLock {
|
|||
Ok(Self {
|
||||
url: f.url_owned(),
|
||||
cha: f.cha,
|
||||
mime: t.raw_get::<mlua::String>("mime")?.to_str()?.intern(),
|
||||
mime: t.raw_get::<LuaString>("mime")?.to_str()?.intern(),
|
||||
|
||||
skip: t.raw_get("skip")?,
|
||||
area: t.raw_get("area")?,
|
||||
|
|
|
|||
17
yazi-core/src/tab/snap.rs
Normal file
17
yazi-core/src/tab/snap.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
use yazi_shared::url::UrlBuf;
|
||||
|
||||
use crate::tab::Tab;
|
||||
|
||||
pub struct TabSnap {
|
||||
pub hovered: Option<UrlBuf>,
|
||||
pub selected: Vec<UrlBuf>,
|
||||
}
|
||||
|
||||
impl From<&Tab> for TabSnap {
|
||||
fn from(value: &Tab) -> Self {
|
||||
Self {
|
||||
hovered: value.hovered_url().cloned(),
|
||||
selected: value.selected.urls().cloned().collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -78,6 +78,9 @@ impl Tab {
|
|||
#[inline]
|
||||
pub fn hovered(&self) -> Option<&File> { self.current.hovered() }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_url(&self) -> Option<&UrlBuf> { self.current.hovered_url() }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_mut(&mut self) -> Option<&mut File> { self.current.hovered_mut() }
|
||||
|
||||
|
|
@ -109,7 +112,7 @@ impl Tab {
|
|||
|
||||
pub fn selected_or_hovered_urls(&self) -> Box<dyn Iterator<Item = &UrlBuf> + '_> {
|
||||
if self.selected.is_empty() {
|
||||
Box::new(self.hovered().map(|h| &h.url).into_iter())
|
||||
Box::new(self.hovered_url().into_iter())
|
||||
} else {
|
||||
Box::new(self.selected.urls())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
yazi_macro::mod_flat!(file option prework process tasks);
|
||||
yazi_macro::mod_flat!(file option prework tasks);
|
||||
|
||||
pub const TASKS_BORDER: u16 = 2;
|
||||
pub const TASKS_PADDING: u16 = 2;
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
use std::mem;
|
||||
|
||||
use yazi_fs::Splatter;
|
||||
use yazi_scheduler::process::ProcessOpt;
|
||||
|
||||
use super::Tasks;
|
||||
|
||||
impl Tasks {
|
||||
// TODO: remove
|
||||
pub fn open_shell_compat(&self, mut opt: ProcessOpt) {
|
||||
if opt.spread {
|
||||
opt.cmd = Splatter::new(&opt.args).splat(opt.cmd);
|
||||
self.scheduler.process_open(opt);
|
||||
return;
|
||||
}
|
||||
if opt.args.is_empty() {
|
||||
return;
|
||||
}
|
||||
if opt.args.len() == 2 {
|
||||
opt.cmd = Splatter::new(&opt.args).splat(opt.cmd);
|
||||
self.scheduler.process_open(opt);
|
||||
return;
|
||||
}
|
||||
let hovered = mem::take(&mut opt.args[0]);
|
||||
for target in opt.args.into_iter().skip(1) {
|
||||
let args = vec![hovered.clone(), target];
|
||||
self.scheduler.process_open(ProcessOpt {
|
||||
cwd: opt.cwd.clone(),
|
||||
cmd: Splatter::new(&args).splat(&opt.cmd),
|
||||
args,
|
||||
block: opt.block,
|
||||
orphan: opt.orphan,
|
||||
spread: opt.spread,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ libc = { workspace = true }
|
|||
signal-hook-tokio = { version = "0.4.0", features = [ "futures-v0_3" ] }
|
||||
|
||||
[target.'cfg(all(not(target_os = "macos"), not(target_os = "windows")))'.dependencies]
|
||||
tikv-jemallocator = "0.6.1"
|
||||
tikv-jemallocator = "0.7.0"
|
||||
|
||||
[[bin]]
|
||||
name = "yazi"
|
||||
|
|
|
|||
|
|
@ -182,7 +182,6 @@ impl<'a> Executor<'a> {
|
|||
on!(inspect);
|
||||
on!(cancel);
|
||||
on!(process_open);
|
||||
on!(open_shell_compat);
|
||||
|
||||
match action.name.as_ref() {
|
||||
// Help
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ impl<'a> Router<'a> {
|
|||
use Layer as L;
|
||||
|
||||
let core = &mut self.app.core;
|
||||
if core.help.visible && core.help.r#type(key)? {
|
||||
if core.help.visible && core.help.r#type(&key)? {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
if let Some(mut guard) = core.input.lock_mut()
|
||||
&& guard.r#type(key)?
|
||||
&& guard.r#type(&key)?
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::os::unix::ffi::{OsStrExt, OsStringExt};
|
|||
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||
use std::{cell::Cell, ffi::{OsStr, OsString}, iter::{self, Peekable}, mem};
|
||||
|
||||
use yazi_shared::url::{AsUrl, Url, UrlCow};
|
||||
use yazi_shared::url::{AsUrl, Url};
|
||||
|
||||
use crate::FsUrl;
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ pub trait Splatable {
|
|||
|
||||
fn hovered(&self, tab: usize) -> Option<Url<'_>>;
|
||||
|
||||
fn yanked(&self) -> impl Iterator<Item = Url<'_>>;
|
||||
fn yanked(&self, idx: Option<usize>) -> impl Iterator<Item = Url<'_>>;
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
|
|
@ -50,7 +50,7 @@ impl<T> Splatter<T>
|
|||
where
|
||||
T: Splatable,
|
||||
{
|
||||
pub fn new(src: T) -> Self { Self { tab: src.tab() + 1, src } }
|
||||
pub fn new(src: T) -> Self { Self { tab: src.tab(), src } }
|
||||
|
||||
pub fn splat(mut self, cmd: impl AsRef<OsStr>) -> OsString {
|
||||
#[cfg(unix)]
|
||||
|
|
@ -82,8 +82,6 @@ where
|
|||
Some('t') | Some('T') => self.visit_tab(it, buf),
|
||||
Some('y') | Some('Y') => self.visit_yanked(it, buf),
|
||||
Some('%') => self.visit_escape(it, buf),
|
||||
Some('*') => self.visit_selected(it, buf), // TODO: remove this
|
||||
Some(c) if c.is_ascii_digit() => self.visit_digit(it, buf),
|
||||
_ => self.visit_unknown(it, buf),
|
||||
}
|
||||
}
|
||||
|
|
@ -154,32 +152,12 @@ where
|
|||
self.tab = old;
|
||||
}
|
||||
|
||||
fn visit_digit(&mut self, it: &mut Iter, buf: &mut Buf) {
|
||||
// TODO: remove
|
||||
match self.consume_digit(it) {
|
||||
Some(0) => {
|
||||
cue(buf, self.src.hovered(self.tab).map(|u| u.unified_path_str()).unwrap_or_default());
|
||||
}
|
||||
Some(n) => {
|
||||
cue(
|
||||
buf,
|
||||
self
|
||||
.src
|
||||
.selected(self.tab, Some(n))
|
||||
.next()
|
||||
.map(|u| u.unified_path_str())
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
}
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_yanked(&mut self, it: &mut Iter, buf: &mut Buf) {
|
||||
let c = it.next().and_then(b2c);
|
||||
let idx = self.consume_digit(it);
|
||||
|
||||
let mut first = true;
|
||||
for url in self.src.yanked() {
|
||||
for url in self.src.yanked(idx) {
|
||||
if !mem::replace(&mut first, false) {
|
||||
buf.push(b' ' as _);
|
||||
}
|
||||
|
|
@ -190,6 +168,9 @@ where
|
|||
cue(buf, url.unified_path_str());
|
||||
}
|
||||
}
|
||||
if first && idx.is_some() {
|
||||
cue(buf, "");
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_escape(&mut self, it: &mut Iter, buf: &mut Buf) { buf.push(it.next().unwrap()); }
|
||||
|
|
@ -232,10 +213,7 @@ impl<T> Splatter<T> {
|
|||
|
||||
fn hovered(&self, _tab: usize) -> Option<Url<'_>> { None }
|
||||
|
||||
fn yanked(&self) -> impl Iterator<Item = Url<'_>> {
|
||||
self.0.set(true);
|
||||
iter::empty()
|
||||
}
|
||||
fn yanked(&self, _idx: Option<usize>) -> impl Iterator<Item = Url<'_>> { iter::empty() }
|
||||
}
|
||||
|
||||
let src = Source(Cell::new(false));
|
||||
|
|
@ -244,28 +222,27 @@ impl<T> Splatter<T> {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
impl<'a, T> Splatable for &'a T
|
||||
impl<'a, I, T> Splatable for &'a I
|
||||
where
|
||||
T: AsRef<[UrlCow<'a>]>,
|
||||
I: ?Sized,
|
||||
&'a I: IntoIterator<Item = &'a T>,
|
||||
T: AsUrl + 'a,
|
||||
{
|
||||
fn tab(&self) -> usize { 0 }
|
||||
fn tab(&self) -> usize { 1 }
|
||||
|
||||
fn selected(&self, tab: usize, idx: Option<usize>) -> impl Iterator<Item = Url<'_>> {
|
||||
self
|
||||
.as_ref()
|
||||
.iter()
|
||||
fn selected(&self, tab: usize, mut idx: Option<usize>) -> impl Iterator<Item = Url<'_>> {
|
||||
idx = idx.and_then(|i| i.checked_sub(1));
|
||||
(*self)
|
||||
.into_iter()
|
||||
.filter(move |_| tab == 1)
|
||||
.map(|u| u.as_url())
|
||||
.skip(idx.unwrap_or(1))
|
||||
.skip(idx.unwrap_or(0))
|
||||
.take(if idx.is_some() { 1 } else { usize::MAX })
|
||||
}
|
||||
|
||||
fn hovered(&self, tab: usize) -> Option<Url<'_>> {
|
||||
self.as_ref().first().filter(|_| tab == 1).map(|u| u.as_url())
|
||||
}
|
||||
fn hovered(&self, _tab: usize) -> Option<Url<'_>> { None }
|
||||
|
||||
fn yanked(&self) -> impl Iterator<Item = Url<'_>> { iter::empty() }
|
||||
fn yanked(&self, _idx: Option<usize>) -> impl Iterator<Item = Url<'_>> { iter::empty() }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -300,8 +277,12 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
fn yanked(&self) -> impl Iterator<Item = Url<'_>> {
|
||||
[Url::regular("y1"), Url::regular("y 2"), Url::regular("y3")].into_iter()
|
||||
fn yanked(&self, mut idx: Option<usize>) -> impl Iterator<Item = Url<'_>> {
|
||||
idx = idx.and_then(|i| i.checked_sub(1));
|
||||
[Url::regular("y1"), Url::regular("y 2"), Url::regular("y3")]
|
||||
.into_iter()
|
||||
.skip(idx.unwrap_or(0))
|
||||
.take(if idx.is_some() { 1 } else { usize::MAX })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -310,41 +291,40 @@ mod tests {
|
|||
fn test_unix() {
|
||||
let cases = [
|
||||
// Selected
|
||||
(Source(0), r#"ls %s"#, r#"ls t1/s1 t1/s2"#),
|
||||
(Source(0), r#"ls %s1 %s2 %s3"#, r#"ls t1/s1 t1/s2 ''"#),
|
||||
(Source(0), r#"ls %s %s2 %s"#, r#"ls t1/s1 t1/s2 t1/s2 t1/s1 t1/s2"#),
|
||||
(Source(1), r#"ls %s"#, r#"ls 't 2/s 1' 't 2/s 2'"#),
|
||||
(Source(1), r#"ls %s1 %s3 %s2"#, r#"ls 't 2/s 1' '' 't 2/s 2'"#),
|
||||
(Source(2), r#"ls %s"#, r#"ls "#),
|
||||
(Source(2), r#"ls %s1 %s %s2"#, r#"ls '' ''"#),
|
||||
(Source(1), r#"ls %s"#, r#"ls t1/s1 t1/s2"#),
|
||||
(Source(1), r#"ls %s1 %s2 %s3"#, r#"ls t1/s1 t1/s2 ''"#),
|
||||
(Source(1), r#"ls %s %s2 %s"#, r#"ls t1/s1 t1/s2 t1/s2 t1/s1 t1/s2"#),
|
||||
(Source(2), r#"ls %s"#, r#"ls 't 2/s 1' 't 2/s 2'"#),
|
||||
(Source(2), r#"ls %s1 %s3 %s2"#, r#"ls 't 2/s 1' '' 't 2/s 2'"#),
|
||||
(Source(3), r#"ls %s"#, r#"ls "#),
|
||||
(Source(3), r#"ls %s1 %s %s2"#, r#"ls '' ''"#),
|
||||
// Hovered
|
||||
(Source(0), r#"ls %h"#, r#"ls hovered"#),
|
||||
(Source(1), r#"ls %h"#, r#"ls 'hover ed'"#),
|
||||
(Source(2), r#"ls %h"#, r#"ls ''"#),
|
||||
(Source(1), r#"ls %h"#, r#"ls hovered"#),
|
||||
(Source(2), r#"ls %h"#, r#"ls 'hover ed'"#),
|
||||
(Source(3), r#"ls %h"#, r#"ls ''"#),
|
||||
// Dirname
|
||||
(Source(0), r#"cd %d"#, r#"cd t1 t1"#),
|
||||
(Source(1), r#"cd %d"#, r#"cd 't 2' 't 2'"#),
|
||||
(Source(1), r#"cd %d1 %d3 %d2"#, r#"cd 't 2' '' 't 2'"#),
|
||||
(Source(2), r#"cd %d %d1"#, r#"cd ''"#),
|
||||
(Source(1), r#"cd %d"#, r#"cd t1 t1"#),
|
||||
(Source(2), r#"cd %d"#, r#"cd 't 2' 't 2'"#),
|
||||
(Source(2), r#"cd %d1 %d3 %d2"#, r#"cd 't 2' '' 't 2'"#),
|
||||
(Source(3), r#"cd %d %d1"#, r#"cd ''"#),
|
||||
// Yanked
|
||||
(Source(0), r#"cd %y"#, r#"cd y1 'y 2' y3"#),
|
||||
(Source(1), r#"cd %y"#, r#"cd y1 'y 2' y3"#),
|
||||
(Source(2), r#"cd %y"#, r#"cd y1 'y 2' y3"#),
|
||||
(Source(3), r#"cd %y"#, r#"cd y1 'y 2' y3"#),
|
||||
(Source(1), r#"cd %y1 %y3 %y2 %y4"#, r#"cd y1 y3 'y 2' ''"#),
|
||||
// Tab
|
||||
(Source(0), r#"ls %s %ts %s"#, r#"ls t1/s1 t1/s2 't 2/s 1' 't 2/s 2' t1/s1 t1/s2"#),
|
||||
(Source(1), r#"ls %s1 %ts %s2"#, r#"ls 't 2/s 1' 't 2/s 2'"#),
|
||||
(Source(1), r#"ls %s1 %Ts1 %s2 %Ts2"#, r#"ls 't 2/s 1' t1/s1 't 2/s 2' t1/s2"#),
|
||||
(Source(0), r#"ls %s1 %Ts1 %s2 %Ts2"#, r#"ls t1/s1 '' t1/s2 ''"#),
|
||||
(Source(0), r#"ls %ty"#, r#"ls y1 'y 2' y3"#),
|
||||
(Source(0), r#"ls %Ty"#, r#"ls y1 'y 2' y3"#),
|
||||
(Source(1), r#"ls %s %ts %s"#, r#"ls t1/s1 t1/s2 't 2/s 1' 't 2/s 2' t1/s1 t1/s2"#),
|
||||
(Source(2), r#"ls %s1 %ts %s2"#, r#"ls 't 2/s 1' 't 2/s 2'"#),
|
||||
(Source(2), r#"ls %s1 %Ts1 %s2 %Ts2"#, r#"ls 't 2/s 1' t1/s1 't 2/s 2' t1/s2"#),
|
||||
(Source(1), r#"ls %s1 %Ts1 %s2 %Ts2"#, r#"ls t1/s1 '' t1/s2 ''"#),
|
||||
(Source(1), r#"ls %ty"#, r#"ls y1 'y 2' y3"#),
|
||||
(Source(1), r#"ls %Ty"#, r#"ls y1 'y 2' y3"#),
|
||||
// Escape
|
||||
(
|
||||
Source(0),
|
||||
Source(1),
|
||||
r#"echo % %% %s2 %%h %d %%%y %%%%ts %%%%%ts1"#,
|
||||
r#"echo % % t1/s2 %h t1 t1 %y1 'y 2' y3 %%ts %%'t 2/s 1'"#,
|
||||
),
|
||||
// TODO: remove
|
||||
(Source(0), r#"ls %1 %* %2 %0 %3"#, r#"ls t1/s1 t1/s1 t1/s2 t1/s2 hovered ''"#),
|
||||
];
|
||||
|
||||
for (src, cmd, expected) in cases {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use anyhow::anyhow;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use yazi_scheduler::process::ProcessOpt;
|
||||
use yazi_scheduler::process::ShellOpt;
|
||||
use yazi_shared::event::{ActionCow, Replier};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ProcessOpenForm {
|
||||
pub opt: ProcessOpt,
|
||||
pub opt: ShellOpt,
|
||||
pub replier: Option<Replier>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use mlua::{ExternalError, Function, IntoLua, IntoLuaMulti, Lua, Table, Value};
|
||||
use mlua::{ExternalError, Function, IntoLua, IntoLuaMulti, Lua, LuaString, Table, Value};
|
||||
use yazi_binding::{Composer, ComposerGet, ComposerSet, Error};
|
||||
use yazi_config::Pattern;
|
||||
use yazi_fs::{file::File, mounts::PARTITIONS, provider::{Attrs, DirReader, FileHolder}};
|
||||
|
|
@ -81,7 +81,7 @@ fn copy(lua: &Lua) -> mlua::Result<Function> {
|
|||
}
|
||||
|
||||
fn create(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, (r#type, url): (mlua::String, UrlRef)| async move {
|
||||
lua.create_async_function(|lua, (r#type, url): (LuaString, UrlRef)| async move {
|
||||
let result = match &*r#type.as_bytes() {
|
||||
b"dir" => provider::create_dir(&*url).await,
|
||||
b"dir_all" => provider::create_dir_all(&*url).await,
|
||||
|
|
@ -132,7 +132,7 @@ fn file(lua: &Lua) -> mlua::Result<Function> {
|
|||
}
|
||||
|
||||
fn op(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (name, t): (mlua::String, Table)| match &*name.as_bytes() {
|
||||
lua.create_function(|lua, (name, t): (LuaString, Table)| match &*name.as_bytes() {
|
||||
b"part" => super::FilesOp::part(lua, t),
|
||||
b"done" => super::FilesOp::done(lua, t),
|
||||
b"size" => super::FilesOp::size(lua, t),
|
||||
|
|
@ -162,7 +162,7 @@ fn partitions(lua: &Lua) -> mlua::Result<Function> {
|
|||
|
||||
fn read_dir(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, (dir, options): (UrlRef, Table)| async move {
|
||||
let pat = if let Ok(s) = options.raw_get::<mlua::String>("glob") {
|
||||
let pat = if let Ok(s) = options.raw_get::<LuaString>("glob") {
|
||||
Some(Pattern::from_str(&s.to_str()?)?)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -202,7 +202,7 @@ fn read_dir(lua: &Lua) -> mlua::Result<Function> {
|
|||
}
|
||||
|
||||
fn remove(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, (r#type, url): (mlua::String, UrlRef)| async move {
|
||||
lua.create_async_function(|lua, (r#type, url): (LuaString, UrlRef)| async move {
|
||||
let result = match &*r#type.as_bytes() {
|
||||
b"file" => provider::remove_file(&*url).await,
|
||||
b"dir" => provider::remove_dir(&*url).await,
|
||||
|
|
@ -228,7 +228,7 @@ fn rename(lua: &Lua) -> mlua::Result<Function> {
|
|||
}
|
||||
|
||||
fn unique(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, (r#type, url): (mlua::String, UrlRef)| async move {
|
||||
lua.create_async_function(|lua, (r#type, url): (LuaString, UrlRef)| async move {
|
||||
let result = match &*r#type.as_bytes() {
|
||||
b"dir" => yazi_vfs::unique_file(url.clone(), true).await,
|
||||
b"file" => yazi_vfs::unique_file(url.clone(), false).await,
|
||||
|
|
@ -243,7 +243,7 @@ fn unique(lua: &Lua) -> mlua::Result<Function> {
|
|||
}
|
||||
|
||||
fn write(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, (url, data): (UrlRef, mlua::String)| async move {
|
||||
lua.create_async_function(|lua, (url, data): (UrlRef, LuaString)| async move {
|
||||
match provider::write(&*url, data.as_bytes()).await {
|
||||
Ok(()) => true.into_lua_multi(&lua),
|
||||
Err(e) => (false, Error::Io(e)).into_lua_multi(&lua),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use yazi_codegen::FromLuaOwned;
|
|||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::url::UrlBuf;
|
||||
|
||||
#[derive(Clone, FromLuaOwned)]
|
||||
#[derive(Clone, FromLuaOwned, UserData)]
|
||||
pub(super) struct FilesOp(yazi_fs::FilesOp);
|
||||
|
||||
impl_data_any!(FilesOp => yazi_fs::FilesOp; from_into_lua = inherit);
|
||||
|
|
@ -44,5 +44,3 @@ impl FilesOp {
|
|||
Ok(Self(yazi_fs::FilesOp::Size(url, sizes.pairs().collect::<mlua::Result<_>>()?)))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for FilesOp {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{ExternalResult, Function, Lua, Value};
|
||||
use mlua::{ExternalResult, Function, Lua, LuaString, Value};
|
||||
use yazi_binding::runtime;
|
||||
use yazi_dds::ember::Ember;
|
||||
use yazi_shared::id::Id;
|
||||
|
|
@ -7,20 +7,20 @@ pub struct Pubsub;
|
|||
|
||||
impl Pubsub {
|
||||
pub(super) fn r#pub(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (kind, value): (mlua::String, Value)| {
|
||||
lua.create_function(|lua, (kind, value): (LuaString, Value)| {
|
||||
yazi_dds::Pubsub::r#pub(Ember::from_lua(lua, &kind.to_str()?, value)?).into_lua_err()
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn pub_to(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (receiver, kind, value): (Id, mlua::String, Value)| {
|
||||
lua.create_function(|lua, (receiver, kind, value): (Id, LuaString, Value)| {
|
||||
yazi_dds::Pubsub::pub_to(receiver, Ember::from_lua(lua, &kind.to_str()?, value)?)
|
||||
.into_lua_err()
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn sub(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
|
||||
lua.create_function(|lua, (kind, f): (LuaString, Function)| {
|
||||
let rt = runtime!(lua)?;
|
||||
if !yazi_dds::Pubsub::sub(rt.current()?, &kind.to_str()?, f) {
|
||||
return Err("`sub()` called twice").into_lua_err();
|
||||
|
|
@ -30,7 +30,7 @@ impl Pubsub {
|
|||
}
|
||||
|
||||
pub(super) fn sub_remote(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
|
||||
lua.create_function(|lua, (kind, f): (LuaString, Function)| {
|
||||
let rt = runtime!(lua)?;
|
||||
if !yazi_dds::Pubsub::sub_remote(rt.current()?, &kind.to_str()?, f) {
|
||||
return Err("`sub_remote()` called twice").into_lua_err();
|
||||
|
|
@ -40,14 +40,14 @@ impl Pubsub {
|
|||
}
|
||||
|
||||
pub(super) fn unsub(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, kind: mlua::String| {
|
||||
lua.create_function(|lua, kind: LuaString| {
|
||||
let rt = runtime!(lua)?;
|
||||
Ok(yazi_dds::Pubsub::unsub(rt.current()?, &kind.to_str()?))
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn unsub_remote(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, kind: mlua::String| {
|
||||
lua.create_function(|lua, kind: LuaString| {
|
||||
let rt = runtime!(lua)?;
|
||||
Ok(yazi_dds::Pubsub::unsub_remote(rt.current()?, &kind.to_str()?))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{AnyUserData, UserData, UserDataMethods};
|
||||
use mlua::{AnyUserData, LuaString, UserData, UserDataMethods};
|
||||
use yazi_proxy::TasksProxy;
|
||||
use yazi_scheduler::TaskIn;
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ pub(crate) struct TaskOpt(pub(crate) yazi_core::tasks::TaskOpt);
|
|||
|
||||
impl UserData for TaskOpt {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_function("name", |_, (ud, name): (AnyUserData, mlua::String)| {
|
||||
methods.add_function("name", |_, (ud, name): (AnyUserData, LuaString)| {
|
||||
ud.borrow_mut::<Self>()?.0.set_title(name.to_string_lossy());
|
||||
Ok(ud)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{borrow::Cow, iter};
|
||||
|
||||
use ansi_to_tui::IntoText;
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, IntoLua, Lua, ObjectLike, Table, Value};
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, IntoLua, Lua, LuaString, ObjectLike, Table, Value};
|
||||
use tracing::error;
|
||||
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
||||
use yazi_binding::{Permit, PermitRef, elements::{Line, Rect, Span, Wrap}, runtime};
|
||||
|
|
@ -12,7 +12,7 @@ use yazi_shim::ratatui::LineIter;
|
|||
use yazi_term::YIELD_TO_SUBPROCESS;
|
||||
|
||||
pub(super) fn area(lua: &Lua) -> mlua::Result<Value> {
|
||||
let f = lua.create_function(|_, s: mlua::String| {
|
||||
let f = lua.create_function(|_, s: LuaString| {
|
||||
let layout = LAYOUT.get();
|
||||
Ok(match &*s.as_bytes() {
|
||||
b"current" => Rect(layout.current),
|
||||
|
|
@ -46,7 +46,7 @@ pub(super) fn hide(lua: &Lua) -> mlua::Result<Value> {
|
|||
}
|
||||
|
||||
pub(super) fn lines(lua: &Lua) -> mlua::Result<Value> {
|
||||
let f = lua.create_function(|lua, (s, opts): (mlua::String, Table)| {
|
||||
let f = lua.create_function(|lua, (s, opts): (LuaString, Table)| {
|
||||
let b = s.as_bytes();
|
||||
let s = &*String::from_utf8_lossy(&b);
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ pub(super) fn lines(lua: &Lua) -> mlua::Result<Value> {
|
|||
}
|
||||
|
||||
pub(super) fn printable(lua: &Lua) -> mlua::Result<Value> {
|
||||
let f = lua.create_function(|lua, s: mlua::String| {
|
||||
let f = lua.create_function(|lua, s: LuaString| {
|
||||
Ok(match replace_to_printable(&s.as_bytes(), false, 1, true) {
|
||||
Cow::Borrowed(_) => s,
|
||||
Cow::Owned(new) => lua.create_external_string(new)?,
|
||||
|
|
@ -86,7 +86,7 @@ pub(super) fn printable(lua: &Lua) -> mlua::Result<Value> {
|
|||
|
||||
pub(super) fn redraw(lua: &Lua) -> mlua::Result<Value> {
|
||||
let f = lua.create_function(|lua, c: Table| {
|
||||
let id: mlua::String = c.get("_id")?;
|
||||
let id: LuaString = c.get("_id")?;
|
||||
|
||||
let mut layout = LAYOUT.get();
|
||||
match &*id.as_bytes() {
|
||||
|
|
@ -135,7 +135,7 @@ pub(super) fn truncate(lua: &Lua) -> mlua::Result<Value> {
|
|||
(idx, last, adv > max)
|
||||
}
|
||||
|
||||
let f = lua.create_function(|lua, (s, t): (mlua::String, Table)| {
|
||||
let f = lua.create_function(|lua, (s, t): (LuaString, Table)| {
|
||||
let b = s.as_bytes();
|
||||
if b.is_empty() {
|
||||
return Ok(s);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::any::TypeId;
|
||||
|
||||
use mlua::{AnyUserData, ExternalError, Function, Lua};
|
||||
use mlua::{AnyUserData, ExternalError, Function, Lua, LuaString};
|
||||
use tokio::process::{ChildStderr, ChildStdin, ChildStdout};
|
||||
use yazi_vfs::provider::RwFile;
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ use super::Utils;
|
|||
|
||||
impl Utils {
|
||||
pub(super) fn id(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|_, r#type: mlua::String| {
|
||||
lua.create_function(|_, r#type: LuaString| {
|
||||
Ok(match &*r#type.as_bytes() {
|
||||
b"app" => *yazi_dds::ID,
|
||||
b"ft" => yazi_fs::FILES_TICKET.next(),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{Function, IntoLuaMulti, Lua, LuaSerdeExt, Value};
|
||||
use mlua::{Function, IntoLuaMulti, Lua, LuaSerdeExt, LuaString, Value};
|
||||
use yazi_binding::Error;
|
||||
use yazi_shim::mlua::SER_OPT;
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ impl Utils {
|
|||
}
|
||||
|
||||
pub(super) fn json_decode(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, s: mlua::String| async move {
|
||||
lua.create_async_function(|lua, s: LuaString| async move {
|
||||
match serde_json::from_slice::<serde_json::Value>(&s.as_bytes()) {
|
||||
Ok(v) => lua.to_value_with(&v, SER_OPT)?.into_lua_multi(&lua),
|
||||
Err(e) => (Value::Nil, Error::Serde(e)).into_lua_multi(&lua),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::{str::FromStr, time::Duration};
|
||||
|
||||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, Table, Value};
|
||||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, LuaString, Table, Value};
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
use yazi_binding::{elements::{Line, Text}, runtime};
|
||||
use yazi_config::{Platform, keymap::{Chord, ChordArc, Key}, popup::ConfirmCfg};
|
||||
|
|
@ -99,7 +99,7 @@ impl Utils {
|
|||
}
|
||||
Value::Table(t) => {
|
||||
let mut v = Vec::with_capacity(10);
|
||||
for s in t.sequence_values::<mlua::String>() {
|
||||
for s in t.sequence_values::<LuaString>() {
|
||||
v.push(Key::from_str(&s?.to_str()?).into_lua_err()?);
|
||||
}
|
||||
v
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use std::{any::TypeId, fmt::Write};
|
||||
use std::fmt::Write;
|
||||
|
||||
use mlua::{Function, Lua, MultiValue, Value};
|
||||
use mlua::{Function, Lua, MultiValue};
|
||||
use tracing::{debug, error};
|
||||
use yazi_shared::{id::Id, path::PathBufDyn, url::UrlBuf};
|
||||
|
||||
use super::Utils;
|
||||
|
||||
|
|
@ -21,27 +20,8 @@ impl Utils {
|
|||
if !s.is_empty() {
|
||||
s.push(' ');
|
||||
}
|
||||
Self::format_one(&mut s, value)?;
|
||||
write!(s, "{value:#?}")?;
|
||||
}
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn format_one(buf: &mut String, value: Value) -> anyhow::Result<()> {
|
||||
let Value::UserData(ud) = &value else {
|
||||
return Ok(write!(buf, "{value:#?}")?);
|
||||
};
|
||||
|
||||
let id = ud.type_id();
|
||||
let ptr = ud.to_pointer();
|
||||
Ok(match id {
|
||||
Some(t) if t == TypeId::of::<UrlBuf>() => {
|
||||
write!(buf, "Url({ptr:?}): {:?}", *ud.borrow::<UrlBuf>()?)?
|
||||
}
|
||||
Some(t) if t == TypeId::of::<PathBufDyn>() => {
|
||||
write!(buf, "Path({ptr:?}): {:?}", *ud.borrow::<PathBufDyn>()?)?
|
||||
}
|
||||
Some(t) if t == TypeId::of::<Id>() => write!(buf, "Id({ptr:?}): {}", *ud.borrow::<Id>()?)?,
|
||||
_ => write!(buf, "{value:#?}")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::Context;
|
||||
use futures::future::join_all;
|
||||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, MultiValue, Table, Value, Variadic};
|
||||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, LuaString, MultiValue, Table, Value, Variadic};
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_binding::{Handle, MpscRx, MpscTx, MpscUnboundedRx, MpscUnboundedTx, OneshotRx, OneshotTx, runtime, runtime_mut};
|
||||
use yazi_core::{AppProxy, app::PluginOpt};
|
||||
|
|
@ -88,7 +88,7 @@ impl Utils {
|
|||
}
|
||||
|
||||
pub(super) fn chan(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (r#type, buffer): (mlua::String, Option<usize>)| {
|
||||
lua.create_function(|lua, (r#type, buffer): (LuaString, Option<usize>)| {
|
||||
match (&*r#type.as_bytes(), buffer) {
|
||||
(b"mpsc", Some(buffer)) if buffer < 1 => {
|
||||
Err("Buffer size must be greater than 0".into_lua_err())
|
||||
|
|
@ -103,7 +103,7 @@ impl Utils {
|
|||
}
|
||||
(b"oneshot", _) => {
|
||||
let (tx, rx) = tokio::sync::oneshot::channel::<Value>();
|
||||
(OneshotTx(Some(tx)), OneshotRx(Some(rx))).into_lua_multi(lua)
|
||||
(OneshotTx(tx), OneshotRx(rx)).into_lua_multi(lua)
|
||||
}
|
||||
_ => Err("Channel type must be `mpsc` or `oneshot`".into_lua_err()),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{ExternalError, FromLua, Function, Lua, Value};
|
||||
use mlua::{ExternalError, FromLua, Function, Lua, LuaString, Value};
|
||||
use yazi_core::tasks;
|
||||
|
||||
use super::Utils;
|
||||
|
|
@ -6,7 +6,7 @@ use crate::tasks::TaskOpt;
|
|||
|
||||
impl Utils {
|
||||
pub(super) fn task(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (kind, value): (mlua::String, Value)| {
|
||||
lua.create_function(|lua, (kind, value): (LuaString, Value)| {
|
||||
Ok(TaskOpt(match &*kind.as_bytes() {
|
||||
b"cut" => tasks::TaskOpt::Cut(<_>::from_lua(value, lua)?),
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use mlua::{Function, Lua};
|
||||
use mlua::{Function, Lua, LuaString};
|
||||
use twox_hash::XxHash3_128;
|
||||
use yazi_shim::RFC_3986;
|
||||
use yazi_widgets::CLIPBOARD;
|
||||
|
|
@ -9,13 +9,13 @@ use super::Utils;
|
|||
|
||||
impl Utils {
|
||||
pub(super) fn hash(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(move |_, s: mlua::String| async move {
|
||||
lua.create_async_function(move |_, s: LuaString| async move {
|
||||
Ok(format!("{:x}", XxHash3_128::oneshot(&s.as_bytes())))
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn quote(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (s, unix): (mlua::String, Option<bool>)| {
|
||||
lua.create_function(|lua, (s, unix): (LuaString, Option<bool>)| {
|
||||
let b = s.as_bytes();
|
||||
let s = match unix {
|
||||
Some(true) => yazi_shared::shell::unix::escape_os_bytes(&b),
|
||||
|
|
@ -38,7 +38,7 @@ impl Utils {
|
|||
}
|
||||
|
||||
pub(super) fn percent_decode(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, s: mlua::String| {
|
||||
lua.create_function(|lua, s: LuaString| {
|
||||
let b = s.as_bytes();
|
||||
match percent_encoding::percent_decode(&b).into() {
|
||||
Cow::Borrowed(_) => Ok(s),
|
||||
|
|
@ -48,7 +48,7 @@ impl Utils {
|
|||
}
|
||||
|
||||
pub(super) fn percent_encode(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, s: mlua::String| {
|
||||
lua.create_function(|lua, s: LuaString| {
|
||||
let b = s.as_bytes();
|
||||
match percent_encoding::percent_encode(&b, RFC_3986).into() {
|
||||
Cow::Borrowed(_) => Ok(s),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
use std::ffi::OsString;
|
||||
|
||||
use anyhow::{Result, anyhow};
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_core::tasks::TaskOpt;
|
||||
use yazi_macro::{emit, relay};
|
||||
use yazi_scheduler::process::ProcessOpt;
|
||||
use yazi_shared::{id::Id, url::{UrlBuf, UrlCow}};
|
||||
use yazi_scheduler::process::ShellOpt;
|
||||
use yazi_shared::id::Id;
|
||||
|
||||
pub struct TasksProxy;
|
||||
|
||||
|
|
@ -17,24 +15,13 @@ impl TasksProxy {
|
|||
rx.recv().await.ok_or_else(|| anyhow!("channel closed"))??.try_into()
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
pub fn open_shell_compat(opt: ProcessOpt) {
|
||||
emit!(Call(relay!(tasks:open_shell_compat).with_any("opt", opt)));
|
||||
pub fn process_open(opt: ShellOpt) {
|
||||
emit!(Call(relay!(tasks:process_open).with_any("opt", opt)));
|
||||
}
|
||||
|
||||
pub async fn process_exec(
|
||||
cwd: UrlBuf,
|
||||
cmd: OsString,
|
||||
args: Vec<UrlCow<'static>>,
|
||||
block: bool,
|
||||
orphan: bool,
|
||||
) {
|
||||
pub async fn process_exec(opt: ShellOpt) {
|
||||
let (tx, mut rx) = mpsc::unbounded_channel();
|
||||
emit!(Call(
|
||||
relay!(tasks:process_open)
|
||||
.with_any("opt", ProcessOpt { cwd, cmd, args, block, orphan, spread: false })
|
||||
.with_replier(tx)
|
||||
));
|
||||
emit!(Call(relay!(tasks:process_open).with_any("opt", opt).with_replier(tx)));
|
||||
rx.recv().await;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use mlua::{AsChunk, ChunkMode};
|
||||
use mlua::chunk::{AsChunk, ChunkMode};
|
||||
use yazi_shared::natsort;
|
||||
|
||||
pub struct Chunk {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::{borrow::Cow, ops::Deref};
|
|||
|
||||
use anyhow::{Context, Result, bail, ensure};
|
||||
use hashbrown::HashMap;
|
||||
use mlua::{ChunkMode, ExternalError, Lua, Table};
|
||||
use mlua::{ExternalError, Lua, Table, chunk::ChunkMode};
|
||||
use parking_lot::RwLock;
|
||||
use yazi_fs::{Xdg, provider::local::Local};
|
||||
use yazi_macro::plugin_preset as preset;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::{borrow::Cow, sync::Arc};
|
||||
|
||||
use mlua::{ExternalResult, Function, IntoLua, Lua, MetaMethod, MultiValue, ObjectLike, Table, Value};
|
||||
use mlua::{ExternalResult, Function, IntoLua, Lua, LuaString, MetaMethod, MultiValue, ObjectLike, Table, Value};
|
||||
use yazi_binding::{runtime, runtime_mut};
|
||||
|
||||
use super::LOADER;
|
||||
|
|
@ -11,7 +11,7 @@ impl Require {
|
|||
pub(super) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.globals().raw_set(
|
||||
"require",
|
||||
lua.create_async_function(|lua, id: mlua::String| async move {
|
||||
lua.create_async_function(|lua, id: LuaString| async move {
|
||||
let id = id.to_str()?;
|
||||
let id = Self::absolute_id(&lua, &id)?;
|
||||
LOADER.ensure(&id, |_| ()).await.into_lua_err()?;
|
||||
|
|
@ -30,7 +30,7 @@ impl Require {
|
|||
let mt = lua.create_table_from([
|
||||
(
|
||||
MetaMethod::Index.name(),
|
||||
lua.create_function(move |lua, (ts, key): (Table, mlua::String)| {
|
||||
lua.create_function(move |lua, (ts, key): (Table, LuaString)| {
|
||||
match ts.raw_get::<Table>("__mod")?.raw_get::<Value>(&key)? {
|
||||
Value::Function(_) => {
|
||||
Self::create_wrapper(lua, id.clone(), &key.to_str()?)?.into_lua(lua)
|
||||
|
|
@ -41,7 +41,7 @@ impl Require {
|
|||
),
|
||||
(
|
||||
MetaMethod::NewIndex.name(),
|
||||
lua.create_function(move |_, (ts, key, value): (Table, mlua::String, Value)| {
|
||||
lua.create_function(move |_, (ts, key, value): (Table, LuaString, Value)| {
|
||||
ts.raw_get::<Table>("__mod")?.raw_set(key, value)
|
||||
})?,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::{borrow::Cow, ffi::OsString};
|
||||
|
||||
use yazi_shared::{CompletionToken, id::Id, url::{UrlBuf, UrlCow}};
|
||||
use yazi_shared::{CompletionToken, id::Id, url::UrlBuf};
|
||||
|
||||
use super::ShellOpt;
|
||||
use crate::{TaskIn, process::{ProcessProgBg, ProcessProgBlock, ProcessProgOrphan}};
|
||||
|
|
@ -46,10 +46,9 @@ impl TaskIn for ProcessIn {
|
|||
// --- Block
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ProcessInBlock {
|
||||
pub(crate) id: Id,
|
||||
pub(crate) cwd: UrlBuf,
|
||||
pub(crate) cmd: OsString,
|
||||
pub(crate) args: Vec<UrlCow<'static>>,
|
||||
pub(crate) id: Id,
|
||||
pub(crate) cwd: UrlBuf,
|
||||
pub(crate) cmd: OsString,
|
||||
}
|
||||
|
||||
impl TaskIn for ProcessInBlock {
|
||||
|
|
@ -67,17 +66,16 @@ impl TaskIn for ProcessInBlock {
|
|||
|
||||
impl From<ProcessInBlock> for ShellOpt {
|
||||
fn from(r#in: ProcessInBlock) -> Self {
|
||||
Self { cwd: r#in.cwd, cmd: r#in.cmd, args: r#in.args, piped: false, orphan: false }
|
||||
Self { cwd: r#in.cwd, cmd: r#in.cmd, block: true, orphan: false }
|
||||
}
|
||||
}
|
||||
|
||||
// --- Orphan
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ProcessInOrphan {
|
||||
pub(crate) id: Id,
|
||||
pub(crate) cwd: UrlBuf,
|
||||
pub(crate) cmd: OsString,
|
||||
pub(crate) args: Vec<UrlCow<'static>>,
|
||||
pub(crate) id: Id,
|
||||
pub(crate) cwd: UrlBuf,
|
||||
pub(crate) cmd: OsString,
|
||||
}
|
||||
|
||||
impl TaskIn for ProcessInOrphan {
|
||||
|
|
@ -95,7 +93,7 @@ impl TaskIn for ProcessInOrphan {
|
|||
|
||||
impl From<ProcessInOrphan> for ShellOpt {
|
||||
fn from(r#in: ProcessInOrphan) -> Self {
|
||||
Self { cwd: r#in.cwd, cmd: r#in.cmd, args: r#in.args, piped: false, orphan: true }
|
||||
Self { cwd: r#in.cwd, cmd: r#in.cmd, block: false, orphan: true }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +103,6 @@ pub(crate) struct ProcessInBg {
|
|||
pub(crate) id: Id,
|
||||
pub(crate) cwd: UrlBuf,
|
||||
pub(crate) cmd: OsString,
|
||||
pub(crate) args: Vec<UrlCow<'static>>,
|
||||
pub(crate) done: CompletionToken,
|
||||
}
|
||||
|
||||
|
|
@ -124,6 +121,6 @@ impl TaskIn for ProcessInBg {
|
|||
|
||||
impl From<ProcessInBg> for ShellOpt {
|
||||
fn from(r#in: ProcessInBg) -> Self {
|
||||
Self { cwd: r#in.cwd, cmd: r#in.cmd, args: r#in.args, piped: true, orphan: false }
|
||||
Self { cwd: r#in.cwd, cmd: r#in.cmd, block: false, orphan: false }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
yazi_macro::mod_flat!(option out process progress r#in shell);
|
||||
yazi_macro::mod_flat!(out process progress r#in shell);
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
use std::ffi::OsString;
|
||||
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::url::{UrlBuf, UrlCow};
|
||||
|
||||
// TODO: remove in favor of ShellForm
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ProcessOpt {
|
||||
pub cwd: UrlBuf,
|
||||
pub cmd: OsString,
|
||||
pub args: Vec<UrlCow<'static>>,
|
||||
pub block: bool,
|
||||
pub orphan: bool,
|
||||
|
||||
pub spread: bool, // TODO: remove
|
||||
}
|
||||
|
||||
impl_data_any!(ProcessOpt);
|
||||
|
|
@ -54,14 +54,8 @@ impl Process {
|
|||
}
|
||||
|
||||
pub(crate) async fn bg(&self, task: ProcessInBg) -> Result<(), ProcessOutBg> {
|
||||
let mut child = super::shell(ShellOpt {
|
||||
cwd: task.cwd,
|
||||
cmd: task.cmd,
|
||||
args: task.args,
|
||||
piped: true,
|
||||
orphan: false,
|
||||
})
|
||||
.await?;
|
||||
let mut child =
|
||||
super::shell(ShellOpt { cwd: task.cwd, cmd: task.cmd, block: false, orphan: false }).await?;
|
||||
|
||||
let done = task.done;
|
||||
let mut stdout = BufReader::new(child.stdout.take().unwrap()).lines();
|
||||
|
|
|
|||
|
|
@ -3,25 +3,28 @@ use std::{ffi::OsString, process::Stdio};
|
|||
use anyhow::Result;
|
||||
use tokio::process::{Child, Command};
|
||||
use yazi_fs::Cwd;
|
||||
use yazi_shared::url::{AsUrl, UrlBuf, UrlCow};
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::url::{AsUrl, UrlBuf};
|
||||
|
||||
pub(crate) struct ShellOpt {
|
||||
pub(crate) cwd: UrlBuf,
|
||||
pub(crate) cmd: OsString,
|
||||
pub(crate) args: Vec<UrlCow<'static>>,
|
||||
pub(crate) piped: bool,
|
||||
pub(crate) orphan: bool,
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ShellOpt {
|
||||
pub cwd: UrlBuf,
|
||||
pub cmd: OsString,
|
||||
pub block: bool,
|
||||
pub orphan: bool,
|
||||
}
|
||||
|
||||
impl_data_any!(ShellOpt);
|
||||
|
||||
impl ShellOpt {
|
||||
#[inline]
|
||||
fn stdio(&self) -> Stdio {
|
||||
if self.orphan {
|
||||
Stdio::null()
|
||||
} else if self.piped {
|
||||
Stdio::piped()
|
||||
} else {
|
||||
if self.block {
|
||||
Stdio::inherit()
|
||||
} else if self.orphan {
|
||||
Stdio::null()
|
||||
} else {
|
||||
Stdio::piped()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,21 +35,16 @@ pub(crate) async fn shell(opt: ShellOpt) -> Result<Child> {
|
|||
|
||||
#[cfg(unix)]
|
||||
return Ok(unsafe {
|
||||
use yazi_fs::FsUrl;
|
||||
use yazi_shared::url::AsUrl;
|
||||
|
||||
Command::new("sh")
|
||||
.stdin(opt.stdio())
|
||||
.stdout(opt.stdio())
|
||||
.stderr(opt.stdio())
|
||||
.arg("-c")
|
||||
.arg(opt.cmd)
|
||||
// TODO: remove
|
||||
.args(opt.args.iter().map(|u| u.as_url().unified_path_str()))
|
||||
.current_dir(cwd)
|
||||
.kill_on_drop(!opt.orphan)
|
||||
.pre_exec(move || {
|
||||
if (opt.piped || opt.orphan) && libc::setsid() < 0 {
|
||||
if !opt.block && libc::setsid() < 0 {
|
||||
return Err(std::io::Error::last_os_error());
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use yazi_config::{YAZI, plugin::{FetcherArc, PreloaderArc}};
|
|||
use yazi_fs::FsHash64;
|
||||
use yazi_shared::{CompletionToken, Throttle, id::Id, url::{UrlBuf, UrlLike}};
|
||||
|
||||
use crate::{Behavior, HIGH, LOW, NORMAL, Task, TaskIn, TaskProg, Worker, fetch::FetchIn, file::{FileInCopy, FileInCut, FileInDelete, FileInDownload, FileInHardlink, FileInLink, FileInTrash, FileInUpload, FileOutCopy, FileOutCut, FileOutDownload, FileOutHardlink, FileOutUpload}, hook::{HookIn, HookInDelete, HookInDownload, HookInPreload, HookInTrash, HookInUpload}, plugin::PluginInEntry, preload::PreloadIn, process::{ProcessIn, ProcessInBg, ProcessInBlock, ProcessInOrphan, ProcessOpt}, size::SizeIn};
|
||||
use crate::{Behavior, HIGH, LOW, NORMAL, Task, TaskIn, TaskProg, Worker, fetch::FetchIn, file::{FileInCopy, FileInCut, FileInDelete, FileInDownload, FileInHardlink, FileInLink, FileInTrash, FileInUpload, FileOutCopy, FileOutCut, FileOutDownload, FileOutHardlink, FileOutUpload}, hook::{HookIn, HookInDelete, HookInDownload, HookInPreload, HookInTrash, HookInUpload}, plugin::PluginInEntry, preload::PreloadIn, process::{ProcessIn, ProcessInBg, ProcessInBlock, ProcessInOrphan, ShellOpt}, size::SizeIn};
|
||||
|
||||
pub struct Scheduler {
|
||||
pub worker: Worker,
|
||||
|
|
@ -227,20 +227,14 @@ impl Scheduler {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn process_open(&self, opt: ProcessOpt) -> CompletionToken {
|
||||
pub fn process_open(&self, opt: ShellOpt) -> CompletionToken {
|
||||
let mut r#in: ProcessIn = if opt.block {
|
||||
ProcessInBlock { id: Id::ZERO, cwd: opt.cwd, cmd: opt.cmd, args: opt.args }.into()
|
||||
ProcessInBlock { id: Id::ZERO, cwd: opt.cwd, cmd: opt.cmd }.into()
|
||||
} else if opt.orphan {
|
||||
ProcessInOrphan { id: Id::ZERO, cwd: opt.cwd, cmd: opt.cmd, args: opt.args }.into()
|
||||
ProcessInOrphan { id: Id::ZERO, cwd: opt.cwd, cmd: opt.cmd }.into()
|
||||
} else {
|
||||
ProcessInBg {
|
||||
id: Id::ZERO,
|
||||
cwd: opt.cwd,
|
||||
cmd: opt.cmd,
|
||||
args: opt.args,
|
||||
done: CompletionToken::default(),
|
||||
}
|
||||
.into()
|
||||
ProcessInBg { id: Id::ZERO, cwd: opt.cwd, cmd: opt.cmd, done: CompletionToken::default() }
|
||||
.into()
|
||||
};
|
||||
|
||||
let done = match &mut r#in {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ futures = { workspace = true }
|
|||
hashbrown = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
inventory = { workspace = true }
|
||||
memchr = "2.8.2"
|
||||
memchr = "2.8.3"
|
||||
mlua = { workspace = true }
|
||||
ordered-float = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,5 @@ use mlua::UserData;
|
|||
|
||||
use crate::data::DataAny;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, UserData)]
|
||||
pub struct AnyData(pub Box<dyn DataAny>);
|
||||
|
||||
impl UserData for AnyData {}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use mlua::{ExternalError, ExternalResult, FromLua, Lua, UserData, UserDataFields, Value};
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, Lua, MetaMethod, UserData, UserDataFields, UserDataMethods, Value};
|
||||
|
||||
use crate::id::Id;
|
||||
use crate::{LOG_LEVEL, id::Id};
|
||||
|
||||
impl FromLua for Id {
|
||||
fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
|
||||
|
|
@ -16,4 +16,12 @@ impl UserData for Id {
|
|||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("value", |_, me| Ok(me.get()));
|
||||
}
|
||||
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
if !LOG_LEVEL.get().is_none() {
|
||||
methods.add_meta_function(MetaMethod::ToDebugString, |_, ud: AnyUserData| {
|
||||
Ok(format!("Id({:?}): {}", ud.to_pointer(), *ud.borrow::<Self>()?))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{ExternalError, ExternalResult, FromLua, MetaMethod, UserData, UserDataMethods, Value};
|
||||
use mlua::{ExternalError, ExternalResult, FromLua, Lua, MetaMethod, UserData, UserDataMethods, Value};
|
||||
use serde::Deserialize;
|
||||
use strum::{Display, EnumString, FromRepr, IntoStaticStr};
|
||||
use yazi_shim::strum::IntoStr;
|
||||
|
|
@ -41,7 +41,7 @@ impl Layer {
|
|||
}
|
||||
|
||||
impl FromLua for Layer {
|
||||
fn from_lua(value: Value, _: &mlua::Lua) -> mlua::Result<Self> {
|
||||
fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
|
||||
Ok(match value {
|
||||
Value::String(s) => s.to_str()?.parse().into_lua_err()?,
|
||||
Value::UserData(ud) => *ud.borrow::<Self>()?,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use mlua::{ExternalError, ExternalResult, Lua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, Value};
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, Lua, LuaString, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, Value};
|
||||
use yazi_shim::mlua::UserDataFieldsExt;
|
||||
|
||||
use crate::{path::{PathBufDyn, PathLike, StripPrefixError}, strand::{AsStrand, StrandCow}};
|
||||
use crate::{LOG_LEVEL, path::{PathBufDyn, PathLike, StripPrefixError}, strand::{AsStrand, StrandCow}};
|
||||
|
||||
pub type PathRef = UserDataRef<PathBufDyn>;
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ impl PathBufDyn {
|
|||
"Path",
|
||||
lua.create_table_from([(
|
||||
"os",
|
||||
lua.create_function(|_, s: mlua::String| {
|
||||
lua.create_function(|_, s: LuaString| {
|
||||
Ok(Self::from(s.as_bytes().as_strand().as_os_path().into_lua_err()?))
|
||||
})?,
|
||||
)])?,
|
||||
|
|
@ -89,11 +89,17 @@ impl UserData for PathBufDyn {
|
|||
methods.add_method("starts_with", |_, me, base: Value| me.starts_with(base));
|
||||
methods.add_method("strip_prefix", |_, me, base: Value| me.strip_prefix(base));
|
||||
|
||||
methods.add_meta_method(MetaMethod::Concat, |lua, lhs, rhs: mlua::String| {
|
||||
methods.add_meta_method(MetaMethod::Concat, |lua, lhs, rhs: LuaString| {
|
||||
lua.create_external_string([lhs.encoded_bytes(), &rhs.as_bytes()].concat())
|
||||
});
|
||||
methods.add_meta_method(MetaMethod::Eq, |_, me, other: PathRef| Ok(*me == *other));
|
||||
methods
|
||||
.add_meta_method(MetaMethod::ToString, |lua, me, ()| lua.create_string(me.encoded_bytes()));
|
||||
|
||||
if !LOG_LEVEL.get().is_none() {
|
||||
methods.add_meta_function(MetaMethod::ToDebugString, |_, ud: AnyUserData| {
|
||||
Ok(format!("Path({:?}): {:?}", ud.to_pointer(), *ud.borrow::<Self>()?))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use mlua::{AnyUserData, ExternalError, ExternalResult, IntoLua, Lua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, UserDataRegistry, Value};
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, IntoLua, Lua, LuaString, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, UserDataRegistry, Value};
|
||||
use yazi_shim::mlua::UserDataFieldsExt;
|
||||
|
||||
use crate::{path::{PathBufDyn, PathLike, StripPrefixError}, scheme::{SchemeCow, SchemeLike}, strand::{StrandLike, ToStrand}, url::{UrlBuf, UrlBufInventory, UrlCow, UrlLike}};
|
||||
use crate::{LOG_LEVEL, path::{PathBufDyn, PathLike, StripPrefixError}, scheme::{SchemeCow, SchemeLike}, strand::{StrandLike, ToStrand}, url::{UrlBuf, UrlBufInventory, UrlCow, UrlLike}};
|
||||
|
||||
pub type UrlRef = UserDataRef<UrlBuf>;
|
||||
|
||||
|
|
@ -124,17 +124,23 @@ impl UserData for UrlBuf {
|
|||
methods.add_method("starts_with", |_, me, base: Value| me.starts_with(base));
|
||||
methods.add_method("strip_prefix", |_, me, base: Value| me.strip_prefix(base));
|
||||
|
||||
methods.add_function("into_search", |_, (ud, domain): (AnyUserData, mlua::String)| {
|
||||
ud.take::<Self>()?.into_search(domain.to_str()?).into_lua_err()
|
||||
methods.add_method_once("into_search", |_, me, domain: LuaString| {
|
||||
me.into_search(domain.to_str()?).into_lua_err()
|
||||
});
|
||||
|
||||
methods.add_meta_method(MetaMethod::Eq, |_, me, other: UrlRef| Ok(*me == *other));
|
||||
methods.add_meta_method(MetaMethod::ToString, |lua, me, ()| {
|
||||
lua.create_string(me.to_strand().encoded_bytes())
|
||||
});
|
||||
methods.add_meta_method(MetaMethod::Concat, |lua, lhs, rhs: mlua::String| {
|
||||
methods.add_meta_method(MetaMethod::Concat, |lua, lhs, rhs: LuaString| {
|
||||
lua.create_external_string([lhs.to_strand().encoded_bytes(), &rhs.as_bytes()].concat())
|
||||
});
|
||||
|
||||
if !LOG_LEVEL.get().is_none() {
|
||||
methods.add_meta_function(MetaMethod::ToDebugString, |_, ud: AnyUserData| {
|
||||
Ok(format!("Url({:?}): {:?}", ud.to_pointer(), *ud.borrow::<Self>()?))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn register(registry: &mut UserDataRegistry<Self>) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::SerializeOptions;
|
||||
use mlua::serde::SerializeOptions;
|
||||
|
||||
pub const SER_OPT: SerializeOptions =
|
||||
SerializeOptions::new().serialize_none_to_null(false).serialize_unit_to_null(false);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use std::{fmt, ops::Deref};
|
||||
|
||||
use mlua::{FromLua, IntoLua, Lua, Value};
|
||||
use mlua::{FromLua, IntoLua, Lua, LuaString, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ByteString(mlua::String);
|
||||
pub struct ByteString(LuaString);
|
||||
|
||||
impl Deref for ByteString {
|
||||
type Target = mlua::String;
|
||||
type Target = LuaString;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.0 }
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ impl fmt::Display for ByteString {
|
|||
|
||||
impl FromLua for ByteString {
|
||||
fn from_lua(value: Value, lua: &Lua) -> mlua::Result<Self> {
|
||||
Ok(Self(mlua::String::from_lua(value, lua)?))
|
||||
Ok(Self(LuaString::from_lua(value, lua)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ yazi-tty = { path = "../yazi-tty", version = "26.5.9" }
|
|||
anyhow = { workspace = true }
|
||||
base64 = { workspace = true }
|
||||
bitflags = { workspace = true }
|
||||
compact_str = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,41 +1,39 @@
|
|||
use bitflags::bitflags;
|
||||
use compact_str::CompactString;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{ParseError, Result, bail, event::Modifiers};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Serialize)]
|
||||
#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct KeyEvent {
|
||||
#[serde(flatten)]
|
||||
pub code: KeyCode,
|
||||
pub kind: KeyEventKind,
|
||||
pub modifiers: Modifiers,
|
||||
pub state: KeyEventState,
|
||||
#[serde(skip_serializing_if = "CompactString::is_empty")]
|
||||
pub text: CompactString,
|
||||
}
|
||||
|
||||
impl KeyEvent {
|
||||
pub const fn new(code: KeyCode, modifiers: Modifiers) -> Self {
|
||||
Self { code, kind: KeyEventKind::Press, modifiers, state: KeyEventState::empty() }
|
||||
pub fn new(code: KeyCode, modifiers: Modifiers) -> Self {
|
||||
Self { code, modifiers, ..Default::default() }
|
||||
}
|
||||
|
||||
pub fn plain(&self) -> Option<char> {
|
||||
pub fn text<'a>(&'a self, buf: &'a mut [u8; 4]) -> Option<&'a str> {
|
||||
use Modifiers as M;
|
||||
|
||||
match self.code {
|
||||
KeyCode::Char(c) if !self.modifiers.intersects(M::CONTROL | M::ALT | M::SUPER) => Some(c),
|
||||
_ if self.modifiers.intersects(M::CONTROL | M::ALT | M::SUPER) => None,
|
||||
KeyCode::Char(c) if self.text.is_empty() => Some(c.encode_utf8(buf)),
|
||||
KeyCode::Char(_) | KeyCode::Null if !self.text.is_empty() => Some(&self.text),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KeyCode> for KeyEvent {
|
||||
fn from(code: KeyCode) -> Self {
|
||||
Self {
|
||||
code,
|
||||
kind: KeyEventKind::Press,
|
||||
modifiers: Modifiers::empty(),
|
||||
state: KeyEventState::empty(),
|
||||
}
|
||||
}
|
||||
fn from(code: KeyCode) -> Self { Self { code, ..Default::default() } }
|
||||
}
|
||||
|
||||
// --- Kind
|
||||
|
|
@ -116,6 +114,8 @@ pub enum KeyCode {
|
|||
}
|
||||
|
||||
impl KeyCode {
|
||||
pub fn implies_shift(self) -> bool { matches!(self, Self::Char(c) if c.is_uppercase()) }
|
||||
|
||||
pub(crate) fn from_xterm_modifier(r#final: u8) -> Result<Self> {
|
||||
Ok(match r#final {
|
||||
b'A' => Self::Up,
|
||||
|
|
@ -138,6 +138,7 @@ impl KeyCode {
|
|||
}
|
||||
|
||||
let code = match char::from_u32(codepoint).ok_or(ParseError::Invalid)? {
|
||||
'\0' => Self::Null,
|
||||
'\x1B' => Self::Escape,
|
||||
'\r' => Self::Enter,
|
||||
'\t' => Self::Tab,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use std::str::{self, FromStr};
|
||||
|
||||
use compact_str::CompactString;
|
||||
|
||||
use super::parser::Parser;
|
||||
use crate::{ParseError, Result, bail, event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, Modifiers, MouseEvent, MouseEventKind}};
|
||||
|
||||
|
|
@ -84,8 +86,10 @@ impl Parser {
|
|||
|
||||
let (mut code, state_from_keycode) = KeyCode::from_codepoint(parse_next(&mut codepoints)?)?;
|
||||
let (mut modifiers, kind, state_from_modifiers) = parse_mks(&mut it).unwrap_or_default();
|
||||
let text = parse_text(it.next().unwrap_or_default())?;
|
||||
|
||||
if let KeyCode::Modifier(c) = code
|
||||
&& kind != KeyEventKind::Release
|
||||
&& let Some(m) = c.to_modifier()
|
||||
{
|
||||
modifiers |= m;
|
||||
|
|
@ -97,9 +101,10 @@ impl Parser {
|
|||
// which contains the shifted character according to the keyboard layout.
|
||||
if modifiers.contains(Modifiers::SHIFT)
|
||||
&& let Ok(Some(shifted)) = parse_next(&mut codepoints).map(char::from_u32)
|
||||
&& code != KeyCode::Char(shifted)
|
||||
{
|
||||
code = KeyCode::Char(shifted);
|
||||
modifiers.remove(Modifiers::SHIFT);
|
||||
modifiers.set(Modifiers::SHIFT, code.implies_shift());
|
||||
}
|
||||
|
||||
Ok(Event::Key(KeyEvent {
|
||||
|
|
@ -107,6 +112,7 @@ impl Parser {
|
|||
modifiers,
|
||||
kind,
|
||||
state: state_from_keycode | state_from_modifiers,
|
||||
text,
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +129,7 @@ impl Parser {
|
|||
|
||||
let (modifiers, kind, _) = parse_mks(&mut it).unwrap_or_default();
|
||||
let code = KeyCode::from_xterm_modifier(seq[seq.len() - 1])?;
|
||||
Ok(Event::Key(KeyEvent { code, modifiers, kind, state: KeyEventState::empty() }))
|
||||
Ok(Event::Key(KeyEvent { code, modifiers, kind, ..Default::default() }))
|
||||
}
|
||||
|
||||
/// Parses legacy `CSI modifier final` - no semicolon, modifier digit
|
||||
|
|
@ -138,10 +144,9 @@ impl Parser {
|
|||
}
|
||||
|
||||
Ok(Event::Key(KeyEvent {
|
||||
code: KeyCode::from_xterm_modifier(seq[seq.len() - 1])?,
|
||||
code: KeyCode::from_xterm_modifier(seq[seq.len() - 1])?,
|
||||
modifiers: Modifiers::from_vt_mask(modifier - b'0'),
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::empty(),
|
||||
..Default::default()
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +178,7 @@ impl Parser {
|
|||
_ => bail!(),
|
||||
};
|
||||
|
||||
let event = Event::Key(KeyEvent { code, modifiers, kind, state });
|
||||
let event = Event::Key(KeyEvent { code, modifiers, kind, state, ..Default::default() });
|
||||
|
||||
Ok(event)
|
||||
}
|
||||
|
|
@ -277,3 +282,13 @@ where
|
|||
KeyEventState::from_vt_mask(mask),
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_text(s: &str) -> Result<CompactString> {
|
||||
if s.is_empty() {
|
||||
return Ok(CompactString::default());
|
||||
}
|
||||
|
||||
s.split(':')
|
||||
.map(|codepoint| char::from_u32(codepoint.parse()?).ok_or(ParseError::Invalid))
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,13 +51,6 @@ impl Display for RequestCursorBlink {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("\x1b[?12$p") }
|
||||
}
|
||||
|
||||
/// Request keyboard enhancement flags (CSI u query)
|
||||
pub struct RequestKeyboardFlags;
|
||||
|
||||
impl Display for RequestKeyboardFlags {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("\x1b[?u") }
|
||||
}
|
||||
|
||||
/// Device Status Report (DSR)
|
||||
pub struct RequestDeviceStatus;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{io::{self, Write}, ops::Deref};
|
||||
use std::{io, ops::Deref};
|
||||
|
||||
use anyhow::Result;
|
||||
use ratatui_core::{buffer::Buffer, layout::Rect, terminal::{CompletedFrame, Frame, Terminal}};
|
||||
|
|
@ -8,7 +8,7 @@ use yazi_macro::writef;
|
|||
use yazi_proxy::AppProxy;
|
||||
use yazi_shim::cell::SyncCell;
|
||||
use yazi_term::{TERM, event::{Event, KeyEventKind}, stream::EventStream};
|
||||
use yazi_tty::{TTY, TtyWriter, sequence::{DisableBracketedPaste, DisableDrag, DisableDrop, DisableFocusChange, DisableMouseCapture, EnableBracketedPaste, EnableDrag, EnableDrop, EnableFocusChange, EnableMouseCapture, EnterAlternateScreen, If, LeaveAlternateScreen, PopKeyboardFlags, PushKeyboardFlags, RequestCursorBlink, RequestCursorStyle, RequestDA1, RequestKeyboardFlags, RestoreCursorStyle, SetTitle, ShowCursor}};
|
||||
use yazi_tty::{TTY, TtyWriter, sequence::{DisableBracketedPaste, DisableDrag, DisableDrop, DisableFocusChange, DisableMouseCapture, EnableBracketedPaste, EnableDrag, EnableDrop, EnableFocusChange, EnableMouseCapture, EnterAlternateScreen, If, LeaveAlternateScreen, PopKeyboardFlags, PushKeyboardFlags, RequestCursorBlink, RequestCursorStyle, RequestDA1, RestoreCursorStyle, SetTitle, ShowCursor}};
|
||||
|
||||
use crate::{RatermBackend, RatermOption, RatermState};
|
||||
|
||||
|
|
@ -43,9 +43,12 @@ impl Raterm {
|
|||
let opt = RatermOption::default();
|
||||
writef!(
|
||||
TTY.writer(),
|
||||
"{}{RequestCursorStyle}{RequestCursorBlink}{RequestKeyboardFlags}{RequestDA1}{}{EnableBracketedPaste}{EnableFocusChange}{}{}{}",
|
||||
"{}{RequestCursorStyle}{RequestCursorBlink}{RequestDA1}{}{EnableBracketedPaste}{EnableFocusChange}{}{}{}{}",
|
||||
If(!TMUX.get(), EnterAlternateScreen),
|
||||
If(TMUX.get(), EnterAlternateScreen),
|
||||
PushKeyboardFlags::DISAMBIGUATE_ESCAPE_CODES
|
||||
| PushKeyboardFlags::REPORT_ALTERNATE_KEYS
|
||||
| PushKeyboardFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES,
|
||||
EnableDrag(""),
|
||||
EnableDrop(&["text/uri-list"]),
|
||||
If(opt.mouse, EnableMouseCapture),
|
||||
|
|
@ -55,14 +58,6 @@ impl Raterm {
|
|||
Mux::tmux_drain()?;
|
||||
|
||||
STATE.set(RatermState::new(&resp, &opt));
|
||||
if STATE.get().csi_u {
|
||||
write!(
|
||||
TTY.writer(),
|
||||
"{}",
|
||||
PushKeyboardFlags::DISAMBIGUATE_ESCAPE_CODES | PushKeyboardFlags::REPORT_ALTERNATE_KEYS,
|
||||
)?;
|
||||
}
|
||||
|
||||
let mut term = Self {
|
||||
inner: Terminal::new(RatermBackend::new(TTY.writer()))?,
|
||||
stream: EventStream::from(&*TERM),
|
||||
|
|
@ -82,9 +77,8 @@ impl Raterm {
|
|||
|
||||
_ = writef!(
|
||||
TTY.writer(),
|
||||
"{}{DisableDrop}{DisableDrag}{}{}{}{DisableFocusChange}{DisableBracketedPaste}{LeaveAlternateScreen}{ShowCursor}",
|
||||
"{}{PopKeyboardFlags}{DisableDrop}{DisableDrag}{}{}{DisableFocusChange}{DisableBracketedPaste}{LeaveAlternateScreen}{ShowCursor}",
|
||||
If(state.mouse, DisableMouseCapture),
|
||||
If(state.csi_u, PopKeyboardFlags),
|
||||
RestoreCursorStyle { shape: state.cursor_shape, blink: state.cursor_blink },
|
||||
If(state.title, SetTitle("")),
|
||||
);
|
||||
|
|
@ -100,7 +94,7 @@ impl Raterm {
|
|||
loop {
|
||||
match rx.recv().await {
|
||||
Some(Ok(event)) => match event {
|
||||
Event::Key(key) if key.kind != KeyEventKind::Press => continue,
|
||||
Event::Key(key) if key.kind == KeyEventKind::Release => continue,
|
||||
Event::Mouse(mouse) if !YAZI.mgr.mouse_events.get().contains(mouse.kind.into()) => {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use crate::RatermOption;
|
|||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RatermState {
|
||||
pub csi_u: bool,
|
||||
pub mouse: bool,
|
||||
pub title: bool,
|
||||
pub cursor_shape: u8,
|
||||
|
|
@ -11,18 +10,10 @@ pub struct RatermState {
|
|||
|
||||
impl RatermState {
|
||||
pub(super) const fn default() -> Self {
|
||||
Self {
|
||||
csi_u: false,
|
||||
mouse: false,
|
||||
title: false,
|
||||
cursor_shape: 0,
|
||||
cursor_blink: false,
|
||||
}
|
||||
Self { mouse: false, title: false, cursor_shape: 0, cursor_blink: false }
|
||||
}
|
||||
|
||||
pub(super) fn new(resp: &str, opt: &RatermOption) -> Self {
|
||||
let csi_u = resp.contains("\x1b[?0u");
|
||||
|
||||
let cursor_shape = resp
|
||||
.split_once("\x1bP1$r")
|
||||
.and_then(|(_, s)| s.bytes().next())
|
||||
|
|
@ -31,6 +22,6 @@ impl RatermState {
|
|||
|
||||
let cursor_blink = resp.contains("\x1b[?12;1$y");
|
||||
|
||||
Self { csi_u, mouse: opt.mouse, title: false, cursor_shape, cursor_blink }
|
||||
Self { mouse: opt.mouse, title: false, cursor_shape, cursor_blink }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{IntoLuaMulti, UserData, UserDataMethods, Value};
|
||||
use mlua::{IntoLuaMulti, LuaString, UserData, UserDataMethods, Value};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use yazi_binding::Error;
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ impl UserData for RwFile {
|
|||
Err(e) => (Value::Nil, Error::Io(e)).into_lua_multi(&lua),
|
||||
}
|
||||
});
|
||||
methods.add_async_method_mut("write_all", |lua, mut me, src: mlua::String| async move {
|
||||
methods.add_async_method_mut("write_all", |lua, mut me, src: LuaString| async move {
|
||||
match me.write_all(&src.as_bytes()).await {
|
||||
Ok(()) => true.into_lua_multi(&lua),
|
||||
Err(e) => (false, Error::Io(e)).into_lua_multi(&lua),
|
||||
|
|
|
|||
|
|
@ -6,14 +6,15 @@ use yazi_term::event::KeyEvent;
|
|||
use crate::input::{Input, InputMode};
|
||||
|
||||
impl Input {
|
||||
pub fn r#type(&mut self, key: KeyEvent) -> Result<bool> {
|
||||
let Some(c) = key.plain() else { return Ok(false) };
|
||||
pub fn r#type(&mut self, key: &KeyEvent) -> Result<bool> {
|
||||
let mut buf = [0; 4];
|
||||
let Some(text) = key.text(&mut buf) else { return Ok(false) };
|
||||
|
||||
if self.mode() == InputMode::Insert {
|
||||
self.type_str(c.encode_utf8(&mut [0; 4]))?;
|
||||
self.type_str(text)?;
|
||||
return Ok(true);
|
||||
} else if self.mode() == InputMode::Replace {
|
||||
self.replace_str(c.encode_utf8(&mut [0; 4]))?;
|
||||
self.replace_str(text)?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue