mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
Merge branch 'main' into main
This commit is contained in:
commit
b1787d7771
138 changed files with 1618 additions and 986 deletions
|
|
@ -11,3 +11,6 @@ JEMALLOC_SYS_WITH_LG_PAGE = "16"
|
|||
#
|
||||
# Improve memory efficiency by reducing fragmentation and ensuring all threads allocate from the same pool
|
||||
JEMALLOC_SYS_WITH_MALLOC_CONF = "narenas:1"
|
||||
|
||||
[target.aarch64-apple-darwin]
|
||||
rustflags = [ "-Ctarget-cpu=apple-m1" ]
|
||||
|
|
|
|||
284
Cargo.lock
generated
284
Cargo.lock
generated
|
|
@ -273,9 +273,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.11.3"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0"
|
||||
checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
|
|
@ -328,9 +328,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.17"
|
||||
version = "1.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
|
||||
checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
|
|
@ -367,9 +367,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.34"
|
||||
version = "4.5.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff"
|
||||
checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -377,9 +377,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.34"
|
||||
version = "4.5.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489"
|
||||
checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
|
@ -507,9 +507,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.14"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471"
|
||||
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
|
@ -552,7 +552,7 @@ dependencies = [
|
|||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"rustix",
|
||||
"rustix 0.38.44",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
|
|
@ -585,9 +585,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
|
|
@ -595,9 +595,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.10"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
|
|
@ -609,9 +609,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.10"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
|
|
@ -620,9 +620,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.4.1"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058"
|
||||
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
|
@ -725,9 +725,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.10"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
||||
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
|
|
@ -809,9 +809,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
|
||||
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
|
|
@ -945,7 +945,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasi 0.14.2+wasi-0.2.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -979,9 +991,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.5.0"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1"
|
||||
checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
|
|
@ -1006,9 +1018,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.62"
|
||||
version = "0.1.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127"
|
||||
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
|
|
@ -1016,7 +1028,7 @@ dependencies = [
|
|||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core 0.52.0",
|
||||
"windows-core 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1073,9 +1085,9 @@ checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408"
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.8.0"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
|
||||
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
|
|
@ -1164,10 +1176,11 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
|||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
||||
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
|
||||
dependencies = [
|
||||
"getrandom 0.3.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
|
@ -1246,6 +1259,12 @@ version = "0.4.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.12"
|
||||
|
|
@ -1359,9 +1378,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.5"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"simd-adler32",
|
||||
|
|
@ -1375,7 +1394,7 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
|
|
@ -1603,9 +1622,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.1"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "onig"
|
||||
|
|
@ -1833,6 +1852,12 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
|
|
@ -1860,7 +1885,7 @@ version = "0.6.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.2.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1945,9 +1970,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.10"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
|
||||
checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
]
|
||||
|
|
@ -1958,7 +1983,7 @@ version = "0.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.2.15",
|
||||
"libredox",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
|
@ -2043,7 +2068,20 @@ dependencies = [
|
|||
"bitflags 2.9.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.4",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
|
|
@ -2220,9 +2258,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.14.0"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
|
||||
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
|
||||
|
||||
[[package]]
|
||||
name = "smawk"
|
||||
|
|
@ -2232,9 +2270,9 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
|
|||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.8"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
|
||||
checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
|
|
@ -2441,9 +2479,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.44.1"
|
||||
version = "1.44.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a"
|
||||
checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
|
|
@ -2720,9 +2758,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
|||
|
||||
[[package]]
|
||||
name = "vergen"
|
||||
version = "9.0.4"
|
||||
version = "9.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0d2f179f8075b805a43a2a21728a46f0cc2921b3c58695b28fa8817e103cd9a"
|
||||
checksum = "6b2bf58be11fc9414104c6d3a2e464163db5ef74b12296bda593cac37b6e4777"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"derive_builder",
|
||||
|
|
@ -2734,9 +2772,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "vergen-gitcl"
|
||||
version = "1.0.5"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2f89d70a58a4506a6079cedf575c64cf51649ccbb4e02a63dac539b264b7711"
|
||||
checksum = "92ee058141ff0fab661d1e2837d1cf0fe1ac6173cf46224e25cec21e780eb5cc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"derive_builder",
|
||||
|
|
@ -2785,6 +2823,15 @@ version = "0.11.0+wasi-snapshot-preview1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.14.2+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
||||
dependencies = [
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
|
|
@ -2851,13 +2898,13 @@ checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
|
|||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "7.0.2"
|
||||
version = "7.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2774c861e1f072b3aadc02f8ba886c26ad6321567ecc294c935434cad06f1283"
|
||||
checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762"
|
||||
dependencies = [
|
||||
"either",
|
||||
"env_home",
|
||||
"rustix",
|
||||
"rustix 1.0.5",
|
||||
"winsafe",
|
||||
]
|
||||
|
||||
|
|
@ -2904,23 +2951,27 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
version = "0.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6"
|
||||
dependencies = [
|
||||
"windows-implement 0.56.0",
|
||||
"windows-interface 0.56.0",
|
||||
"windows-result 0.1.2",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.56.0"
|
||||
version = "0.61.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6"
|
||||
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-targets",
|
||||
"windows-implement 0.60.0",
|
||||
"windows-interface 0.59.1",
|
||||
"windows-link",
|
||||
"windows-result 0.3.2",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2934,6 +2985,17 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.56.0"
|
||||
|
|
@ -2945,6 +3007,17 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.1"
|
||||
|
|
@ -2960,6 +3033,24 @@ dependencies = [
|
|||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
|
|
@ -3044,9 +3135,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.4"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36"
|
||||
checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
|
@ -3057,9 +3148,18 @@ version = "0.0.19"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi-adapter"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"ansi-to-tui",
|
||||
"anyhow",
|
||||
|
|
@ -3076,9 +3176,21 @@ dependencies = [
|
|||
"yazi-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi-binding"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"mlua",
|
||||
"paste",
|
||||
"serde_json",
|
||||
"yazi-fs",
|
||||
"yazi-macro",
|
||||
"yazi-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi-boot"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
|
|
@ -3096,7 +3208,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-cli"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
|
|
@ -3119,7 +3231,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-codegen"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
|
|
@ -3127,7 +3239,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-config"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.9.0",
|
||||
|
|
@ -3147,7 +3259,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-core"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.9.0",
|
||||
|
|
@ -3182,7 +3294,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-dds"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"mlua",
|
||||
|
|
@ -3195,6 +3307,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"uzers",
|
||||
"vergen-gitcl",
|
||||
"yazi-binding",
|
||||
"yazi-boot",
|
||||
"yazi-fs",
|
||||
"yazi-macro",
|
||||
|
|
@ -3203,7 +3316,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-ffi"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"core-foundation-sys",
|
||||
|
|
@ -3214,16 +3327,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-fm"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"better-panic",
|
||||
"crossterm",
|
||||
"fdlimit",
|
||||
"foldhash",
|
||||
"futures",
|
||||
"indexmap",
|
||||
"libc",
|
||||
"mlua",
|
||||
"paste",
|
||||
"ratatui",
|
||||
"scopeguard",
|
||||
"signal-hook-tokio",
|
||||
|
|
@ -3235,6 +3350,7 @@ dependencies = [
|
|||
"tracing-appender",
|
||||
"tracing-subscriber",
|
||||
"yazi-adapter",
|
||||
"yazi-binding",
|
||||
"yazi-boot",
|
||||
"yazi-codegen",
|
||||
"yazi-config",
|
||||
|
|
@ -3250,7 +3366,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-fs"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
|
|
@ -3276,11 +3392,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-macro"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
|
||||
[[package]]
|
||||
name = "yazi-plugin"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"ansi-to-tui",
|
||||
"anyhow",
|
||||
|
|
@ -3289,9 +3405,11 @@ dependencies = [
|
|||
"crossterm",
|
||||
"futures",
|
||||
"globset",
|
||||
"libc",
|
||||
"md-5",
|
||||
"mlua",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
"ratatui",
|
||||
"serde_json",
|
||||
"syntect",
|
||||
|
|
@ -3302,7 +3420,9 @@ dependencies = [
|
|||
"twox-hash",
|
||||
"unicode-width 0.2.0",
|
||||
"uzers",
|
||||
"windows-sys 0.59.0",
|
||||
"yazi-adapter",
|
||||
"yazi-binding",
|
||||
"yazi-boot",
|
||||
"yazi-config",
|
||||
"yazi-dds",
|
||||
|
|
@ -3321,7 +3441,7 @@ checksum = "33232d9116df6415ddfcdf72701b1b7439ce87f240a14723e8dd5d17e7ed5f98"
|
|||
|
||||
[[package]]
|
||||
name = "yazi-proxy"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"mlua",
|
||||
|
|
@ -3334,7 +3454,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-scheduler"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-priority-channel",
|
||||
|
|
@ -3357,7 +3477,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-shared"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"crossterm",
|
||||
|
|
@ -3377,7 +3497,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yazi-widgets"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"ratatui",
|
||||
|
|
|
|||
|
|
@ -18,27 +18,28 @@ ansi-to-tui = "7.0.0"
|
|||
anyhow = "1.0.97"
|
||||
base64 = "0.22.1"
|
||||
bitflags = "2.9.0"
|
||||
clap = { version = "4.5.34", features = [ "derive" ] }
|
||||
clap = { version = "4.5.35", features = [ "derive" ] }
|
||||
core-foundation-sys = "0.8.7"
|
||||
crossterm = { version = "0.28.1", features = [ "event-stream" ] }
|
||||
dirs = "6.0.0"
|
||||
foldhash = "0.1.5"
|
||||
futures = "0.3.31"
|
||||
globset = "0.4.16"
|
||||
indexmap = { version = "2.8.0", features = [ "serde" ] }
|
||||
indexmap = { version = "2.9.0", features = [ "serde" ] }
|
||||
libc = "0.2.171"
|
||||
lru = "0.13.0"
|
||||
md-5 = "0.10.6"
|
||||
mlua = { version = "0.10.3", features = [ "anyhow", "async", "error-send", "lua54", "macros", "serialize" ] }
|
||||
objc = "0.2.7"
|
||||
parking_lot = "0.12.3"
|
||||
paste = "1.0.15"
|
||||
ratatui = { version = "0.29.0", features = [ "unstable-rendered-line-info" ] }
|
||||
regex = "1.11.1"
|
||||
scopeguard = "1.2.0"
|
||||
serde = { version = "1.0.219", features = [ "derive" ] }
|
||||
serde_json = "1.0.140"
|
||||
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
||||
tokio = { version = "1.44.1", features = [ "full" ] }
|
||||
tokio = { version = "1.44.2", features = [ "full" ] }
|
||||
tokio-stream = "0.1.17"
|
||||
tokio-util = "0.7.14"
|
||||
toml = { version = "0.8.20" }
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ Yazi is currently in heavy development, expect breaking changes.
|
|||
| [Ghostty](https://github.com/ghostty-org/ghostty) | [Kitty unicode placeholders][kgp] | ✅ Built-in |
|
||||
| [Windows Terminal](https://github.com/microsoft/terminal) (>= v1.22.10352.0) | [Sixel graphics format][sixel] | ✅ Built-in |
|
||||
| [st with Sixel patch](https://github.com/bakkeby/st-flexipatch) | [Sixel graphics format][sixel] | ✅ Built-in |
|
||||
| [Warp](https://www.warp.dev) | [Inline images protocol][iip] | ✅ Built-in |
|
||||
| [Tabby](https://github.com/Eugeny/tabby) | [Inline images protocol][iip] | ✅ Built-in |
|
||||
| [VSCode](https://github.com/microsoft/vscode) | [Inline images protocol][iip] | ✅ Built-in |
|
||||
| [Rio](https://github.com/raphamorim/rio) | [Inline images protocol][iip] | ❌ Rio doesn't correctly clear images [#709][rio-bug] |
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
export ARTIFACT_NAME="yazi-$1"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd $SCRIPT_DIR/..
|
||||
cd "$SCRIPT_DIR/.."
|
||||
|
||||
echo "Bumping version: $1"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
cargo publish -p yazi-macro && sleep 30
|
||||
cargo publish -p yazi-codegen && sleep 30
|
||||
cargo publish -p yazi-shared && sleep 30
|
||||
|
|
@ -7,9 +9,11 @@ cargo publish -p yazi-config && sleep 30
|
|||
cargo publish -p yazi-proxy && sleep 30
|
||||
cargo publish -p yazi-adapter && sleep 30
|
||||
cargo publish -p yazi-boot && sleep 30
|
||||
cargo publish -p yazi-binding && sleep 30
|
||||
cargo publish -p yazi-dds && sleep 30
|
||||
cargo publish -p yazi-scheduler && sleep 30
|
||||
cargo publish -p yazi-plugin && sleep 30
|
||||
cargo publish -p yazi-widgets && sleep 30
|
||||
cargo publish -p yazi-core && sleep 30
|
||||
cargo publish -p yazi-fm && sleep 30
|
||||
cargo publish -p yazi-cli
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const RE_DEPENDENCIES = /Dependencies\s+[/a-z]+\s*:\s/gm
|
|||
const RE_CHECKLIST = /#{3}\s+Checklist\s+(?:^-\s+\[x]\s+.+?(?:\n|\r\n|$)){2}/gm
|
||||
|
||||
function bugReportBody(creator, content, hash) {
|
||||
if (RE_DEPENDENCIES.test(content) && RE_CHECKLIST.test(content) && new RegExp(` \\(${hash}[a-z]? `).test(content)) {
|
||||
if (RE_DEPENDENCIES.test(content) && RE_CHECKLIST.test(content) && new RegExp(` \\(${hash}[a-f0-9]? `).test(content)) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-adapter"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
@ -9,9 +9,9 @@ homepage = "https://yazi-rs.github.io"
|
|||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[dependencies]
|
||||
yazi-config = { path = "../yazi-config", version = "25.3.7" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.4.8" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
ansi-to-tui = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -109,8 +109,9 @@ impl Adapter {
|
|||
if env_exists("WAYLAND_DISPLAY") {
|
||||
return if supported_compositor { Self::Wayland } else { Self::Chafa };
|
||||
}
|
||||
if env_exists("DISPLAY") {
|
||||
return Self::X11;
|
||||
match env::var("DISPLAY").unwrap_or_default().as_str() {
|
||||
s if !s.is_empty() && !s.contains("/org.xquartz") => return Self::X11,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
warn!("[Adapter] Falling back to chafa");
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ impl Brand {
|
|||
B::Foot => &[A::Sixel],
|
||||
B::Ghostty => &[A::Kgp],
|
||||
B::Microsoft => &[A::Sixel],
|
||||
B::Warp => &[],
|
||||
B::Warp => &[A::Iip, A::KgpOld],
|
||||
B::Rio => &[A::Iip, A::Sixel],
|
||||
B::BlackBox => &[A::Sixel],
|
||||
B::VSCode => &[A::Iip, A::Sixel],
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ impl Unknown {
|
|||
use Adapter as A;
|
||||
|
||||
match (self.kgp, self.sixel) {
|
||||
(true, true) => &[A::Kgp, A::Sixel],
|
||||
(true, false) => &[A::Kgp],
|
||||
(true, true) => &[A::Sixel, A::KgpOld],
|
||||
(true, false) => &[A::KgpOld],
|
||||
(false, true) => &[A::Sixel],
|
||||
(false, false) => &[],
|
||||
}
|
||||
|
|
|
|||
19
yazi-binding/Cargo.toml
Normal file
19
yazi-binding/Cargo.toml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "yazi-binding"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
description = "Yazi Lua bindings"
|
||||
homepage = "https://yazi-rs.github.io"
|
||||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[dependencies]
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.4.8" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
mlua = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
3
yazi-binding/src/lib.rs
Normal file
3
yazi-binding/src/lib.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
mod macros;
|
||||
|
||||
yazi_macro::mod_flat!(error stage url);
|
||||
19
yazi-binding/src/macros.rs
Normal file
19
yazi-binding/src/macros.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#[macro_export]
|
||||
macro_rules! cached_field {
|
||||
($fields:ident, $key:ident, $value:expr) => {
|
||||
$fields.add_field_function_get(stringify!($key), |lua, ud| {
|
||||
use mlua::IntoLua;
|
||||
ud.borrow_mut_scoped::<Self, mlua::Result<mlua::Value>>(|me| {
|
||||
match paste::paste! { &me.[<v_ $key>] } {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => {
|
||||
let v: mlua::Result<_> = $value(lua, me);
|
||||
let v = v?.into_lua(lua)?;
|
||||
paste::paste! { me.[<v_ $key>] = Some(v.clone()) };
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
})?
|
||||
});
|
||||
};
|
||||
}
|
||||
21
yazi-binding/src/stage.rs
Normal file
21
yazi-binding/src/stage.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
use mlua::{IntoLuaMulti, MetaMethod, UserData, UserDataMethods};
|
||||
|
||||
pub struct FolderStage(yazi_fs::FolderStage);
|
||||
|
||||
impl FolderStage {
|
||||
pub fn new(inner: yazi_fs::FolderStage) -> Self { Self(inner) }
|
||||
}
|
||||
|
||||
impl UserData for FolderStage {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::Call, |lua, me, ()| {
|
||||
use yazi_fs::FolderStage::*;
|
||||
|
||||
match me.0 {
|
||||
Loading => false.into_lua_multi(lua),
|
||||
Loaded => true.into_lua_multi(lua),
|
||||
Failed(kind) => (true, crate::Error::IoKind(kind)).into_lua_multi(lua),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
141
yazi-binding/src/url.rs
Normal file
141
yazi-binding/src/url.rs
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
use std::{ops::Deref, path::Path};
|
||||
|
||||
use mlua::{AnyUserData, ExternalError, FromLua, Lua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, Value};
|
||||
|
||||
use crate::cached_field;
|
||||
|
||||
pub type UrlRef = UserDataRef<Url>;
|
||||
|
||||
pub struct Url {
|
||||
inner: yazi_shared::url::Url,
|
||||
|
||||
v_name: Option<Value>,
|
||||
v_stem: Option<Value>,
|
||||
v_ext: Option<Value>,
|
||||
v_base: Option<Value>,
|
||||
v_parent: Option<Value>,
|
||||
v_frag: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Url {
|
||||
type Target = yazi_shared::url::Url;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl AsRef<Path> for Url {
|
||||
fn as_ref(&self) -> &Path { self.inner.as_path() }
|
||||
}
|
||||
|
||||
impl From<Url> for yazi_shared::url::Url {
|
||||
fn from(value: Url) -> Self { value.inner }
|
||||
}
|
||||
|
||||
impl Url {
|
||||
pub fn new(url: impl Into<yazi_shared::url::Url>) -> Self {
|
||||
Self {
|
||||
inner: url.into(),
|
||||
|
||||
v_name: None,
|
||||
v_stem: None,
|
||||
v_ext: None,
|
||||
v_base: None,
|
||||
v_parent: None,
|
||||
v_frag: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.globals().raw_set(
|
||||
"Url",
|
||||
lua.create_function(|_, value: Value| {
|
||||
Ok(match value {
|
||||
Value::String(s) => Self::new(s.to_str()?.as_ref()),
|
||||
Value::UserData(ud) => Self::new(ud.borrow::<Self>()?.inner.clone()),
|
||||
_ => Err("Expected a string or a Url".into_lua_err())?,
|
||||
})
|
||||
})?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for Url {
|
||||
fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
|
||||
Ok(match value {
|
||||
Value::UserData(ud) => Self::new(ud.take::<Self>()?.inner),
|
||||
_ => Err("Expected a Url".into_lua_err())?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Url {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
cached_field!(fields, name, |lua: &Lua, me: &Self| {
|
||||
Some(me.name())
|
||||
.filter(|&s| !s.is_empty())
|
||||
.map(|s| lua.create_string(s.as_encoded_bytes()))
|
||||
.transpose()
|
||||
});
|
||||
cached_field!(fields, stem, |lua: &Lua, me: &Self| {
|
||||
me.file_stem().map(|s| lua.create_string(s.as_encoded_bytes())).transpose()
|
||||
});
|
||||
cached_field!(fields, ext, |lua: &Lua, me: &Self| {
|
||||
me.extension().map(|s| lua.create_string(s.as_encoded_bytes())).transpose()
|
||||
});
|
||||
cached_field!(fields, parent, |_, me: &Self| Ok(me.parent_url().map(Self::new)));
|
||||
cached_field!(fields, base, |_, me: &Self| {
|
||||
Ok(if me.base().as_os_str().is_empty() { None } else { Some(Self::new(me.base())) })
|
||||
});
|
||||
cached_field!(fields, frag, |lua: &Lua, me: &Self| lua.create_string(me.frag()));
|
||||
|
||||
fields.add_field_method_get("is_regular", |_, me| Ok(me.is_regular()));
|
||||
fields.add_field_method_get("is_search", |_, me| Ok(me.is_search()));
|
||||
fields.add_field_method_get("is_archive", |_, me| Ok(me.is_archive()));
|
||||
fields.add_field_method_get("is_absolute", |_, me| Ok(me.is_absolute()));
|
||||
fields.add_field_method_get("has_root", |_, me| Ok(me.has_root()));
|
||||
}
|
||||
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_method("join", |_, me, other: Value| {
|
||||
Ok(Self::new(match other {
|
||||
Value::String(s) => me.join(s.to_str()?.as_ref()),
|
||||
Value::UserData(ud) => me.join(&ud.borrow::<Self>()?.inner),
|
||||
_ => Err("must be a string or a Url".into_lua_err())?,
|
||||
}))
|
||||
});
|
||||
methods.add_method("starts_with", |_, me, base: Value| {
|
||||
Ok(match base {
|
||||
Value::String(s) => me.starts_with(s.to_str()?.as_ref()),
|
||||
Value::UserData(ud) => me.starts_with(&ud.borrow::<Self>()?.inner),
|
||||
_ => Err("must be a string or a Url".into_lua_err())?,
|
||||
})
|
||||
});
|
||||
methods.add_method("ends_with", |_, me, child: Value| {
|
||||
Ok(match child {
|
||||
Value::String(s) => me.ends_with(s.to_str()?.as_ref()),
|
||||
Value::UserData(ud) => me.ends_with(&ud.borrow::<Self>()?.inner),
|
||||
_ => Err("must be a string or a Url".into_lua_err())?,
|
||||
})
|
||||
});
|
||||
methods.add_method("strip_prefix", |_, me, base: Value| {
|
||||
let path = match base {
|
||||
Value::String(s) => me.strip_prefix(s.to_str()?.as_ref()),
|
||||
Value::UserData(ud) => me.strip_prefix(&ud.borrow::<Self>()?.inner),
|
||||
_ => Err("must be a string or a Url".into_lua_err())?,
|
||||
};
|
||||
Ok(path.ok().map(Self::new))
|
||||
});
|
||||
|
||||
methods.add_function_mut("into_search", |_, (ud, frag): (AnyUserData, mlua::String)| {
|
||||
Ok(Self::new(ud.take::<Self>()?.inner.into_search(&frag.to_str()?)))
|
||||
});
|
||||
|
||||
methods.add_meta_method(MetaMethod::Eq, |_, me, other: UrlRef| Ok(me.inner == other.inner));
|
||||
methods.add_meta_method(MetaMethod::ToString, |lua, me, ()| {
|
||||
lua.create_string(me.as_os_str().as_encoded_bytes())
|
||||
});
|
||||
methods.add_meta_method(MetaMethod::Concat, |lua, lhs, rhs: mlua::String| {
|
||||
lua.create_string([lhs.as_os_str().as_encoded_bytes(), rhs.as_bytes().as_ref()].concat())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-boot"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
@ -9,11 +9,11 @@ homepage = "https://yazi-rs.github.io"
|
|||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[dependencies]
|
||||
yazi-adapter = { path = "../yazi-adapter", version = "25.3.7" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.3.7" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.3.7" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-adapter = { path = "../yazi-adapter", version = "25.4.8" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.4.8" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.4.8" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
clap = { workspace = true }
|
||||
|
|
@ -21,11 +21,11 @@ regex = { workspace = true }
|
|||
serde = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
clap = { workspace = true }
|
||||
clap_complete = "4.5.47"
|
||||
clap_complete_fig = "4.5.2"
|
||||
clap_complete_nushell = "4.5.5"
|
||||
vergen-gitcl = { version = "1.0.5", features = [ "build", "rustc" ] }
|
||||
vergen-gitcl = { version = "1.0.7", features = [ "build", "rustc" ] }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-cli"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
@ -9,11 +9,11 @@ homepage = "https://yazi-rs.github.io"
|
|||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[dependencies]
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.3.7" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.3.7" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.3.7" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.4.8" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.4.8" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.4.8" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
|
|
@ -26,7 +26,7 @@ toml = { workspace = true }
|
|||
twox-hash = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
|
||||
# External build dependencies
|
||||
anyhow = { workspace = true }
|
||||
|
|
@ -35,7 +35,7 @@ clap_complete = "4.5.47"
|
|||
clap_complete_fig = "4.5.2"
|
||||
clap_complete_nushell = "4.5.5"
|
||||
serde_json = { workspace = true }
|
||||
vergen-gitcl = { version = "1.0.5", features = [ "build" ] }
|
||||
vergen-gitcl = { version = "1.0.7", features = [ "build" ] }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
crossterm = { workspace = true, features = [ "use-dev-tty", "libc" ] }
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ impl Dependency {
|
|||
self.header("Upgrading package `{name}`")?;
|
||||
|
||||
let path = self.local();
|
||||
if !must_exists(&path).await {
|
||||
Git::clone(&self.remote(), &path).await?;
|
||||
} else {
|
||||
if must_exists(&path).await {
|
||||
Git::pull(&path).await?;
|
||||
} else {
|
||||
Git::clone(&self.remote(), &path).await?;
|
||||
};
|
||||
|
||||
self.rev = Git::hash(&path).await?;
|
||||
self.rev = Git::revision(&path).await?;
|
||||
self.deploy().await
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::{Context, Result, bail};
|
||||
use anyhow::{Context, Result};
|
||||
use tokio::fs;
|
||||
use yazi_fs::{maybe_exists, ok_or_not_found, remove_dir_clean, remove_sealed};
|
||||
use yazi_macro::outln;
|
||||
|
|
@ -14,36 +14,9 @@ impl Dependency {
|
|||
return Ok(outln!("Not found, skipping")?);
|
||||
}
|
||||
|
||||
if self.hash != self.hash().await? {
|
||||
bail!(
|
||||
"You have modified the contents of the `{}` {}. For safety, the operation has been aborted.
|
||||
Please manually delete it from: {}",
|
||||
self.name,
|
||||
if self.is_flavor { "flavor" } else { "plugin" },
|
||||
dir.display()
|
||||
);
|
||||
}
|
||||
|
||||
let files = if self.is_flavor {
|
||||
&["flavor.toml", "tmtheme.xml", "README.md", "preview.png", "LICENSE", "LICENSE-tmtheme"][..]
|
||||
} else {
|
||||
&["main.lua", "README.md", "LICENSE"][..]
|
||||
};
|
||||
for p in files.iter().map(|&f| dir.join(f)) {
|
||||
ok_or_not_found(remove_sealed(&p).await)
|
||||
.with_context(|| format!("failed to delete `{}`", p.display()))?;
|
||||
}
|
||||
|
||||
self.hash_check().await?;
|
||||
self.delete_assets().await?;
|
||||
if ok_or_not_found(fs::remove_dir(&dir).await).is_ok() {
|
||||
outln!("Done!")?;
|
||||
} else {
|
||||
outln!(
|
||||
"Done!
|
||||
For safety, user data has been preserved, please manually delete them within: {}",
|
||||
dir.display()
|
||||
)?;
|
||||
}
|
||||
self.delete_sources().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -65,4 +38,29 @@ For safety, user data has been preserved, please manually delete them within: {}
|
|||
remove_dir_clean(&assets).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) async fn delete_sources(&self) -> Result<()> {
|
||||
let dir = self.target();
|
||||
let files = if self.is_flavor {
|
||||
&["flavor.toml", "tmtheme.xml", "README.md", "preview.png", "LICENSE", "LICENSE-tmtheme"][..]
|
||||
} else {
|
||||
&["main.lua", "README.md", "LICENSE"][..]
|
||||
};
|
||||
|
||||
for p in files.iter().map(|&f| dir.join(f)) {
|
||||
ok_or_not_found(remove_sealed(&p).await)
|
||||
.with_context(|| format!("failed to delete `{}`", p.display()))?;
|
||||
}
|
||||
|
||||
if ok_or_not_found(fs::remove_dir(&dir).await).is_ok() {
|
||||
outln!("Done!")?;
|
||||
} else {
|
||||
outln!(
|
||||
"Done!
|
||||
For safety, user data has been preserved, please manually delete them within: {}",
|
||||
dir.display()
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::{Context, Result, bail};
|
||||
use anyhow::{Context, Result};
|
||||
use tokio::fs;
|
||||
use yazi_fs::{copy_and_seal, maybe_exists, remove_dir_clean};
|
||||
use yazi_macro::outln;
|
||||
|
|
@ -15,44 +15,27 @@ impl Dependency {
|
|||
self.is_flavor = maybe_exists(&from.join("flavor.toml")).await;
|
||||
|
||||
let to = self.target();
|
||||
if maybe_exists(&to).await && self.hash != self.hash().await? {
|
||||
bail!(
|
||||
"You have modified the contents of the `{}` {}. For safety, the operation has been aborted.
|
||||
Please manually delete it from `{}` and re-run the command.",
|
||||
self.name,
|
||||
if self.is_flavor { "flavor" } else { "plugin" },
|
||||
to.display()
|
||||
);
|
||||
let exists = maybe_exists(&to).await;
|
||||
if exists {
|
||||
self.hash_check().await?;
|
||||
}
|
||||
|
||||
fs::create_dir_all(&to).await?;
|
||||
if let Err(e) = Self::deploy_sources(&from, &to, self.is_flavor).await {
|
||||
remove_dir_clean(&to).await;
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
self.delete_assets().await?;
|
||||
Self::deploy_assets(from.join("assets"), to.join("assets")).await?;
|
||||
|
||||
self.hash = self.hash().await?;
|
||||
outln!("Done!")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn deploy_sources(from: &Path, to: &Path, is_flavor: bool) -> Result<()> {
|
||||
let files = if is_flavor {
|
||||
&["flavor.toml", "tmtheme.xml", "README.md", "preview.png", "LICENSE", "LICENSE-tmtheme"][..]
|
||||
} else {
|
||||
&["main.lua", "README.md", "LICENSE"][..]
|
||||
};
|
||||
|
||||
for file in files {
|
||||
let (from, to) = (from.join(file), to.join(file));
|
||||
copy_and_seal(&from, &to)
|
||||
.await
|
||||
.with_context(|| format!("failed to copy `{}` to `{}`", from.display(), to.display()))?;
|
||||
let res1 = Self::deploy_assets(from.join("assets"), to.join("assets")).await;
|
||||
let res2 = Self::deploy_sources(&from, &to, self.is_flavor).await;
|
||||
if !exists && (res2.is_err() || res1.is_err()) {
|
||||
self.delete_assets().await?;
|
||||
self.delete_sources().await?;
|
||||
}
|
||||
|
||||
remove_dir_clean(&to).await;
|
||||
self.hash = self.hash().await?;
|
||||
res2?;
|
||||
res1?;
|
||||
|
||||
outln!("Done!")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -72,4 +55,20 @@ Please manually delete it from `{}` and re-run the command.",
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn deploy_sources(from: &Path, to: &Path, is_flavor: bool) -> Result<()> {
|
||||
let files = if is_flavor {
|
||||
&["flavor.toml", "tmtheme.xml", "README.md", "preview.png", "LICENSE", "LICENSE-tmtheme"][..]
|
||||
} else {
|
||||
&["main.lua", "README.md", "LICENSE"][..]
|
||||
};
|
||||
|
||||
for file in files {
|
||||
let (from, to) = (from.join(file), to.join(file));
|
||||
copy_and_seal(&from, &to)
|
||||
.await
|
||||
.with_context(|| format!("failed to copy `{}` to `{}`", from.display(), to.display()))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl Git {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) async fn hash(path: &Path) -> Result<String> {
|
||||
pub(super) async fn revision(path: &Path) -> Result<String> {
|
||||
let output = Command::new("git")
|
||||
.args(["rev-parse", "--short", "HEAD"])
|
||||
.current_dir(path)
|
||||
|
|
|
|||
|
|
@ -52,4 +52,17 @@ impl Dependency {
|
|||
|
||||
Ok(format!("{:x}", h.finish_128()))
|
||||
}
|
||||
|
||||
pub(super) async fn hash_check(&self) -> Result<()> {
|
||||
if self.hash != self.hash().await? {
|
||||
bail!(
|
||||
"You have modified the contents of the `{}` {}. For safety, the operation has been aborted.
|
||||
Please manually delete it from `{}` and re-run the command.",
|
||||
self.name,
|
||||
if self.is_flavor { "flavor" } else { "plugin" },
|
||||
self.target().display()
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl Dependency {
|
|||
};
|
||||
|
||||
if self.rev.is_empty() {
|
||||
self.rev = Git::hash(&path).await?;
|
||||
self.rev = Git::revision(&path).await?;
|
||||
} else {
|
||||
Git::checkout(&path, self.rev.trim_start_matches('=')).await?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,41 +25,36 @@ impl Package {
|
|||
|
||||
pub(crate) async fn add_many(&mut self, uses: &[String]) -> Result<()> {
|
||||
for u in uses {
|
||||
if let Err(e) = self.add(u).await {
|
||||
self.save().await?;
|
||||
return Err(e);
|
||||
}
|
||||
let r = self.add(u).await;
|
||||
self.save().await?;
|
||||
r?;
|
||||
}
|
||||
self.save().await
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn delete_many(&mut self, uses: &[String]) -> Result<()> {
|
||||
for u in uses {
|
||||
if let Err(e) = self.delete(u).await {
|
||||
self.save().await?;
|
||||
return Err(e);
|
||||
}
|
||||
let r = self.delete(u).await;
|
||||
self.save().await?;
|
||||
r?;
|
||||
}
|
||||
self.save().await
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn install(&mut self, upgrade: bool) -> Result<()> {
|
||||
for d in &mut self.plugins {
|
||||
if upgrade {
|
||||
d.upgrade().await?;
|
||||
} else {
|
||||
d.install().await?;
|
||||
}
|
||||
for i in 0..self.plugins.len() {
|
||||
let r =
|
||||
if upgrade { self.plugins[i].upgrade().await } else { self.plugins[i].install().await };
|
||||
self.save().await?;
|
||||
r?;
|
||||
}
|
||||
for d in &mut self.flavors {
|
||||
if upgrade {
|
||||
d.upgrade().await?;
|
||||
} else {
|
||||
d.install().await?;
|
||||
}
|
||||
for i in 0..self.flavors.len() {
|
||||
let r =
|
||||
if upgrade { self.flavors[i].upgrade().await } else { self.flavors[i].install().await };
|
||||
self.save().await?;
|
||||
r?;
|
||||
}
|
||||
|
||||
self.save().await
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn print(&self) -> Result<()> {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-codegen"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-config"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
@ -9,10 +9,10 @@ homepage = "https://yazi-rs.github.io"
|
|||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[dependencies]
|
||||
yazi-codegen = { path = "../yazi-codegen", version = "25.3.7" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.3.7" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-codegen = { path = "../yazi-codegen", version = "25.4.8" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.4.8" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -82,8 +82,8 @@ keymap = [
|
|||
{ on = "s", run = "search --via=fd", desc = "Search files by name via fd" },
|
||||
{ on = "S", run = "search --via=rg", desc = "Search files by content via ripgrep" },
|
||||
{ on = "<C-s>", run = "escape --search", desc = "Cancel the ongoing search" },
|
||||
{ on = "z", run = "plugin zoxide", desc = "Jump to a directory via zoxide" },
|
||||
{ on = "Z", run = "plugin fzf", desc = "Jump to a file/directory via fzf" },
|
||||
{ on = "z", run = "plugin fzf", desc = "Jump to a file/directory via fzf" },
|
||||
{ on = "Z", run = "plugin zoxide", desc = "Jump to a directory via zoxide" },
|
||||
|
||||
# Linemode
|
||||
{ on = [ "m", "s" ], run = "linemode size", desc = "Linemode: size" },
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ micro_workers = 10
|
|||
macro_workers = 10
|
||||
bizarre_retry = 3
|
||||
image_alloc = 536870912 # 512MB
|
||||
image_bound = [ 0, 0 ]
|
||||
image_bound = [ 5000, 5000 ]
|
||||
suppress_preload = false
|
||||
|
||||
[plugin]
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ fn try_init_flavor(light: bool, merge: bool) -> anyhow::Result<()> {
|
|||
))?;
|
||||
|
||||
let flavor = shadow.flavor.as_ref().map(theme::Flavor::from).unwrap_or_default().read(light)?;
|
||||
theme = theme.deserialize_over_with::<toml::Value>(shadow)?;
|
||||
theme = theme.deserialize_over(toml::Deserializer::new(&flavor))?;
|
||||
theme = theme.deserialize_over_with::<toml::Value>(shadow)?;
|
||||
}
|
||||
|
||||
THEME.init(theme.reshape(light)?);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-core"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
@ -9,18 +9,18 @@ homepage = "https://yazi-rs.github.io"
|
|||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[dependencies]
|
||||
yazi-adapter = { path = "../yazi-adapter", version = "25.3.7" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.3.7" }
|
||||
yazi-codegen = { path = "../yazi-codegen", version = "25.3.7" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.3.7" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.3.7" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.3.7" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.3.7" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "25.3.7" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "25.3.7" }
|
||||
yazi-scheduler = { path = "../yazi-scheduler", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-widgets = { path = "../yazi-widgets", version = "25.3.7" }
|
||||
yazi-adapter = { path = "../yazi-adapter", version = "25.4.8" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.4.8" }
|
||||
yazi-codegen = { path = "../yazi-codegen", version = "25.4.8" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.4.8" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.4.8" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.4.8" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "25.4.8" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "25.4.8" }
|
||||
yazi-scheduler = { path = "../yazi-scheduler", version = "25.4.8" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
yazi-widgets = { path = "../yazi-widgets", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -3,14 +3,10 @@ use yazi_shared::event::CmdCow;
|
|||
use crate::{mgr::{Mgr, commands::quit}, tasks::Tasks};
|
||||
|
||||
#[derive(Default)]
|
||||
struct Opt {
|
||||
no_cwd_file: bool,
|
||||
}
|
||||
struct Opt(quit::Opt);
|
||||
|
||||
impl From<CmdCow> for Opt {
|
||||
fn from(c: CmdCow) -> Self { Self { no_cwd_file: c.bool("no-cwd-file") } }
|
||||
}
|
||||
impl From<Opt> for quit::Opt {
|
||||
fn from(value: Opt) -> Self { Self { no_cwd_file: value.no_cwd_file } }
|
||||
fn from(c: CmdCow) -> Self { Self(c.into()) }
|
||||
}
|
||||
|
||||
impl Mgr {
|
||||
|
|
@ -19,6 +15,6 @@ impl Mgr {
|
|||
if self.tabs.len() > 1 {
|
||||
return self.tabs.close(self.tabs.cursor);
|
||||
}
|
||||
self.quit(opt, tasks);
|
||||
self.quit(opt.0, tasks);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,13 +22,12 @@ impl Mgr {
|
|||
#[yazi_codegen::command]
|
||||
pub fn create(&self, opt: Opt) {
|
||||
let cwd = self.cwd().to_owned();
|
||||
let mut input = InputProxy::show(InputCfg::create(opt.dir));
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut result = InputProxy::show(InputCfg::create(opt.dir));
|
||||
let Some(Ok(name)) = result.recv().await else {
|
||||
return Ok(());
|
||||
};
|
||||
let Some(Ok(name)) = input.recv().await else { return };
|
||||
if name.is_empty() {
|
||||
return Ok(());
|
||||
return;
|
||||
}
|
||||
|
||||
let new = cwd.join(&name);
|
||||
|
|
@ -36,10 +35,10 @@ impl Mgr {
|
|||
&& maybe_exists(&new).await
|
||||
&& !ConfirmProxy::show(ConfirmCfg::overwrite(&new)).await
|
||||
{
|
||||
return Ok(());
|
||||
return;
|
||||
}
|
||||
|
||||
Self::create_do(new, opt.dir || name.ends_with('/') || name.ends_with('\\')).await
|
||||
_ = Self::create_do(new, opt.dir || name.ends_with('/') || name.ends_with('\\')).await;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,18 @@
|
|||
use std::{borrow::Cow, ffi::OsString};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use tracing::error;
|
||||
use yazi_boot::ARGS;
|
||||
use yazi_config::{YAZI, popup::PickCfg};
|
||||
use yazi_fs::File;
|
||||
use yazi_macro::emit;
|
||||
use yazi_plugin::isolate;
|
||||
use yazi_proxy::{MgrProxy, TasksProxy, options::OpenDoOpt};
|
||||
use yazi_shared::{MIME_DIR, event::{CmdCow, EventQuit}, url::Url};
|
||||
use yazi_proxy::{MgrProxy, PickProxy, TasksProxy, options::OpenDoOpt};
|
||||
use yazi_shared::{MIME_DIR, event::CmdCow, url::Url};
|
||||
|
||||
use crate::{mgr::Mgr, tab::Folder, tasks::Tasks};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Opt {
|
||||
interactive: bool,
|
||||
hovered: bool,
|
||||
pub(super) struct Opt {
|
||||
pub(super) interactive: bool,
|
||||
pub(super) hovered: bool,
|
||||
}
|
||||
|
||||
impl From<CmdCow> for Opt {
|
||||
|
|
@ -95,12 +93,10 @@ impl Mgr {
|
|||
return;
|
||||
}
|
||||
|
||||
let pick = PickProxy::show(PickCfg::open(openers.iter().map(|o| o.desc()).collect()));
|
||||
let urls = [opt.hovered].into_iter().chain(targets.into_iter().map(|(u, _)| u)).collect();
|
||||
tokio::spawn(async move {
|
||||
let result =
|
||||
yazi_proxy::PickProxy::show(PickCfg::open(openers.iter().map(|o| o.desc()).collect()));
|
||||
|
||||
if let Ok(choice) = result.await {
|
||||
if let Ok(choice) = pick.await {
|
||||
TasksProxy::open_with(Cow::Borrowed(openers[choice]), opt.cwd, urls);
|
||||
}
|
||||
});
|
||||
|
|
@ -122,19 +118,4 @@ impl Mgr {
|
|||
|| find(self.hovered_folder())
|
||||
|| find(self.active().history.get(&p))
|
||||
}
|
||||
|
||||
fn quit_with_selected(opt: Opt, selected: &[&Url]) -> bool {
|
||||
if opt.interactive || ARGS.chooser_file.is_none() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let paths = selected.iter().fold(OsString::new(), |mut s, &u| {
|
||||
s.push(u.as_os_str());
|
||||
s.push("\n");
|
||||
s
|
||||
});
|
||||
|
||||
emit!(Quit(EventQuit { selected: Some(paths), ..Default::default() }));
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl Mgr {
|
|||
if self.yanked.cut {
|
||||
tasks.file_cut(&src, dest, opt.force);
|
||||
|
||||
self.tabs.iter_mut().for_each(|t| _ = t.selected.remove_many(&src, false));
|
||||
self.tabs.iter_mut().for_each(|t| _ = t.selected.remove_many(&src));
|
||||
self.unyank(());
|
||||
} else {
|
||||
tasks.file_copy(&src, dest, opt.force, opt.follow);
|
||||
|
|
|
|||
|
|
@ -1,25 +1,39 @@
|
|||
use std::time::Duration;
|
||||
use std::{ffi::OsString, time::Duration};
|
||||
|
||||
use tokio::{select, time};
|
||||
use yazi_boot::ARGS;
|
||||
use yazi_config::popup::ConfirmCfg;
|
||||
use yazi_macro::emit;
|
||||
use yazi_proxy::ConfirmProxy;
|
||||
use yazi_shared::event::{CmdCow, EventQuit};
|
||||
use yazi_shared::{event::{CmdCow, Data, EventQuit}, url::Url};
|
||||
|
||||
use crate::{mgr::Mgr, tasks::Tasks};
|
||||
|
||||
#[derive(Default)]
|
||||
pub(super) struct Opt {
|
||||
pub(super) code: i32,
|
||||
pub(super) no_cwd_file: bool,
|
||||
}
|
||||
|
||||
impl From<CmdCow> for Opt {
|
||||
fn from(c: CmdCow) -> Self { Self { no_cwd_file: c.bool("no-cwd-file") } }
|
||||
fn from(c: CmdCow) -> Self {
|
||||
Self {
|
||||
code: c.get("code").and_then(Data::as_i32).unwrap_or_default(),
|
||||
no_cwd_file: c.bool("no-cwd-file"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Opt> for EventQuit {
|
||||
fn from(value: Opt) -> Self {
|
||||
EventQuit { code: value.code, no_cwd_file: value.no_cwd_file, ..Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Mgr {
|
||||
#[yazi_codegen::command]
|
||||
pub fn quit(&self, opt: Opt, tasks: &Tasks) {
|
||||
let opt = EventQuit { no_cwd_file: opt.no_cwd_file, ..Default::default() };
|
||||
let event = opt.into();
|
||||
|
||||
let ongoing = tasks.ongoing().clone();
|
||||
let (left, left_names) = {
|
||||
|
|
@ -28,7 +42,7 @@ impl Mgr {
|
|||
};
|
||||
|
||||
if left == 0 {
|
||||
emit!(Quit(opt));
|
||||
emit!(Quit(event));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -41,13 +55,13 @@ impl Mgr {
|
|||
i += 1;
|
||||
if i > 40 { break }
|
||||
else if ongoing.lock().is_empty() {
|
||||
emit!(Quit(opt));
|
||||
emit!(Quit(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
b = &mut rx => {
|
||||
if b.unwrap_or(false) {
|
||||
emit!(Quit(opt));
|
||||
emit!(Quit(event));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -55,8 +69,23 @@ impl Mgr {
|
|||
}
|
||||
|
||||
if rx.await.unwrap_or(false) {
|
||||
emit!(Quit(opt));
|
||||
emit!(Quit(event));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub(super) fn quit_with_selected(opt: super::open::Opt, selected: &[&Url]) -> bool {
|
||||
if opt.interactive || ARGS.chooser_file.is_none() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let paths = selected.iter().fold(OsString::new(), |mut s, &u| {
|
||||
s.push(u.as_os_str());
|
||||
s.push("\n");
|
||||
s
|
||||
});
|
||||
|
||||
emit!(Quit(EventQuit { selected: Some(paths), ..Default::default() }));
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,14 +41,14 @@ impl Mgr {
|
|||
return self.remove_do(opt, tasks);
|
||||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
let result = ConfirmProxy::show(if opt.permanently {
|
||||
ConfirmCfg::delete(&opt.targets)
|
||||
} else {
|
||||
ConfirmCfg::trash(&opt.targets)
|
||||
});
|
||||
let confirm = ConfirmProxy::show(if opt.permanently {
|
||||
ConfirmCfg::delete(&opt.targets)
|
||||
} else {
|
||||
ConfirmCfg::trash(&opt.targets)
|
||||
});
|
||||
|
||||
if result.await {
|
||||
tokio::spawn(async move {
|
||||
if confirm.await {
|
||||
MgrProxy::remove_do(opt.targets, opt.permanently);
|
||||
}
|
||||
});
|
||||
|
|
@ -57,7 +57,7 @@ impl Mgr {
|
|||
#[yazi_codegen::command]
|
||||
pub fn remove_do(&mut self, opt: Opt, tasks: &Tasks) {
|
||||
self.tabs.iter_mut().for_each(|t| {
|
||||
t.selected.remove_many(&opt.targets, false);
|
||||
t.selected.remove_many(&opt.targets);
|
||||
});
|
||||
|
||||
for u in &opt.targets {
|
||||
|
|
|
|||
|
|
@ -53,12 +53,10 @@ impl Mgr {
|
|||
|
||||
let old = hovered.url_owned();
|
||||
let tab = self.tabs.active().id;
|
||||
tokio::spawn(async move {
|
||||
let mut result = InputProxy::show(InputCfg::rename().with_value(name).with_cursor(cursor));
|
||||
let Some(Ok(name)) = result.recv().await else {
|
||||
return;
|
||||
};
|
||||
let mut input = InputProxy::show(InputCfg::rename().with_value(name).with_cursor(cursor));
|
||||
|
||||
tokio::spawn(async move {
|
||||
let Some(Ok(name)) = input.recv().await else { return };
|
||||
if name.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,10 +77,10 @@ impl Tab {
|
|||
}
|
||||
|
||||
fn cd_interactive(&mut self) {
|
||||
tokio::spawn(async move {
|
||||
let rx = InputProxy::show(InputCfg::cd());
|
||||
let input = InputProxy::show(InputCfg::cd());
|
||||
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||
tokio::spawn(async move {
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(input), Duration::from_millis(50));
|
||||
pin!(rx);
|
||||
|
||||
while let Some(result) = rx.next().await {
|
||||
|
|
|
|||
|
|
@ -109,10 +109,9 @@ impl Tab {
|
|||
let urls: Vec<_> =
|
||||
indices.into_iter().filter_map(|i| self.current.files.get(i)).map(|f| &f.url).collect();
|
||||
|
||||
let same = !self.cwd().is_search();
|
||||
if !select {
|
||||
self.selected.remove_many(&urls, same);
|
||||
} else if self.selected.add_many(&urls, same) != urls.len() {
|
||||
self.selected.remove_many(&urls);
|
||||
} else if self.selected.add_many(&urls) != urls.len() {
|
||||
AppProxy::notify_warn(
|
||||
"Escape visual mode",
|
||||
"Some files cannot be selected, due to path nesting conflict.",
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ impl From<CmdCow> for Opt {
|
|||
impl Tab {
|
||||
#[yazi_codegen::command]
|
||||
pub fn filter(&mut self, opt: Opt) {
|
||||
tokio::spawn(async move {
|
||||
let rx = InputProxy::show(InputCfg::filter());
|
||||
let input = InputProxy::show(InputCfg::filter());
|
||||
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||
tokio::spawn(async move {
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(input), Duration::from_millis(50));
|
||||
pin!(rx);
|
||||
|
||||
while let Some(result) = rx.next().await {
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ impl From<CmdCow> for Opt {
|
|||
impl Tab {
|
||||
#[yazi_codegen::command]
|
||||
pub fn find(&mut self, opt: Opt) {
|
||||
tokio::spawn(async move {
|
||||
let rx = InputProxy::show(InputCfg::find(opt.prev));
|
||||
let input = InputProxy::show(InputCfg::find(opt.prev));
|
||||
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||
tokio::spawn(async move {
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(input), Duration::from_millis(50));
|
||||
pin!(rx);
|
||||
|
||||
while let Some(Ok(s)) | Some(Err(InputError::Typed(s))) = rx.next().await {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::{borrow::Cow, mem, time::Duration};
|
||||
|
||||
use anyhow::bail;
|
||||
use tokio::pin;
|
||||
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
|
||||
use tracing::error;
|
||||
|
|
@ -13,22 +12,18 @@ use crate::tab::Tab;
|
|||
|
||||
impl Tab {
|
||||
pub fn search(&mut self, opt: impl TryInto<SearchOpt>) {
|
||||
let Ok(mut opt) = opt.try_into() else {
|
||||
let Ok(mut opt): Result<SearchOpt, _> = opt.try_into() else {
|
||||
return AppProxy::notify_error("Invalid `search` option", "Failed to parse search option");
|
||||
};
|
||||
|
||||
if opt.via == SearchOptVia::None {
|
||||
return self.search_stop();
|
||||
}
|
||||
|
||||
if let Some(handle) = self.search.take() {
|
||||
handle.abort();
|
||||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut input =
|
||||
InputProxy::show(InputCfg::search(&opt.via.to_string()).with_value(opt.subject));
|
||||
let mut input =
|
||||
InputProxy::show(InputCfg::search(opt.via.as_ref()).with_value(opt.subject.to_owned()));
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Some(Ok(subject)) = input.recv().await {
|
||||
opt.subject = Cow::Owned(subject);
|
||||
TabProxy::search_do(opt);
|
||||
|
|
@ -68,7 +63,6 @@ impl Tab {
|
|||
subject: opt.subject.into_owned(),
|
||||
args: opt.args,
|
||||
}),
|
||||
SearchOptVia::None => bail!("Invalid `via` option for `search` command"),
|
||||
}?;
|
||||
|
||||
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(5000, Duration::from_millis(500));
|
||||
|
|
|
|||
|
|
@ -54,11 +54,16 @@ impl Tab {
|
|||
|
||||
let cwd = opt.cwd.take().unwrap_or_else(|| self.cwd().clone());
|
||||
let selected = self.hovered_and_selected().cloned().collect();
|
||||
|
||||
let input = opt.interactive.then(|| {
|
||||
InputProxy::show(
|
||||
InputCfg::shell(opt.block).with_value(opt.run.to_owned()).with_cursor(opt.cursor),
|
||||
)
|
||||
});
|
||||
|
||||
tokio::spawn(async move {
|
||||
if opt.interactive {
|
||||
let mut result =
|
||||
InputProxy::show(InputCfg::shell(opt.block).with_value(opt.run).with_cursor(opt.cursor));
|
||||
match result.recv().await {
|
||||
if let Some(mut rx) = input {
|
||||
match rx.recv().await {
|
||||
Some(Ok(e)) => opt.run = Cow::Owned(e),
|
||||
_ => return,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,26 @@
|
|||
use yazi_macro::render;
|
||||
use yazi_proxy::AppProxy;
|
||||
use yazi_shared::event::CmdCow;
|
||||
use yazi_shared::{event::CmdCow, url::Url};
|
||||
|
||||
use crate::tab::Tab;
|
||||
|
||||
struct Opt {
|
||||
urls: Vec<Url>,
|
||||
state: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<CmdCow> for Opt {
|
||||
fn from(c: CmdCow) -> Self {
|
||||
fn from(mut c: CmdCow) -> Self {
|
||||
let mut urls = Vec::with_capacity(c.len());
|
||||
for i in 0..c.len() {
|
||||
match c.take_url(i) {
|
||||
Some(url) => urls.push(url),
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
urls,
|
||||
state: match c.str("state") {
|
||||
Some("on") => Some(true),
|
||||
Some("off") => Some(false),
|
||||
|
|
@ -19,27 +29,38 @@ impl From<CmdCow> for Opt {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Option<bool>> for Opt {
|
||||
fn from(state: Option<bool>) -> Self { Self { state } }
|
||||
fn from(state: Option<bool>) -> Self { Self { urls: vec![], state } }
|
||||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_codegen::command]
|
||||
pub fn toggle_all(&mut self, opt: Opt) {
|
||||
let iter = self.current.files.iter().map(|f| &f.url);
|
||||
let (removal, addition): (Vec<_>, Vec<_>) = match opt.state {
|
||||
Some(true) => (vec![], iter.collect()),
|
||||
Some(false) => (iter.collect(), vec![]),
|
||||
None => iter.partition(|&u| self.selected.contains_key(u)),
|
||||
use yazi_shared::Either::*;
|
||||
|
||||
let it = self.current.files.iter().map(|f| &f.url);
|
||||
let either = match opt.state {
|
||||
Some(true) if opt.urls.is_empty() => Left((vec![], it.collect())),
|
||||
Some(true) => Right((vec![], opt.urls)),
|
||||
Some(false) if opt.urls.is_empty() => Left((it.collect(), vec![])),
|
||||
Some(false) => Right((opt.urls, vec![])),
|
||||
None if opt.urls.is_empty() => Left(it.partition(|&u| self.selected.contains_key(u))),
|
||||
None => Right(opt.urls.into_iter().partition(|u| self.selected.contains_key(u))),
|
||||
};
|
||||
|
||||
let same = !self.cwd().is_search();
|
||||
render!(self.selected.remove_many(&removal, same) > 0);
|
||||
let warn = match either {
|
||||
Left((removal, addition)) => {
|
||||
render!(self.selected.remove_many(&removal) > 0);
|
||||
render!(self.selected.add_many(&addition), > 0) != addition.len()
|
||||
}
|
||||
Right((removal, addition)) => {
|
||||
render!(self.selected.remove_many(&removal) > 0);
|
||||
render!(self.selected.add_many(&addition), > 0) != addition.len()
|
||||
}
|
||||
};
|
||||
|
||||
let added = self.selected.add_many(&addition, same);
|
||||
render!(added > 0);
|
||||
|
||||
if added != addition.len() {
|
||||
if warn {
|
||||
AppProxy::notify_warn(
|
||||
"Toggle all",
|
||||
"Some files cannot be selected, due to path nesting conflict.",
|
||||
|
|
|
|||
|
|
@ -20,11 +20,7 @@ impl Selected {
|
|||
#[inline]
|
||||
pub fn add(&mut self, url: &Url) -> bool { self.add_same(&[url]) == 1 }
|
||||
|
||||
pub fn add_many(&mut self, urls: &[impl AsRef<Url>], same: bool) -> usize {
|
||||
if same {
|
||||
return self.add_same(urls);
|
||||
}
|
||||
|
||||
pub fn add_many(&mut self, urls: &[impl AsRef<Url>]) -> usize {
|
||||
let mut grouped: HashMap<_, Vec<_>> = Default::default();
|
||||
for u in urls {
|
||||
if let Some(p) = u.as_ref().parent_url() {
|
||||
|
|
@ -66,22 +62,19 @@ impl Selected {
|
|||
#[inline]
|
||||
pub fn remove(&mut self, url: &Url) -> bool { self.remove_same(&[url]) == 1 }
|
||||
|
||||
pub fn remove_many(&mut self, urls: &[impl AsRef<Url>], same: bool) -> usize {
|
||||
let affected = if same {
|
||||
self.remove_same(urls)
|
||||
} else {
|
||||
let mut grouped: HashMap<_, Vec<_>> = Default::default();
|
||||
for u in urls {
|
||||
if let Some(p) = u.as_ref().parent_url() {
|
||||
grouped.entry(p).or_default().push(u);
|
||||
}
|
||||
pub fn remove_many(&mut self, urls: &[impl AsRef<Url>]) -> usize {
|
||||
let mut grouped: HashMap<_, Vec<_>> = Default::default();
|
||||
for u in urls {
|
||||
if let Some(p) = u.as_ref().parent_url() {
|
||||
grouped.entry(p).or_default().push(u);
|
||||
}
|
||||
grouped.into_values().map(|v| self.remove_same(&v)).sum()
|
||||
};
|
||||
}
|
||||
|
||||
let affected = grouped.into_values().map(|v| self.remove_same(&v)).sum();
|
||||
if affected > 0 {
|
||||
self.inner.sort_unstable_by(|_, a, _, b| a.cmp(b));
|
||||
}
|
||||
|
||||
affected
|
||||
}
|
||||
|
||||
|
|
@ -113,10 +106,10 @@ impl Selected {
|
|||
pub fn apply_op(&mut self, op: &FilesOp) {
|
||||
let (removal, addition) = op.diff_recoverable(|u| self.contains_key(u));
|
||||
if !removal.is_empty() {
|
||||
self.remove_many(&removal, !op.cwd().is_search());
|
||||
self.remove_many(&removal);
|
||||
}
|
||||
if !addition.is_empty() {
|
||||
self.add_many(&addition, !op.cwd().is_search());
|
||||
self.add_many(&addition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-dds"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
@ -13,10 +13,11 @@ default = [ "vendored-lua" ]
|
|||
vendored-lua = [ "mlua/vendored" ]
|
||||
|
||||
[dependencies]
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.3.7" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.3.7" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-binding = { path = "../yazi-binding", version = "25.4.8" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.4.8" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.4.8" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
|
|
@ -30,7 +31,7 @@ tokio-util = { workspace = true }
|
|||
tracing = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
vergen-gitcl = { version = "1.0.5", features = [ "build" ] }
|
||||
vergen-gitcl = { version = "1.0.7", features = [ "build" ] }
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
uzers = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ impl UserData for BodyBulkIter {
|
|||
methods.add_meta_function(MetaMethod::Pairs, |lua, me: AnyUserData| {
|
||||
let iter = lua.create_function(|lua, mut me: UserDataRefMut<Self>| {
|
||||
if let Some((Cow::Owned(from), Cow::Owned(to))) = me.inner.next() {
|
||||
(lua.create_any_userdata(from)?, lua.create_any_userdata(to)?).into_lua_multi(lua)
|
||||
(yazi_binding::Url::new(from), yazi_binding::Url::new(to)).into_lua_multi(lua)
|
||||
} else {
|
||||
().into_lua_multi(lua)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ impl IntoLua for BodyCd<'static> {
|
|||
if let Some(Cow::Owned(url)) = Some(self.url).filter(|_| !self.dummy) {
|
||||
lua.create_table_from([
|
||||
("tab", self.tab.get().into_lua(lua)?),
|
||||
("url", lua.create_any_userdata(url)?.into_lua(lua)?),
|
||||
("url", yazi_binding::Url::new(url).into_lua(lua)?),
|
||||
])?
|
||||
} else {
|
||||
lua.create_table_from([("tab", self.tab.get())])?
|
||||
|
|
|
|||
|
|
@ -27,10 +27,8 @@ impl<'a> From<BodyDelete<'a>> for Body<'a> {
|
|||
|
||||
impl IntoLua for BodyDelete<'static> {
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
let urls = lua.create_table_with_capacity(self.urls.len(), 0)?;
|
||||
for (i, url) in self.urls.into_owned().into_iter().enumerate() {
|
||||
urls.raw_set(i + 1, lua.create_any_userdata(url)?)?;
|
||||
}
|
||||
let urls =
|
||||
lua.create_sequence_from(self.urls.into_owned().into_iter().map(yazi_binding::Url::new))?;
|
||||
|
||||
lua.create_table_from([("urls", urls)])?.into_lua(lua)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ impl IntoLua for BodyHover<'static> {
|
|||
if let Some(Cow::Owned(url)) = self.url {
|
||||
lua.create_table_from([
|
||||
("tab", self.tab.get().into_lua(lua)?),
|
||||
("url", lua.create_any_userdata(url)?.into_lua(lua)?),
|
||||
("url", yazi_binding::Url::new(url).into_lua(lua)?),
|
||||
])?
|
||||
} else {
|
||||
lua.create_table_from([("tab", self.tab.get())])?
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ impl IntoLua for BodyLoad<'static> {
|
|||
lua
|
||||
.create_table_from([
|
||||
("tab", self.tab.get().into_lua(lua)?),
|
||||
("url", lua.create_any_userdata(self.url.into_owned())?.into_lua(lua)?),
|
||||
("stage", lua.create_any_userdata(self.stage)?.into_lua(lua)?),
|
||||
("url", yazi_binding::Url::new(self.url.into_owned()).into_lua(lua)?),
|
||||
("stage", yazi_binding::FolderStage::new(self.stage).into_lua(lua)?),
|
||||
])?
|
||||
.into_lua(lua)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ impl IntoLua for BodyMoveItem {
|
|||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
lua
|
||||
.create_table_from([
|
||||
("from", lua.create_any_userdata(self.from)?),
|
||||
("to", lua.create_any_userdata(self.to)?),
|
||||
("from", yazi_binding::Url::new(self.from)),
|
||||
("to", yazi_binding::Url::new(self.to)),
|
||||
])?
|
||||
.into_lua(lua)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ impl IntoLua for BodyRename<'static> {
|
|||
lua
|
||||
.create_table_from([
|
||||
("tab", self.tab.get().into_lua(lua)?),
|
||||
("from", lua.create_any_userdata(self.from.into_owned())?.into_lua(lua)?),
|
||||
("to", lua.create_any_userdata(self.to.into_owned())?.into_lua(lua)?),
|
||||
("from", yazi_binding::Url::new(self.from.into_owned()).into_lua(lua)?),
|
||||
("to", yazi_binding::Url::new(self.to.into_owned()).into_lua(lua)?),
|
||||
])?
|
||||
.into_lua(lua)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,8 @@ impl<'a> From<BodyTrash<'a>> for Body<'a> {
|
|||
|
||||
impl IntoLua for BodyTrash<'static> {
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
let urls = lua.create_table_with_capacity(self.urls.len(), 0)?;
|
||||
for (i, url) in self.urls.into_owned().into_iter().enumerate() {
|
||||
urls.raw_set(i + 1, lua.create_any_userdata(url)?)?;
|
||||
}
|
||||
let urls =
|
||||
lua.create_sequence_from(self.urls.into_owned().into_iter().map(yazi_binding::Url::new))?;
|
||||
|
||||
lua.create_table_from([("urls", urls)])?.into_lua(lua)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,12 +57,12 @@ impl UserData for BodyYankIter {
|
|||
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.urls.len()));
|
||||
|
||||
methods.add_meta_method(MetaMethod::Index, |lua, me, idx: usize| {
|
||||
if idx > me.urls.len() || idx == 0 {
|
||||
Ok(None)
|
||||
methods.add_meta_method(MetaMethod::Index, |_, me, idx: usize| {
|
||||
Ok(if idx > me.urls.len() || idx == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(lua.create_any_userdata(me.urls[idx - 1].clone())).transpose()
|
||||
}
|
||||
Some(yazi_binding::Url::new(me.urls[idx - 1].clone()))
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
use mlua::{ExternalError, Lua, MultiValue, Table, Value};
|
||||
use mlua::{ExternalError, IntoLua, Lua, MultiValue, Table, Value};
|
||||
use yazi_shared::{OrderedFloat, event::{Data, DataKey}, replace_cow};
|
||||
|
||||
pub struct Sendable;
|
||||
|
|
@ -41,8 +41,8 @@ impl Sendable {
|
|||
Value::Function(_) => Err("function is not supported".into_lua_err())?,
|
||||
Value::Thread(_) => Err("thread is not supported".into_lua_err())?,
|
||||
Value::UserData(ud) => {
|
||||
if let Ok(t) = ud.take::<yazi_shared::url::Url>() {
|
||||
Data::Url(t)
|
||||
if let Ok(t) = ud.take::<yazi_binding::Url>() {
|
||||
Data::Url(t.into())
|
||||
} else if let Ok(t) = ud.take::<yazi_fs::FilesOp>() {
|
||||
Data::Any(Box::new(t))
|
||||
} else if let Ok(t) = ud.take::<super::body::BodyYankIter>() {
|
||||
|
|
@ -73,7 +73,7 @@ impl Sendable {
|
|||
}
|
||||
Value::Table(tbl)
|
||||
}
|
||||
Data::Url(u) => Value::UserData(lua.create_any_userdata(u)?),
|
||||
Data::Url(u) => yazi_binding::Url::new(u).into_lua(lua)?,
|
||||
Data::Any(a) => Value::UserData(if a.is::<yazi_fs::FilesOp>() {
|
||||
lua.create_any_userdata(*a.downcast::<yazi_fs::FilesOp>().unwrap())?
|
||||
} else if a.is::<super::body::BodyYankIter>() {
|
||||
|
|
@ -107,7 +107,7 @@ impl Sendable {
|
|||
}
|
||||
Value::Table(tbl)
|
||||
}
|
||||
Data::Url(u) => Value::UserData(lua.create_any_userdata(u.clone())?),
|
||||
Data::Url(u) => yazi_binding::Url::new(u.clone()).into_lua(lua)?,
|
||||
Data::Bytes(b) => Value::String(lua.create_string(b)?),
|
||||
Data::Any(a) => Value::UserData(if let Some(t) = a.downcast_ref::<yazi_fs::FilesOp>() {
|
||||
lua.create_any_userdata(t.clone())?
|
||||
|
|
@ -189,8 +189,8 @@ impl Sendable {
|
|||
Value::Function(_) => Err("function is not supported".into_lua_err())?,
|
||||
Value::Thread(_) => Err("thread is not supported".into_lua_err())?,
|
||||
Value::UserData(ud) => {
|
||||
if let Ok(t) = ud.take::<yazi_shared::url::Url>() {
|
||||
DataKey::Url(t)
|
||||
if let Ok(t) = ud.take::<yazi_binding::Url>() {
|
||||
DataKey::Url(t.into())
|
||||
} else {
|
||||
Err("unsupported userdata included".into_lua_err())?
|
||||
}
|
||||
|
|
@ -202,7 +202,7 @@ impl Sendable {
|
|||
|
||||
fn key_to_value(lua: &Lua, key: DataKey) -> mlua::Result<Value> {
|
||||
Ok(match key {
|
||||
DataKey::Url(u) => Value::UserData(lua.create_any_userdata(u)?),
|
||||
DataKey::Url(u) => yazi_binding::Url::new(u).into_lua(lua)?,
|
||||
key => Self::key_to_value_ref(lua, &key)?,
|
||||
})
|
||||
}
|
||||
|
|
@ -214,7 +214,7 @@ impl Sendable {
|
|||
DataKey::Integer(i) => Value::Integer(*i),
|
||||
DataKey::Number(n) => Value::Number(n.get()),
|
||||
DataKey::String(s) => Value::String(lua.create_string(s.as_ref())?),
|
||||
DataKey::Url(u) => Value::UserData(lua.create_any_userdata(u.clone())?),
|
||||
DataKey::Url(u) => yazi_binding::Url::new(u.clone()).into_lua(lua)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-ffi"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
@ -9,7 +9,7 @@ homepage = "https://yazi-rs.github.io"
|
|||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[dependencies]
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.3.7" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-fm"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
@ -13,27 +13,30 @@ default = [ "vendored-lua" ]
|
|||
vendored-lua = [ "mlua/vendored" ]
|
||||
|
||||
[dependencies]
|
||||
yazi-adapter = { path = "../yazi-adapter", version = "25.3.7" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.3.7" }
|
||||
yazi-codegen = { path = "../yazi-codegen", version = "25.3.7" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.3.7" }
|
||||
yazi-core = { path = "../yazi-core", version = "25.3.7" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.3.7" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.3.7" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.3.7" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "25.3.7" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-widgets = { path = "../yazi-widgets", version = "25.3.7" }
|
||||
yazi-adapter = { path = "../yazi-adapter", version = "25.4.8" }
|
||||
yazi-binding = { path = "../yazi-binding", version = "25.4.8" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.4.8" }
|
||||
yazi-codegen = { path = "../yazi-codegen", version = "25.4.8" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.4.8" }
|
||||
yazi-core = { path = "../yazi-core", version = "25.4.8" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.4.8" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.4.8" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "25.4.8" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "25.4.8" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
yazi-widgets = { path = "../yazi-widgets", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
better-panic = "0.3.0"
|
||||
crossterm = { workspace = true }
|
||||
fdlimit = "0.3.0"
|
||||
foldhash = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
ratatui = { workspace = true }
|
||||
scopeguard = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,14 @@ use std::{env, error::Error};
|
|||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let dir = env::var("OUT_DIR").unwrap();
|
||||
if dir.contains("\\target\\release\\build\\yazi-fm-") {
|
||||
|
||||
// cargo build
|
||||
// C:\Users\Ika\Desktop\yazi\target\release\build\yazi-fm-cfc94820f71daa30\out
|
||||
// cargo install
|
||||
// C:\Users\Ika\AppData\Local\Temp\cargo-installTFU8cj\release\build\
|
||||
// yazi-fm-45dffef2500eecd0\out
|
||||
|
||||
if dir.contains("\\release\\build\\yazi-fm-") {
|
||||
panic!(
|
||||
"Unwinding must be enabled for Windows. Please use `cargo build --profile release-windows --locked` instead to build Yazi."
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use yazi_macro::emit;
|
|||
use yazi_shared::event::{CmdCow, Event, NEED_RENDER};
|
||||
use yazi_widgets::input::InputMode;
|
||||
|
||||
use crate::{Ctx, Executor, Router, Signals, Term, lives::Lives};
|
||||
use crate::{Ctx, Executor, Router, Signals, Term};
|
||||
|
||||
pub(crate) struct App {
|
||||
pub(crate) cx: Ctx,
|
||||
|
|
@ -20,7 +20,6 @@ impl App {
|
|||
let term = Term::start()?;
|
||||
let (mut rx, signals) = (Event::take(), Signals::start()?);
|
||||
|
||||
Lives::register()?;
|
||||
let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
|
||||
app.render();
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl App {
|
|||
self.selected_to_file(selected);
|
||||
}
|
||||
|
||||
Term::goodbye(|| false);
|
||||
Term::goodbye(|| opt.code);
|
||||
}
|
||||
|
||||
fn cwd_to_file(&self) {
|
||||
|
|
|
|||
|
|
@ -1,38 +1,66 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, IntoLua, MetaMethod, UserData, Value};
|
||||
use paste::paste;
|
||||
|
||||
use super::Lives;
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Ctx {
|
||||
inner: *const crate::Ctx,
|
||||
inner: PtrCell<crate::Ctx>,
|
||||
|
||||
c_active: Option<Value>,
|
||||
c_tabs: Option<Value>,
|
||||
c_tasks: Option<Value>,
|
||||
c_yanked: Option<Value>,
|
||||
c_layer: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Ctx {
|
||||
type Target = crate::Ctx;
|
||||
|
||||
fn deref(&self) -> &Self::Target { unsafe { &*self.inner } }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Ctx {
|
||||
#[inline]
|
||||
pub(super) fn make(inner: &crate::Ctx) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
Lives::scoped_userdata(Self {
|
||||
inner: inner.into(),
|
||||
|
||||
c_active: None,
|
||||
c_tabs: None,
|
||||
c_tasks: None,
|
||||
c_yanked: None,
|
||||
c_layer: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Ctx {
|
||||
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::Index, |lua, me, key: mlua::String| {
|
||||
match key.as_bytes().as_ref() {
|
||||
b"active" => super::Tab::make(me.active())?,
|
||||
b"tabs" => super::Tabs::make(&me.mgr.tabs)?,
|
||||
b"tasks" => super::Tasks::make(&me.tasks)?,
|
||||
b"yanked" => super::Yanked::make(&me.mgr.yanked)?,
|
||||
b"layer" => return yazi_plugin::bindings::Layer::from(me.layer()).into_lua(lua),
|
||||
_ => return Ok(Value::Nil),
|
||||
methods.add_meta_method_mut(MetaMethod::Index, |lua, me, key: mlua::String| {
|
||||
macro_rules! reuse {
|
||||
($key:ident, $value:expr) => {
|
||||
match paste! { &me.[<c_ $key>] } {
|
||||
Some(v) => v.clone(),
|
||||
None => {
|
||||
let v = $value?.into_lua(lua)?;
|
||||
paste! { me.[<c_ $key>] = Some(v.clone()); };
|
||||
v
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
.into_lua(lua)
|
||||
Ok(match key.as_bytes().as_ref() {
|
||||
b"active" => reuse!(active, super::Tab::make(me.active())),
|
||||
b"tabs" => reuse!(tabs, super::Tabs::make(&me.mgr.tabs)),
|
||||
b"tasks" => reuse!(tasks, super::Tasks::make(&me.tasks)),
|
||||
b"yanked" => reuse!(yanked, super::Yanked::make(&me.mgr.yanked)),
|
||||
b"layer" => {
|
||||
reuse!(layer, Ok::<_, mlua::Error>(yazi_plugin::bindings::Layer::from(me.layer())))
|
||||
}
|
||||
_ => Value::Nil,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,27 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, IntoLua, UserData, UserDataFields, UserDataMethods};
|
||||
use mlua::{AnyUserData, IntoLua, UserData, UserDataFields, UserDataMethods, Value};
|
||||
use yazi_config::THEME;
|
||||
use yazi_plugin::{bindings::Range, elements::Style};
|
||||
|
||||
use super::Lives;
|
||||
use crate::Ctx;
|
||||
use crate::{Ctx, lives::PtrCell};
|
||||
|
||||
pub(super) struct File {
|
||||
idx: usize,
|
||||
folder: *const yazi_core::tab::Folder,
|
||||
tab: *const yazi_core::tab::Tab,
|
||||
folder: PtrCell<yazi_core::tab::Folder>,
|
||||
tab: PtrCell<yazi_core::tab::Tab>,
|
||||
|
||||
v_cha: Option<Value>,
|
||||
v_url: Option<Value>,
|
||||
v_link_to: Option<Value>,
|
||||
v_name: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for File {
|
||||
type Target = yazi_fs::File;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.folder().files[self.idx] }
|
||||
fn deref(&self) -> &Self::Target { &self.folder.files[self.idx] }
|
||||
}
|
||||
|
||||
impl AsRef<yazi_fs::File> for File {
|
||||
|
|
@ -30,14 +35,26 @@ impl File {
|
|||
folder: &yazi_core::tab::Folder,
|
||||
tab: &yazi_core::tab::Tab,
|
||||
) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { idx, folder, tab })
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
Ok(match super::FILE_CACHE.borrow_mut().entry(PtrCell(&folder.files[idx])) {
|
||||
Entry::Occupied(oe) => oe.into_mut().clone(),
|
||||
Entry::Vacant(ve) => {
|
||||
let ud = Lives::scoped_userdata(Self {
|
||||
idx,
|
||||
folder: folder.into(),
|
||||
tab: tab.into(),
|
||||
|
||||
v_cha: None,
|
||||
v_url: None,
|
||||
v_link_to: None,
|
||||
v_name: None,
|
||||
})?;
|
||||
ve.insert(ud.clone());
|
||||
ud
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn folder(&self) -> &yazi_core::tab::Folder { unsafe { &*self.folder } }
|
||||
|
||||
#[inline]
|
||||
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
|
||||
}
|
||||
|
||||
impl UserData for File {
|
||||
|
|
@ -45,13 +62,17 @@ impl UserData for File {
|
|||
yazi_plugin::impl_file_fields!(fields);
|
||||
|
||||
fields.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
|
||||
fields.add_field_method_get("is_hovered", |_, me| Ok(me.idx == me.folder.cursor));
|
||||
fields.add_field_method_get("in_preview", |_, me| {
|
||||
Ok(me.tab.hovered().is_some_and(|f| f.url == me.folder.url))
|
||||
});
|
||||
}
|
||||
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
yazi_plugin::impl_file_methods!(methods);
|
||||
|
||||
methods.add_method("size", |_, me, ()| {
|
||||
Ok(if me.is_dir() { me.folder().files.sizes.get(me.urn()).copied() } else { Some(me.len) })
|
||||
Ok(if me.is_dir() { me.folder.files.sizes.get(me.urn()).copied() } else { Some(me.len) })
|
||||
});
|
||||
methods.add_method("mime", |lua, me, ()| {
|
||||
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|cx: &Ctx| {
|
||||
|
|
@ -59,11 +80,11 @@ impl UserData for File {
|
|||
})?
|
||||
});
|
||||
methods.add_method("prefix", |lua, me, ()| {
|
||||
if !me.folder().url.is_search() {
|
||||
if !me.folder.url.is_search() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut p = me.url.strip_prefix(&me.folder().url).unwrap_or(&me.url).components();
|
||||
let mut p = me.url.strip_prefix(&me.folder.url).unwrap_or(&me.url).components();
|
||||
p.next_back();
|
||||
Some(lua.create_string(p.as_path().as_os_str().as_encoded_bytes())).transpose()
|
||||
});
|
||||
|
|
@ -73,7 +94,6 @@ impl UserData for File {
|
|||
THEME.filetype.iter().find(|&x| x.matches(me, mime)).map(|x| Style::from(x.style))
|
||||
})
|
||||
});
|
||||
methods.add_method("is_hovered", |_, me, ()| Ok(me.idx == me.folder().cursor));
|
||||
methods.add_method("is_yanked", |lua, me, ()| {
|
||||
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|cx: &Ctx| {
|
||||
if !cx.mgr.yanked.contains(&me.url) {
|
||||
|
|
@ -87,24 +107,17 @@ impl UserData for File {
|
|||
});
|
||||
methods.add_method("is_marked", |_, me, ()| {
|
||||
use yazi_core::tab::Mode::*;
|
||||
if !me.tab().mode.is_visual() || me.folder().url != me.tab().current.url {
|
||||
if !me.tab.mode.is_visual() || me.folder.url != me.tab.current.url {
|
||||
return Ok(0u8);
|
||||
}
|
||||
|
||||
Ok(match &me.tab().mode {
|
||||
Ok(match &me.tab.mode {
|
||||
Select(_, indices) if indices.contains(&me.idx) => 1u8,
|
||||
Unset(_, indices) if indices.contains(&me.idx) => 2u8,
|
||||
_ => 0u8,
|
||||
})
|
||||
});
|
||||
methods.add_method("is_selected", |_, me, ()| Ok(me.tab().selected.contains_key(&me.url)));
|
||||
methods.add_method("in_parent", |_, me, ()| {
|
||||
Ok(me.tab().parent.as_ref().is_some_and(|f| me.folder().url == f.url))
|
||||
});
|
||||
methods.add_method("in_current", |_, me, ()| Ok(me.folder().url == me.tab().current.url));
|
||||
methods.add_method("in_preview", |_, me, ()| {
|
||||
Ok(me.tab().hovered().is_some_and(|f| f.url == me.folder().url))
|
||||
});
|
||||
methods.add_method("is_selected", |_, me, ()| Ok(me.tab.selected.contains_key(&me.url)));
|
||||
methods.add_method("found", |lua, me, ()| {
|
||||
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|cx: &Ctx| {
|
||||
let Some(finder) = &cx.active().finder else {
|
||||
|
|
@ -124,7 +137,7 @@ impl UserData for File {
|
|||
let Some(finder) = &cx.active().finder else {
|
||||
return None;
|
||||
};
|
||||
if me.folder().url != me.tab().current.url {
|
||||
if me.folder.url != me.tab.current.url {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,22 @@
|
|||
use std::ops::{Deref, Range};
|
||||
|
||||
use mlua::{AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMethods};
|
||||
use mlua::{AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMethods, Value};
|
||||
use yazi_binding::cached_field;
|
||||
|
||||
use super::{File, Filter, Lives};
|
||||
use super::{File, Filter, Lives, PtrCell};
|
||||
|
||||
pub(super) struct Files {
|
||||
window: Range<usize>,
|
||||
folder: *const yazi_core::tab::Folder,
|
||||
tab: *const yazi_core::tab::Tab,
|
||||
folder: PtrCell<yazi_core::tab::Folder>,
|
||||
tab: PtrCell<yazi_core::tab::Tab>,
|
||||
|
||||
v_filter: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Files {
|
||||
type Target = yazi_fs::Files;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.folder().files }
|
||||
fn deref(&self) -> &Self::Target { &self.folder.files }
|
||||
}
|
||||
|
||||
impl Files {
|
||||
|
|
@ -23,19 +26,13 @@ impl Files {
|
|||
folder: &yazi_core::tab::Folder,
|
||||
tab: &yazi_core::tab::Tab,
|
||||
) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { window, folder, tab })
|
||||
Lives::scoped_userdata(Self { window, folder: folder.into(), tab: tab.into(), v_filter: None })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn folder(&self) -> &yazi_core::tab::Folder { unsafe { &*self.folder } }
|
||||
|
||||
#[inline]
|
||||
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
|
||||
}
|
||||
|
||||
impl UserData for Files {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("filter", |_, me| me.filter().map(Filter::make).transpose());
|
||||
cached_field!(fields, filter, |_, me: &Self| me.filter().map(Filter::make).transpose());
|
||||
}
|
||||
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
|
|
@ -46,7 +43,7 @@ impl UserData for Files {
|
|||
if idx > me.window.end || idx == 0 {
|
||||
Ok(None)
|
||||
} else {
|
||||
Some(File::make(idx - 1, me.folder(), me.tab())).transpose()
|
||||
Some(File::make(idx - 1, &me.folder, &me.tab)).transpose()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,22 +2,22 @@ use std::ops::Deref;
|
|||
|
||||
use mlua::{AnyUserData, MetaMethod, UserData, UserDataMethods};
|
||||
|
||||
use super::Lives;
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Filter {
|
||||
inner: *const yazi_fs::Filter,
|
||||
inner: PtrCell<yazi_fs::Filter>,
|
||||
}
|
||||
|
||||
impl Deref for Filter {
|
||||
type Target = yazi_fs::Filter;
|
||||
|
||||
fn deref(&self) -> &Self::Target { unsafe { &*self.inner } }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
#[inline]
|
||||
pub(super) fn make(inner: &yazi_fs::Filter) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,22 +2,22 @@ use std::ops::Deref;
|
|||
|
||||
use mlua::{AnyUserData, MetaMethod, UserData, UserDataMethods};
|
||||
|
||||
use super::Lives;
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Finder {
|
||||
inner: *const yazi_core::tab::Finder,
|
||||
inner: PtrCell<yazi_core::tab::Finder>,
|
||||
}
|
||||
|
||||
impl Deref for Finder {
|
||||
type Target = yazi_core::tab::Finder;
|
||||
|
||||
fn deref(&self) -> &Self::Target { unsafe { &*self.inner } }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Finder {
|
||||
#[inline]
|
||||
pub(super) fn make(inner: &yazi_core::tab::Finder) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,27 @@
|
|||
use std::ops::{Deref, Range};
|
||||
|
||||
use mlua::{AnyUserData, IntoLuaMulti, Lua, MetaMethod, UserData, UserDataFields, UserDataMethods};
|
||||
use mlua::{AnyUserData, Lua, UserData, UserDataFields, Value};
|
||||
use yazi_binding::{FolderStage, Url, cached_field};
|
||||
use yazi_config::LAYOUT;
|
||||
use yazi_plugin::url::Url;
|
||||
|
||||
use super::{File, Files, Lives};
|
||||
use super::{File, Files, Lives, PtrCell};
|
||||
|
||||
pub(super) struct Folder {
|
||||
window: Range<usize>,
|
||||
inner: *const yazi_core::tab::Folder,
|
||||
tab: *const yazi_core::tab::Tab,
|
||||
inner: PtrCell<yazi_core::tab::Folder>,
|
||||
tab: PtrCell<yazi_core::tab::Tab>,
|
||||
|
||||
v_cwd: Option<Value>,
|
||||
v_files: Option<Value>,
|
||||
v_stage: Option<Value>,
|
||||
v_window: Option<Value>,
|
||||
v_hovered: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Folder {
|
||||
type Target = yazi_core::tab::Folder;
|
||||
|
||||
fn deref(&self) -> &Self::Target { unsafe { &*self.inner } }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Folder {
|
||||
|
|
@ -33,38 +39,31 @@ impl Folder {
|
|||
}
|
||||
};
|
||||
|
||||
Lives::scoped_userdata(Self { window, inner, tab })
|
||||
Lives::scoped_userdata(Self {
|
||||
window,
|
||||
inner: inner.into(),
|
||||
tab: tab.into(),
|
||||
|
||||
v_cwd: None,
|
||||
v_files: None,
|
||||
v_stage: None,
|
||||
v_window: None,
|
||||
v_hovered: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.register_userdata_type::<yazi_fs::FolderStage>(|reg| {
|
||||
use yazi_fs::FolderStage;
|
||||
|
||||
reg.add_meta_method(MetaMethod::Call, |lua, me, ()| match me {
|
||||
FolderStage::Loading => false.into_lua_multi(lua),
|
||||
FolderStage::Loaded => true.into_lua_multi(lua),
|
||||
FolderStage::Failed(kind) => (true, yazi_plugin::Error::IoKind(*kind)).into_lua_multi(lua),
|
||||
});
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
|
||||
}
|
||||
|
||||
impl UserData for Folder {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("cwd", |_, me| Ok(Url(me.url.to_owned())));
|
||||
fields.add_field_method_get("files", |_, me| Files::make(0..me.files.len(), me, me.tab()));
|
||||
fields.add_field_method_get("stage", |lua, me| lua.create_any_userdata(me.stage));
|
||||
fields.add_field_method_get("window", |_, me| Files::make(me.window.clone(), me, me.tab()));
|
||||
cached_field!(fields, cwd, |_, me: &Self| Ok(Url::new(me.url.to_owned())));
|
||||
cached_field!(fields, files, |_, me: &Self| Files::make(0..me.files.len(), me, &me.tab));
|
||||
cached_field!(fields, stage, |_: &Lua, me: &Self| Ok(FolderStage::new(me.stage)));
|
||||
cached_field!(fields, window, |_, me: &Self| Files::make(me.window.clone(), me, &me.tab));
|
||||
|
||||
fields.add_field_method_get("offset", |_, me| Ok(me.offset));
|
||||
fields.add_field_method_get("cursor", |_, me| Ok(me.cursor));
|
||||
fields.add_field_method_get("hovered", |_, me| {
|
||||
me.hovered().map(|_| File::make(me.cursor, me, me.tab())).transpose()
|
||||
cached_field!(fields, hovered, |_, me: &Self| {
|
||||
me.hovered().map(|_| File::make(me.cursor, me, &me.tab)).transpose()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,26 @@
|
|||
use std::cell::RefCell;
|
||||
|
||||
use foldhash::HashMap;
|
||||
use mlua::{AnyUserData, UserData};
|
||||
use scopeguard::defer;
|
||||
use tracing::error;
|
||||
use yazi_plugin::LUA;
|
||||
use yazi_shared::RoCell;
|
||||
|
||||
use super::PtrCell;
|
||||
use crate::Ctx;
|
||||
|
||||
static TO_DESTROY: RoCell<RefCell<Vec<AnyUserData>>> = RoCell::new_const(RefCell::new(Vec::new()));
|
||||
pub(super) static FILE_CACHE: RoCell<RefCell<HashMap<PtrCell<yazi_fs::File>, AnyUserData>>> =
|
||||
RoCell::new();
|
||||
|
||||
pub(crate) struct Lives;
|
||||
|
||||
impl Lives {
|
||||
pub(crate) fn register() -> mlua::Result<()> {
|
||||
super::Folder::register(&LUA)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn scope<T>(cx: &Ctx, f: impl FnOnce() -> mlua::Result<T>) -> mlua::Result<T> {
|
||||
FILE_CACHE.init(Default::default());
|
||||
defer! { FILE_CACHE.drop(); }
|
||||
|
||||
let result = LUA.scope(|scope| {
|
||||
scope.add_destructor(|| {
|
||||
for ud in TO_DESTROY.borrow_mut().drain(..) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(context file files filter finder folder iter lives mode preference preview selected tab tabs tasks yanked);
|
||||
yazi_macro::mod_flat!(context file files filter finder folder iter lives mode preference preview ptr selected tab tabs tasks yanked);
|
||||
|
|
|
|||
|
|
@ -2,22 +2,22 @@ use std::ops::Deref;
|
|||
|
||||
use mlua::{AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMethods};
|
||||
|
||||
use super::Lives;
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Mode {
|
||||
inner: *const yazi_core::tab::Mode,
|
||||
inner: PtrCell<yazi_core::tab::Mode>,
|
||||
}
|
||||
|
||||
impl Deref for Mode {
|
||||
type Target = yazi_core::tab::Mode;
|
||||
|
||||
fn deref(&self) -> &Self::Target { unsafe { &*self.inner } }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
#[inline]
|
||||
pub(super) fn make(inner: &yazi_core::tab::Mode) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,35 +1,39 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataFields};
|
||||
use mlua::{AnyUserData, UserData, UserDataFields, Value};
|
||||
use yazi_binding::cached_field;
|
||||
|
||||
use super::Lives;
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Preference {
|
||||
inner: *const yazi_core::tab::Preference,
|
||||
inner: PtrCell<yazi_core::tab::Preference>,
|
||||
|
||||
v_sort_by: Option<Value>,
|
||||
v_linemode: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Preference {
|
||||
type Target = yazi_core::tab::Preference;
|
||||
|
||||
fn deref(&self) -> &Self::Target { unsafe { &*self.inner } }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Preference {
|
||||
#[inline]
|
||||
pub(super) fn make(inner: &yazi_core::tab::Preference) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
Lives::scoped_userdata(Self { inner: inner.into(), v_sort_by: None, v_linemode: None })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Preference {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("sort_by", |_, me| Ok(me.sort_by.to_string()));
|
||||
cached_field!(fields, sort_by, |_, me: &Self| Ok(me.sort_by.to_string()));
|
||||
fields.add_field_method_get("sort_sensitive", |_, me| Ok(me.sort_sensitive));
|
||||
fields.add_field_method_get("sort_reverse", |_, me| Ok(me.sort_reverse));
|
||||
fields.add_field_method_get("sort_dir_first", |_, me| Ok(me.sort_dir_first));
|
||||
fields.add_field_method_get("sort_translit", |_, me| Ok(me.sort_translit));
|
||||
|
||||
fields.add_field_method_get("linemode", |_, me| Ok(me.linemode.to_owned()));
|
||||
cached_field!(fields, linemode, |_, me: &Self| Ok(me.linemode.to_string()));
|
||||
fields.add_field_method_get("show_hidden", |_, me| Ok(me.show_hidden));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,39 +1,39 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataFields};
|
||||
use mlua::{AnyUserData, UserData, UserDataFields, Value};
|
||||
use yazi_binding::cached_field;
|
||||
use yazi_config::LAYOUT;
|
||||
|
||||
use super::{Folder, Lives};
|
||||
use super::{Folder, Lives, PtrCell};
|
||||
|
||||
pub(super) struct Preview {
|
||||
tab: *const yazi_core::tab::Tab,
|
||||
tab: PtrCell<yazi_core::tab::Tab>,
|
||||
|
||||
v_folder: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Preview {
|
||||
type Target = yazi_core::tab::Preview;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.tab().preview }
|
||||
fn deref(&self) -> &Self::Target { &self.tab.preview }
|
||||
}
|
||||
|
||||
impl Preview {
|
||||
#[inline]
|
||||
pub(super) fn make(tab: &yazi_core::tab::Tab) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { tab })
|
||||
Lives::scoped_userdata(Self { tab: tab.into(), v_folder: None })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
|
||||
}
|
||||
|
||||
impl UserData for Preview {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("skip", |_, me| Ok(me.skip));
|
||||
fields.add_field_method_get("folder", |_, me| {
|
||||
me.tab()
|
||||
cached_field!(fields, folder, |_, me: &Self| {
|
||||
me.tab
|
||||
.hovered_folder()
|
||||
.map(|f| {
|
||||
let limit = LAYOUT.get().preview.height as usize;
|
||||
Folder::make(Some(me.skip..f.files.len().min(me.skip + limit)), f, me.tab())
|
||||
Folder::make(Some(me.skip..f.files.len().min(me.skip + limit)), f, &me.tab)
|
||||
})
|
||||
.transpose()
|
||||
});
|
||||
|
|
|
|||
34
yazi-fm/src/lives/ptr.rs
Normal file
34
yazi-fm/src/lives/ptr.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use std::{hash::{Hash, Hasher}, ops::Deref};
|
||||
|
||||
pub(super) struct PtrCell<T>(pub(super) *const T);
|
||||
|
||||
impl<T> Deref for PtrCell<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target { unsafe { &*self.0 } }
|
||||
}
|
||||
|
||||
impl<T> From<&T> for PtrCell<T> {
|
||||
fn from(value: &T) -> Self { Self(value) }
|
||||
}
|
||||
|
||||
impl<T> Clone for PtrCell<T> {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
impl<T> Copy for PtrCell<T> {}
|
||||
|
||||
impl<T> PartialEq for PtrCell<T> {
|
||||
fn eq(&self, other: &Self) -> bool { self.0.addr() == other.0.addr() }
|
||||
}
|
||||
|
||||
impl<T> Eq for PtrCell<T> {}
|
||||
|
||||
impl<T> Hash for PtrCell<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) { state.write_usize(self.0.addr()); }
|
||||
}
|
||||
|
||||
impl<T> PtrCell<T> {
|
||||
#[inline]
|
||||
pub(super) fn as_static(&self) -> &'static T { unsafe { &*self.0 } }
|
||||
}
|
||||
|
|
@ -2,29 +2,26 @@ use std::ops::Deref;
|
|||
|
||||
use indexmap::{IndexMap, map::Keys};
|
||||
use mlua::{AnyUserData, IntoLuaMulti, MetaMethod, UserData, UserDataMethods, UserDataRefMut};
|
||||
use yazi_plugin::url::Url;
|
||||
use yazi_binding::Url;
|
||||
|
||||
use super::{Iter, Lives};
|
||||
use super::{Iter, Lives, PtrCell};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) struct Selected {
|
||||
inner: *const IndexMap<yazi_shared::url::Url, u64>,
|
||||
inner: PtrCell<IndexMap<yazi_shared::url::Url, u64>>,
|
||||
}
|
||||
|
||||
impl Deref for Selected {
|
||||
type Target = IndexMap<yazi_shared::url::Url, u64>;
|
||||
|
||||
fn deref(&self) -> &Self::Target { self.inner() }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Selected {
|
||||
#[inline]
|
||||
pub(super) fn make(inner: &IndexMap<yazi_shared::url::Url, u64>) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inner(&self) -> &'static IndexMap<yazi_shared::url::Url, u64> { unsafe { &*self.inner } }
|
||||
}
|
||||
|
||||
impl UserData for Selected {
|
||||
|
|
@ -35,14 +32,14 @@ impl UserData for Selected {
|
|||
let iter = lua.create_function(
|
||||
|lua, mut iter: UserDataRefMut<Iter<Keys<yazi_shared::url::Url, u64>, _>>| {
|
||||
if let Some(next) = iter.next() {
|
||||
(next.0, Url(next.1.clone())).into_lua_multi(lua)
|
||||
(next.0, Url::new(next.1.clone())).into_lua_multi(lua)
|
||||
} else {
|
||||
().into_lua_multi(lua)
|
||||
}
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok((iter, Iter::make(me.inner().keys())))
|
||||
Ok((iter, Iter::make(me.inner.as_static().keys())))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,69 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataFields, UserDataMethods};
|
||||
use yazi_plugin::url::UrlRef;
|
||||
use mlua::{AnyUserData, Lua, UserData, UserDataFields, UserDataMethods, Value};
|
||||
use yazi_binding::{UrlRef, cached_field};
|
||||
use yazi_plugin::Id;
|
||||
|
||||
use super::{Finder, Folder, Lives, Mode, Preference, Preview, Selected};
|
||||
use super::{Finder, Folder, Lives, Mode, Preference, Preview, PtrCell, Selected};
|
||||
|
||||
pub(super) struct Tab {
|
||||
inner: *const yazi_core::tab::Tab,
|
||||
inner: PtrCell<yazi_core::tab::Tab>,
|
||||
|
||||
v_name: Option<Value>,
|
||||
v_mode: Option<Value>,
|
||||
v_pref: Option<Value>,
|
||||
v_current: Option<Value>,
|
||||
v_parent: Option<Value>,
|
||||
v_selected: Option<Value>,
|
||||
v_preview: Option<Value>,
|
||||
v_finder: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Tab {
|
||||
type Target = yazi_core::tab::Tab;
|
||||
|
||||
fn deref(&self) -> &Self::Target { unsafe { &*self.inner } }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Tab {
|
||||
#[inline]
|
||||
pub(super) fn make(inner: &yazi_core::tab::Tab) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
Lives::scoped_userdata(Self {
|
||||
inner: inner.into(),
|
||||
|
||||
v_name: None,
|
||||
v_mode: None,
|
||||
v_pref: None,
|
||||
v_current: None,
|
||||
v_parent: None,
|
||||
v_selected: None,
|
||||
v_preview: None,
|
||||
v_finder: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Tab {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("id", |_, me| Ok(me.id.get()));
|
||||
fields.add_field_method_get("mode", |_, me| Mode::make(&me.mode));
|
||||
fields.add_field_method_get("pref", |_, me| Preference::make(&me.pref));
|
||||
fields.add_field_method_get("current", |_, me| Folder::make(None, &me.current, me));
|
||||
fields.add_field_method_get("parent", |_, me| {
|
||||
fields.add_field_method_get("id", |_, me| Ok(Id(me.id)));
|
||||
cached_field!(fields, name, |lua: &Lua, me: &Self| {
|
||||
lua.create_string(me.current.url.name().as_encoded_bytes())
|
||||
});
|
||||
|
||||
cached_field!(fields, mode, |_, me: &Self| Mode::make(&me.mode));
|
||||
cached_field!(fields, pref, |_, me: &Self| Preference::make(&me.pref));
|
||||
cached_field!(fields, current, |_, me: &Self| Folder::make(None, &me.current, me));
|
||||
cached_field!(fields, parent, |_, me: &Self| {
|
||||
me.parent.as_ref().map(|f| Folder::make(None, f, me)).transpose()
|
||||
});
|
||||
|
||||
fields.add_field_method_get("selected", |_, me| Selected::make(&me.selected));
|
||||
cached_field!(fields, selected, |_, me: &Self| Selected::make(&me.selected));
|
||||
|
||||
fields.add_field_method_get("preview", |_, me| Preview::make(me));
|
||||
fields.add_field_method_get("finder", |_, me| me.finder.as_ref().map(Finder::make).transpose());
|
||||
cached_field!(fields, preview, |_, me: &Self| Preview::make(me));
|
||||
cached_field!(fields, finder, |_, me: &Self| me.finder.as_ref().map(Finder::make).transpose());
|
||||
}
|
||||
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_method("name", |lua, me, ()| {
|
||||
lua.create_string(me.current.url.name().as_encoded_bytes())
|
||||
});
|
||||
methods.add_method("history", |_, me, url: UrlRef| {
|
||||
me.history.get(&url).map(|f| Folder::make(None, f, me)).transpose()
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,22 +2,22 @@ use std::ops::Deref;
|
|||
|
||||
use mlua::{AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMethods};
|
||||
|
||||
use super::{Lives, Tab};
|
||||
use super::{Lives, PtrCell, Tab};
|
||||
|
||||
pub(super) struct Tabs {
|
||||
inner: *const yazi_core::mgr::Tabs,
|
||||
inner: PtrCell<yazi_core::mgr::Tabs>,
|
||||
}
|
||||
|
||||
impl Deref for Tabs {
|
||||
type Target = yazi_core::mgr::Tabs;
|
||||
|
||||
fn deref(&self) -> &Self::Target { unsafe { &*self.inner } }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Tabs {
|
||||
#[inline]
|
||||
pub(super) fn make(inner: &yazi_core::mgr::Tabs) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,31 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, LuaSerdeExt, UserData, UserDataFields};
|
||||
use mlua::{AnyUserData, Lua, LuaSerdeExt, UserData, UserDataFields, Value};
|
||||
use yazi_binding::cached_field;
|
||||
|
||||
use super::Lives;
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Tasks {
|
||||
inner: *const yazi_core::tasks::Tasks,
|
||||
inner: PtrCell<yazi_core::tasks::Tasks>,
|
||||
|
||||
v_progress: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Tasks {
|
||||
type Target = yazi_core::tasks::Tasks;
|
||||
|
||||
fn deref(&self) -> &Self::Target { unsafe { &*self.inner } }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Tasks {
|
||||
#[inline]
|
||||
pub(super) fn make(inner: &yazi_core::tasks::Tasks) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
Lives::scoped_userdata(Self { inner: inner.into(), v_progress: None })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Tasks {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("progress", |lua, me| lua.to_value(&me.progress))
|
||||
cached_field!(fields, progress, |lua: &Lua, me: &Self| lua.to_value(&me.progress));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,25 @@
|
|||
use std::{collections::hash_set, ops::Deref};
|
||||
|
||||
use mlua::{AnyUserData, IntoLuaMulti, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRefMut};
|
||||
use yazi_plugin::url::Url;
|
||||
use yazi_binding::Url;
|
||||
|
||||
use super::{Iter, Lives};
|
||||
use super::{Iter, Lives, PtrCell};
|
||||
|
||||
pub(super) struct Yanked {
|
||||
inner: *const yazi_core::mgr::Yanked,
|
||||
inner: PtrCell<yazi_core::mgr::Yanked>,
|
||||
}
|
||||
|
||||
impl Deref for Yanked {
|
||||
type Target = yazi_core::mgr::Yanked;
|
||||
|
||||
fn deref(&self) -> &Self::Target { self.inner() }
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Yanked {
|
||||
#[inline]
|
||||
pub(super) fn make(inner: &yazi_core::mgr::Yanked) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inner(&self) -> &'static yazi_core::mgr::Yanked { unsafe { &*self.inner } }
|
||||
}
|
||||
|
||||
impl UserData for Yanked {
|
||||
|
|
@ -37,14 +34,14 @@ impl UserData for Yanked {
|
|||
let iter = lua.create_function(
|
||||
|lua, mut iter: UserDataRefMut<Iter<hash_set::Iter<yazi_shared::url::Url>, _>>| {
|
||||
if let Some(next) = iter.next() {
|
||||
(next.0, Url(next.1.clone())).into_lua_multi(lua)
|
||||
(next.0, Url::new(next.1.clone())).into_lua_multi(lua)
|
||||
} else {
|
||||
().into_lua_multi(lua)
|
||||
}
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok((iter, Iter::make(me.inner().iter())))
|
||||
Ok((iter, Iter::make(me.inner.as_static().iter())))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ impl Panic {
|
|||
std::panic::set_hook(Box::new(move |info| {
|
||||
Term::goodbye(|| {
|
||||
hook(info);
|
||||
true
|
||||
1
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ impl Term {
|
|||
Ok(disable_raw_mode()?)
|
||||
}
|
||||
|
||||
pub(super) fn goodbye(f: impl FnOnce() -> bool) -> ! {
|
||||
pub(super) fn goodbye(f: impl FnOnce() -> i32) -> ! {
|
||||
if CSI_U.swap(false, Ordering::Relaxed) {
|
||||
PopKeyboardEnhancementFlags.write_ansi(&mut TTY.writer()).ok();
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ impl Term {
|
|||
|
||||
disable_raw_mode().ok();
|
||||
|
||||
std::process::exit(f() as i32);
|
||||
std::process::exit(f());
|
||||
}
|
||||
|
||||
pub(super) fn draw(&mut self, f: impl FnOnce(&mut Frame)) -> io::Result<CompletedFrame> {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-fs"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
@ -9,9 +9,9 @@ homepage = "https://yazi-rs.github.io"
|
|||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[dependencies]
|
||||
yazi-ffi = { path = "../yazi-ffi", version = "25.3.7" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-ffi = { path = "../yazi-ffi", version = "25.4.8" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -63,14 +63,13 @@ impl Step {
|
|||
Self::Percent(n) => n as isize * limit as isize / 100,
|
||||
};
|
||||
|
||||
if fixed == 0 {
|
||||
pos
|
||||
} else if matches!(self, Self::Prev | Self::Next) {
|
||||
if matches!(self, Self::Prev | Self::Next) {
|
||||
fixed.saturating_add_unsigned(pos).rem_euclid(len as _) as _
|
||||
} else if fixed > 0 {
|
||||
pos.saturating_add_signed(fixed).min(len - 1)
|
||||
} else if fixed >= 0 {
|
||||
pos.saturating_add_signed(fixed)
|
||||
} else {
|
||||
pos.saturating_sub(fixed.unsigned_abs())
|
||||
}
|
||||
.min(len - 1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-macro"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ macro_rules! render {
|
|||
render!();
|
||||
}
|
||||
};
|
||||
($left:expr, > $right:expr) => {{
|
||||
let val = $left;
|
||||
if val > $right {
|
||||
render!();
|
||||
}
|
||||
val
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "yazi-plugin"
|
||||
version = "25.3.7"
|
||||
version = "25.4.8"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
|
|
@ -13,14 +13,15 @@ default = [ "vendored-lua" ]
|
|||
vendored-lua = [ "mlua/vendored" ]
|
||||
|
||||
[dependencies]
|
||||
yazi-adapter = { path = "../yazi-adapter", version = "25.3.7" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.3.7" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.3.7" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.3.7" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.3.7" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.3.7" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "25.3.7" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
yazi-adapter = { path = "../yazi-adapter", version = "25.4.8" }
|
||||
yazi-binding = { path = "../yazi-binding", version = "25.4.8" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.4.8" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.4.8" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.4.8" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.4.8" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.4.8" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "25.4.8" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.4.8" }
|
||||
|
||||
# External dependencies
|
||||
ansi-to-tui = { workspace = true }
|
||||
|
|
@ -32,6 +33,7 @@ globset = { workspace = true }
|
|||
md-5 = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
ratatui = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
syntect = { workspace = true }
|
||||
|
|
@ -44,10 +46,12 @@ unicode-width = { workspace = true }
|
|||
yazi-prebuilt = "0.1.0"
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
libc = { workspace = true }
|
||||
uzers = { workspace = true }
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
clipboard-win = "5.4.0"
|
||||
windows-sys = { version = "0.59.0", features = [ "Win32_Security", "Win32_System_JobObjects", "Win32_System_Threading" ] }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
crossterm = { workspace = true, features = [ "use-dev-tty", "libc" ] }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ function Entity:icon()
|
|||
local icon = self._file:icon()
|
||||
if not icon then
|
||||
return ""
|
||||
elseif self._file:is_hovered() then
|
||||
elseif self._file.is_hovered then
|
||||
return icon.text .. " "
|
||||
else
|
||||
return ui.Line(icon.text .. " "):style(icon.style)
|
||||
|
|
@ -52,7 +52,7 @@ function Entity:highlights()
|
|||
end
|
||||
|
||||
function Entity:found()
|
||||
if not self._file:is_hovered() then
|
||||
if not self._file.is_hovered then
|
||||
return ""
|
||||
end
|
||||
|
||||
|
|
@ -86,9 +86,9 @@ end
|
|||
|
||||
function Entity:style()
|
||||
local s = self._file:style()
|
||||
if not self._file:is_hovered() then
|
||||
if not self._file.is_hovered then
|
||||
return s
|
||||
elseif self._file:in_preview() then
|
||||
elseif self._file.in_preview then
|
||||
return s and s:patch(th.mgr.preview_hovered) or th.mgr.preview_hovered
|
||||
else
|
||||
return s and s:patch(th.mgr.hovered) or th.mgr.hovered
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ function Header:flags()
|
|||
|
||||
local t = {}
|
||||
if cwd.is_search then
|
||||
t[#t + 1] = string.format("search: %s", cwd:frag())
|
||||
t[#t + 1] = string.format("search: %s", cwd.frag)
|
||||
end
|
||||
if filter then
|
||||
t[#t + 1] = string.format("filter: %s", filter)
|
||||
|
|
@ -84,7 +84,7 @@ function Header:tabs()
|
|||
for i = 1, tabs do
|
||||
local text = i
|
||||
if th.mgr.tab_width > 2 then
|
||||
text = ya.truncate(text .. " " .. cx.tabs[i]:name(), { max = th.mgr.tab_width })
|
||||
text = ya.truncate(text .. " " .. cx.tabs[i].name, { max = th.mgr.tab_width })
|
||||
end
|
||||
if i == cx.tabs.idx then
|
||||
spans[#spans + 1] = ui.Span(" " .. text .. " "):style(th.mgr.tab_active)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ function M:entry(job)
|
|||
end
|
||||
|
||||
local value, event = ya.input {
|
||||
title = string.format('Password for "%s":', from:name()),
|
||||
title = string.format('Password for "%s":', from.name),
|
||||
position = { "center", w = 50 },
|
||||
}
|
||||
if event == 1 then
|
||||
|
|
@ -39,7 +39,7 @@ function M:entry(job)
|
|||
end
|
||||
|
||||
function M:try_with(from, pwd, to)
|
||||
to = to or from:parent()
|
||||
to = to or from.parent
|
||||
if not to then
|
||||
fail("Invalid URL '%s'", from)
|
||||
end
|
||||
|
|
@ -90,7 +90,7 @@ function M:tidy(from, to, tmp)
|
|||
if only then
|
||||
target = to:join(outs[1].name)
|
||||
else
|
||||
target = to:join(self.trim_ext(from:name()))
|
||||
target = to:join(self.trim_ext(from.name))
|
||||
end
|
||||
|
||||
target = fs.unique_name(target)
|
||||
|
|
|
|||
|
|
@ -1,29 +1,73 @@
|
|||
local state = ya.sync(function() return cx.active.current.cwd end)
|
||||
local M = {}
|
||||
|
||||
local function fail(s, ...) ya.notify { title = "Fzf", content = string.format(s, ...), timeout = 5, level = "error" } end
|
||||
local state = ya.sync(function()
|
||||
local selected = {}
|
||||
for _, url in pairs(cx.active.selected) do
|
||||
selected[#selected + 1] = url
|
||||
end
|
||||
return cx.active.current.cwd, selected
|
||||
end)
|
||||
|
||||
function M:entry()
|
||||
ya.mgr_emit("escape", { visual = true })
|
||||
|
||||
local function entry()
|
||||
local _permit = ya.hide()
|
||||
local cwd = tostring(state())
|
||||
local cwd, selected = state()
|
||||
|
||||
local child, err =
|
||||
Command("fzf"):cwd(cwd):stdin(Command.INHERIT):stdout(Command.PIPED):stderr(Command.INHERIT):spawn()
|
||||
local output, err = M.run_with(cwd, selected)
|
||||
if not output then
|
||||
return ya.notify { title = "Fzf", content = tostring(err), timeout = 5, level = "error" }
|
||||
end
|
||||
|
||||
local urls = M.split_urls(cwd, output)
|
||||
if #urls == 1 then
|
||||
local cha = #selected == 0 and fs.cha(urls[1])
|
||||
ya.mgr_emit(cha and cha.is_dir and "cd" or "reveal", { urls[1] })
|
||||
elseif #urls > 1 then
|
||||
urls.state = #selected > 0 and "off" or "on"
|
||||
ya.mgr_emit("toggle_all", urls)
|
||||
end
|
||||
end
|
||||
|
||||
function M.run_with(cwd, selected)
|
||||
local child, err = Command("fzf")
|
||||
:arg("-m")
|
||||
:cwd(tostring(cwd))
|
||||
:stdin(#selected > 0 and Command.PIPED or Command.INHERIT)
|
||||
:stdout(Command.PIPED)
|
||||
:spawn()
|
||||
|
||||
if not child then
|
||||
return fail("Failed to start `fzf`, error: " .. err)
|
||||
return nil, Err("Failed to start `fzf`, error: %s", err)
|
||||
end
|
||||
|
||||
for _, u in ipairs(selected) do
|
||||
child:write_all(string.format("%s\n", u))
|
||||
end
|
||||
if #selected > 0 then
|
||||
child:flush()
|
||||
end
|
||||
|
||||
local output, err = child:wait_with_output()
|
||||
if not output then
|
||||
return fail("Cannot read `fzf` output, error: " .. err)
|
||||
return nil, Err("Cannot read `fzf` output, error: %s", err)
|
||||
elseif not output.status.success and output.status.code ~= 130 then
|
||||
return fail("`fzf` exited with error code %s", output.status.code)
|
||||
end
|
||||
|
||||
local target = output.stdout:gsub("\n$", "")
|
||||
if target ~= "" then
|
||||
ya.mgr_emit(target:find("[/\\]$") and "cd" or "reveal", { target })
|
||||
return nil, Err("`fzf` exited with error code %s", output.status.code)
|
||||
end
|
||||
return output.stdout, nil
|
||||
end
|
||||
|
||||
return { entry = entry }
|
||||
function M.split_urls(cwd, output)
|
||||
local t = {}
|
||||
for line in output:gmatch("[^\r\n]+") do
|
||||
local u = Url(line)
|
||||
if u.is_absolute then
|
||||
t[#t + 1] = u
|
||||
else
|
||||
t[#t + 1] = cwd:join(u)
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ function M:preload(job)
|
|||
return true
|
||||
end
|
||||
|
||||
local cmd = M.with_env()
|
||||
local cmd = M.with_limit()
|
||||
if job.args.flatten then
|
||||
cmd = cmd:arg("-flatten")
|
||||
end
|
||||
|
|
@ -46,10 +46,16 @@ end
|
|||
|
||||
function M:spot(job) require("file"):spot(job) end
|
||||
|
||||
function M.with_env()
|
||||
local cmd = Command("magick"):env("MAGICK_THREAD_LIMIT", 1)
|
||||
function M.with_limit()
|
||||
local cmd = Command("magick"):args { "-limit", "thread", 1 }
|
||||
if rt.tasks.image_alloc > 0 then
|
||||
cmd = cmd:env("MAGICK_MEMORY_LIMIT", rt.tasks.image_alloc)
|
||||
cmd = cmd:args({ "-limit", "memory", rt.tasks.image_alloc }):args { "-limit", "disk", "1MiB" }
|
||||
end
|
||||
if rt.tasks.image_bound[1] > 0 then
|
||||
cmd = cmd:args { "-limit", "width", rt.tasks.image_bound[1] }
|
||||
end
|
||||
if rt.tasks.image_bound[2] > 0 then
|
||||
cmd = cmd:args { "-limit", "height", rt.tasks.image_bound[2] }
|
||||
end
|
||||
return cmd
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,19 +25,44 @@ function M:preload(job)
|
|||
end
|
||||
|
||||
-- stylua: ignore
|
||||
local cmd = require("magick").with_env():args {
|
||||
"-density", 200,
|
||||
tostring(job.file.url), "-strip",
|
||||
"-resize", string.format("%dx%d^", rt.preview.max_width, rt.preview.max_height),
|
||||
"-quality", rt.preview.image_quality,
|
||||
string.format("JPG:%s", cache),
|
||||
local cmd = Command("resvg"):args {
|
||||
"-w", rt.preview.max_width, "-h", rt.preview.max_height,
|
||||
"--image-rendering", "optimizeSpeed",
|
||||
tostring(job.file.url), tostring(cache)
|
||||
}
|
||||
if rt.tasks.image_alloc > 0 then
|
||||
cmd = cmd:memory(rt.tasks.image_alloc)
|
||||
end
|
||||
|
||||
local child, err = cmd:spawn()
|
||||
if not child then
|
||||
return true, Err("Failed to start `resvg`, error: %s", err)
|
||||
end
|
||||
|
||||
local status, err
|
||||
while true do
|
||||
ya.sleep(0.2)
|
||||
|
||||
status, err = child:try_wait()
|
||||
if status or err then
|
||||
break
|
||||
end
|
||||
|
||||
local id, mem = child:id(), nil
|
||||
if id then
|
||||
mem = ya.proc_info(id).mem_resident
|
||||
end
|
||||
if mem and mem > rt.tasks.image_alloc then
|
||||
child:start_kill()
|
||||
err = Err("memory limit exceeded, pid: %s, memory: %s", id, mem)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local status, err = cmd:status()
|
||||
if status then
|
||||
return status.success
|
||||
else
|
||||
return true, Err("Failed to start `magick`, error: %s", err)
|
||||
return true, Err("Error while running `resvg`: %s", err)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ function M:preload(job)
|
|||
"-i", tostring(job.file.url),
|
||||
"-vframes", 1,
|
||||
"-q:v", qv,
|
||||
"-vf", string.format("scale=-1:'min(%d,ih)':flags=fast_bilinear", rt.preview.max_height),
|
||||
"-vf", string.format("scale='min(%d,iw)':'min(%d,ih)':force_original_aspect_ratio=decrease:flags=fast_bilinear", rt.preview.max_width, rt.preview.max_height),
|
||||
"-f", "image2",
|
||||
"-y", tostring(cache),
|
||||
}):status()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use mlua::{ExternalError, IntoLuaMulti, UserData, Value};
|
||||
|
||||
use crate::Error;
|
||||
use yazi_binding::Error;
|
||||
|
||||
pub struct MpscTx(pub tokio::sync::mpsc::Sender<Value>);
|
||||
pub struct MpscRx(pub tokio::sync::mpsc::Receiver<Value>);
|
||||
|
|
|
|||
|
|
@ -1,24 +1,32 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{UserData, UserDataFields};
|
||||
use mlua::{Lua, UserData, UserDataFields, Value};
|
||||
use yazi_binding::cached_field;
|
||||
|
||||
use crate::elements::Style;
|
||||
|
||||
pub struct Icon(&'static yazi_shared::theme::Icon);
|
||||
pub struct Icon {
|
||||
inner: &'static yazi_shared::theme::Icon,
|
||||
|
||||
v_text: Option<Value>,
|
||||
v_style: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Icon {
|
||||
type Target = yazi_shared::theme::Icon;
|
||||
|
||||
fn deref(&self) -> &Self::Target { self.0 }
|
||||
fn deref(&self) -> &Self::Target { self.inner }
|
||||
}
|
||||
|
||||
impl From<&'static yazi_shared::theme::Icon> for Icon {
|
||||
fn from(icon: &'static yazi_shared::theme::Icon) -> Self { Self(icon) }
|
||||
fn from(icon: &'static yazi_shared::theme::Icon) -> Self {
|
||||
Self { inner: icon, v_text: None, v_style: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Icon {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("text", |lua, me| lua.create_string(&me.text));
|
||||
fields.add_field_method_get("style", |_, me| Ok(Style::from(me.style)));
|
||||
cached_field!(fields, text, |lua: &Lua, me: &Self| lua.create_string(&me.text));
|
||||
cached_field!(fields, style, |_, me: &Self| Ok(Style::from(me.style)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use mlua::{Function, IntoLua, Lua, UserData, Value};
|
||||
use yazi_binding::{UrlRef, cached_field};
|
||||
use yazi_config::YAZI;
|
||||
|
||||
use crate::{Composer, file::FileRef, url::UrlRef};
|
||||
use crate::{Composer, file::FileRef};
|
||||
|
||||
pub(super) struct Plugin;
|
||||
|
||||
|
|
@ -21,61 +22,93 @@ impl Plugin {
|
|||
|
||||
fn fetchers(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (file, mime): (FileRef, mlua::String)| {
|
||||
lua.create_sequence_from(YAZI.plugin.fetchers(&file.url, &mime.to_str()?).map(Fetcher))
|
||||
lua.create_sequence_from(YAZI.plugin.fetchers(&file.url, &mime.to_str()?).map(Fetcher::new))
|
||||
})
|
||||
}
|
||||
|
||||
fn spotter(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|_, (url, mime): (UrlRef, mlua::String)| {
|
||||
Ok(YAZI.plugin.spotter(&url, &mime.to_str()?).map(Spotter))
|
||||
Ok(YAZI.plugin.spotter(&url, &mime.to_str()?).map(Spotter::new))
|
||||
})
|
||||
}
|
||||
|
||||
fn preloaders(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (url, mime): (UrlRef, mlua::String)| {
|
||||
lua.create_sequence_from(YAZI.plugin.preloaders(&url, &mime.to_str()?).map(Preloader))
|
||||
lua.create_sequence_from(YAZI.plugin.preloaders(&url, &mime.to_str()?).map(Preloader::new))
|
||||
})
|
||||
}
|
||||
|
||||
fn previewer(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|_, (url, mime): (UrlRef, mlua::String)| {
|
||||
Ok(YAZI.plugin.previewer(&url, &mime.to_str()?).map(Previewer))
|
||||
Ok(YAZI.plugin.previewer(&url, &mime.to_str()?).map(Previewer::new))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// --- Fetcher
|
||||
struct Fetcher(&'static yazi_config::plugin::Fetcher);
|
||||
struct Fetcher {
|
||||
inner: &'static yazi_config::plugin::Fetcher,
|
||||
|
||||
v_cmd: Option<Value>,
|
||||
}
|
||||
|
||||
impl Fetcher {
|
||||
pub fn new(inner: &'static yazi_config::plugin::Fetcher) -> Self { Self { inner, v_cmd: None } }
|
||||
}
|
||||
|
||||
impl UserData for Fetcher {
|
||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("cmd", |lua, me| lua.create_string(&me.0.run.name));
|
||||
cached_field!(fields, cmd, |lua: &Lua, me: &Self| lua.create_string(&me.inner.run.name));
|
||||
}
|
||||
}
|
||||
|
||||
// --- Spotter
|
||||
struct Spotter(&'static yazi_config::plugin::Spotter);
|
||||
struct Spotter {
|
||||
inner: &'static yazi_config::plugin::Spotter,
|
||||
|
||||
v_cmd: Option<Value>,
|
||||
}
|
||||
|
||||
impl Spotter {
|
||||
pub fn new(inner: &'static yazi_config::plugin::Spotter) -> Self { Self { inner, v_cmd: None } }
|
||||
}
|
||||
|
||||
impl UserData for Spotter {
|
||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("cmd", |lua, me| lua.create_string(&me.0.run.name));
|
||||
cached_field!(fields, cmd, |lua: &Lua, me: &Self| lua.create_string(&me.inner.run.name));
|
||||
}
|
||||
}
|
||||
|
||||
// --- Preloader
|
||||
struct Preloader(&'static yazi_config::plugin::Preloader);
|
||||
struct Preloader {
|
||||
inner: &'static yazi_config::plugin::Preloader,
|
||||
|
||||
v_cmd: Option<Value>,
|
||||
}
|
||||
|
||||
impl Preloader {
|
||||
pub fn new(inner: &'static yazi_config::plugin::Preloader) -> Self { Self { inner, v_cmd: None } }
|
||||
}
|
||||
|
||||
impl UserData for Preloader {
|
||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("cmd", |lua, me| lua.create_string(&me.0.run.name));
|
||||
cached_field!(fields, cmd, |lua: &Lua, me: &Self| lua.create_string(&me.inner.run.name));
|
||||
}
|
||||
}
|
||||
|
||||
// --- Previewer
|
||||
struct Previewer(&'static yazi_config::plugin::Previewer);
|
||||
struct Previewer {
|
||||
inner: &'static yazi_config::plugin::Previewer,
|
||||
|
||||
v_cmd: Option<Value>,
|
||||
}
|
||||
|
||||
impl Previewer {
|
||||
pub fn new(inner: &'static yazi_config::plugin::Previewer) -> Self { Self { inner, v_cmd: None } }
|
||||
}
|
||||
|
||||
impl UserData for Previewer {
|
||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("cmd", |lua, me| lua.create_string(&me.0.run.name));
|
||||
cached_field!(fields, cmd, |lua: &Lua, me: &Self| lua.create_string(&me.inner.run.name));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,17 @@
|
|||
use mlua::{IntoLua, Lua, LuaSerdeExt, SerializeOptions, Value};
|
||||
use yazi_adapter::EMULATOR;
|
||||
use yazi_binding::Url;
|
||||
use yazi_boot::ARGS;
|
||||
use yazi_config::{THEME, YAZI};
|
||||
use yazi_config::YAZI;
|
||||
|
||||
use crate::{Composer, url::Url};
|
||||
use crate::Composer;
|
||||
|
||||
pub const OPTS: SerializeOptions =
|
||||
SerializeOptions::new().serialize_none_to_null(false).serialize_unit_to_null(false);
|
||||
|
||||
pub struct Runtime<'a> {
|
||||
lua: &'a Lua,
|
||||
}
|
||||
pub struct Runtime;
|
||||
|
||||
impl<'a> Runtime<'a> {
|
||||
impl Runtime {
|
||||
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, 10, |lua, key| {
|
||||
match key {
|
||||
|
|
@ -30,9 +29,9 @@ impl<'a> Runtime<'a> {
|
|||
|
||||
fn args(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, 5, |lua, key| match key {
|
||||
b"entries" => lua.create_sequence_from(ARGS.entries.iter().map(Url::from))?.into_lua(lua),
|
||||
b"cwd_file" => ARGS.cwd_file.as_ref().map(Url::from).into_lua(lua),
|
||||
b"chooser_file" => ARGS.chooser_file.as_ref().map(Url::from).into_lua(lua),
|
||||
b"entries" => lua.create_sequence_from(ARGS.entries.iter().map(Url::new))?.into_lua(lua),
|
||||
b"cwd_file" => ARGS.cwd_file.as_ref().map(Url::new).into_lua(lua),
|
||||
b"chooser_file" => ARGS.chooser_file.as_ref().map(Url::new).into_lua(lua),
|
||||
_ => Ok(Value::Nil),
|
||||
})
|
||||
}
|
||||
|
|
@ -106,24 +105,4 @@ impl<'a> Runtime<'a> {
|
|||
.into_lua(lua)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new(lua: &'a Lua) -> Self { Self { lua } }
|
||||
|
||||
// TODO: remove this
|
||||
pub fn install_manager(self) -> mlua::Result<Self> {
|
||||
self.lua.globals().raw_set("MANAGER", self.lua.to_value_with(&YAZI.mgr, OPTS)?)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
// TODO: remove this
|
||||
pub fn install_theme(self) -> mlua::Result<Self> {
|
||||
self.lua.globals().raw_set("THEME", self.lua.to_value_with(&*THEME, OPTS)?)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
// TODO: remove this
|
||||
pub fn install_preview(self) -> mlua::Result<Self> {
|
||||
self.lua.globals().raw_set("PREVIEW", self.lua.to_value_with(&YAZI.preview, OPTS)?)?;
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@ impl From<ratatui::widgets::Padding> for Pad {
|
|||
|
||||
impl Pad {
|
||||
pub fn compose(lua: &Lua, v4: bool) -> mlua::Result<Table> {
|
||||
if !v4 {
|
||||
crate::deprecate!(
|
||||
lua,
|
||||
"The `ui.Padding` has been deprecated, please use `ui.Pad` instead, in your {}"
|
||||
);
|
||||
}
|
||||
|
||||
let new = if v4 {
|
||||
lua.create_function(|_, (_, top, right, bottom, left): (Table, u16, u16, u16, u16)| {
|
||||
Ok(Self(ratatui::widgets::Padding::new(left, right, top, bottom)))
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue