diff --git a/Cargo.lock b/Cargo.lock index e36560c3..682b3b51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1117,11 +1117,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" dependencies = [ "serde", + "serde_core", "typeid", ] @@ -1817,9 +1818,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ "bitflags 2.9.4", "libc", @@ -3158,16 +3159,17 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.223" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "a505d71960adde88e293da5cb5eda57093379f64e61cf77bf0e6a63af07a7bac" dependencies = [ + "serde_core", "serde_derive", ] @@ -3182,10 +3184,19 @@ dependencies = [ ] [[package]] -name = "serde_derive" -version = "1.0.219" +name = "serde_core" +version = "1.0.223" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "20f57cbd357666aa7b3ac84a90b4ea328f1d4ddb6772b430caa5d9e1309bb9e9" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.223" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d428d07faf17e306e699ec1e91996e5a165ba5d6bce5b5155173e91a8a01a56" dependencies = [ "proc-macro2", "quote", @@ -3194,14 +3205,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -4532,7 +4544,7 @@ dependencies = [ [[package]] name = "yazi-actor" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "crossterm 0.29.0", @@ -4564,7 +4576,7 @@ dependencies = [ [[package]] name = "yazi-adapter" -version = "25.6.11" +version = "25.9.15" dependencies = [ "ansi-to-tui", "anyhow", @@ -4586,7 +4598,7 @@ dependencies = [ [[package]] name = "yazi-binding" -version = "25.6.11" +version = "25.9.15" dependencies = [ "ansi-to-tui", "hashbrown 0.16.0", @@ -4606,7 +4618,7 @@ dependencies = [ [[package]] name = "yazi-boot" -version = "25.6.11" +version = "25.9.15" dependencies = [ "clap", "clap_complete", @@ -4626,14 +4638,14 @@ dependencies = [ [[package]] name = "yazi-build" -version = "0.1.8" +version = "25.9.15" dependencies = [ "yazi-term", ] [[package]] name = "yazi-cli" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "clap", @@ -4656,7 +4668,7 @@ dependencies = [ [[package]] name = "yazi-codegen" -version = "25.6.11" +version = "25.9.15" dependencies = [ "quote", "syn", @@ -4664,7 +4676,7 @@ dependencies = [ [[package]] name = "yazi-config" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "bitflags 2.9.4", @@ -4687,7 +4699,7 @@ dependencies = [ [[package]] name = "yazi-core" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "crossterm 0.29.0", @@ -4716,7 +4728,7 @@ dependencies = [ [[package]] name = "yazi-dds" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "hashbrown 0.16.0", @@ -4742,7 +4754,7 @@ dependencies = [ [[package]] name = "yazi-ffi" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "core-foundation-sys", @@ -4753,7 +4765,7 @@ dependencies = [ [[package]] name = "yazi-fm" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "better-panic", @@ -4792,7 +4804,7 @@ dependencies = [ [[package]] name = "yazi-fs" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "arc-swap", @@ -4820,15 +4832,15 @@ dependencies = [ [[package]] name = "yazi-macro" -version = "25.6.11" +version = "25.9.15" [[package]] name = "yazi-packing" -version = "25.5.28" +version = "25.9.15" [[package]] name = "yazi-parser" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "bitflags 2.9.4", @@ -4848,7 +4860,7 @@ dependencies = [ [[package]] name = "yazi-plugin" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "crossterm 0.29.0", @@ -4891,7 +4903,7 @@ checksum = "33232d9116df6415ddfcdf72701b1b7439ce87f240a14723e8dd5d17e7ed5f98" [[package]] name = "yazi-proxy" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "tokio", @@ -4903,7 +4915,7 @@ dependencies = [ [[package]] name = "yazi-scheduler" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "async-priority-channel", @@ -4943,7 +4955,7 @@ dependencies = [ [[package]] name = "yazi-shared" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "crossterm 0.29.0", @@ -4964,7 +4976,7 @@ dependencies = [ [[package]] name = "yazi-term" -version = "25.6.11" +version = "25.9.15" dependencies = [ "crossterm 0.29.0", "libc", @@ -4977,7 +4989,7 @@ dependencies = [ [[package]] name = "yazi-watcher" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "hashbrown 0.16.0", @@ -4995,7 +5007,7 @@ dependencies = [ [[package]] name = "yazi-widgets" -version = "25.6.11" +version = "25.9.15" dependencies = [ "anyhow", "base64", diff --git a/Cargo.toml b/Cargo.toml index ce0ae20c..9671f764 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,8 +44,8 @@ ratatui = { version = "0.29.0", features = [ "unstable-rendered-line regex = "1.11.2" russh = { version = "0.54.3", default-features = false, features = [ "ring", "rsa" ] } scopeguard = "1.2.0" -serde = { version = "1.0.219", features = [ "derive" ] } -serde_json = "1.0.143" +serde = { version = "1.0.223", features = [ "derive" ] } +serde_json = "1.0.145" syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] } tokio = { version = "1.47.1", features = [ "full" ] } tokio-stream = "0.1.17" diff --git a/yazi-actor/Cargo.toml b/yazi-actor/Cargo.toml index dacc343d..b23fdc8a 100644 --- a/yazi-actor/Cargo.toml +++ b/yazi-actor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-actor" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -13,21 +13,21 @@ default = [ "vendored-lua" ] vendored-lua = [ "mlua/vendored" ] [dependencies] -yazi-binding = { path = "../yazi-binding", version = "25.6.11" } -yazi-boot = { path = "../yazi-boot", version = "25.6.11" } -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-core = { path = "../yazi-core", version = "25.6.11" } -yazi-dds = { path = "../yazi-dds", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-parser = { path = "../yazi-parser", version = "25.6.11" } -yazi-plugin = { path = "../yazi-plugin", version = "25.6.11" } -yazi-proxy = { path = "../yazi-proxy", version = "25.6.11" } -yazi-scheduler = { path = "../yazi-scheduler", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } -yazi-term = { path = "../yazi-term", version = "25.6.11" } -yazi-watcher = { path = "../yazi-watcher", version = "25.6.11" } -yazi-widgets = { path = "../yazi-widgets", version = "25.6.11" } +yazi-binding = { path = "../yazi-binding", version = "25.9.15" } +yazi-boot = { path = "../yazi-boot", version = "25.9.15" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-core = { path = "../yazi-core", version = "25.9.15" } +yazi-dds = { path = "../yazi-dds", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-parser = { path = "../yazi-parser", version = "25.9.15" } +yazi-plugin = { path = "../yazi-plugin", version = "25.9.15" } +yazi-proxy = { path = "../yazi-proxy", version = "25.9.15" } +yazi-scheduler = { path = "../yazi-scheduler", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-term = { path = "../yazi-term", version = "25.9.15" } +yazi-watcher = { path = "../yazi-watcher", version = "25.9.15" } +yazi-widgets = { path = "../yazi-widgets", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-adapter/Cargo.toml b/yazi-adapter/Cargo.toml index b53e5b0a..32010648 100644 --- a/yazi-adapter/Cargo.toml +++ b/yazi-adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-adapter" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,11 +9,11 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } -yazi-term = { path = "../yazi-term", version = "25.6.11" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-term = { path = "../yazi-term", version = "25.9.15" } # External dependencies ansi-to-tui = { workspace = true } diff --git a/yazi-binding/Cargo.toml b/yazi-binding/Cargo.toml index 0fe12131..0ed3286d 100644 --- a/yazi-binding/Cargo.toml +++ b/yazi-binding/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-binding" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -13,11 +13,11 @@ default = [ "vendored-lua" ] vendored-lua = [ "mlua/vendored" ] [dependencies] -yazi-adapter = { path = "../yazi-adapter", version = "25.6.11" } -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-adapter = { path = "../yazi-adapter", version = "25.9.15" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies ansi-to-tui = { workspace = true } diff --git a/yazi-binding/src/cha.rs b/yazi-binding/src/cha.rs index d6a7da9d..c110322c 100644 --- a/yazi-binding/src/cha.rs +++ b/yazi-binding/src/cha.rs @@ -1,7 +1,7 @@ use std::{ops::Deref, time::{Duration, SystemTime, UNIX_EPOCH}}; use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, UserData, UserDataFields, UserDataMethods}; -use yazi_fs::cha::ChaKind; +use yazi_fs::cha::{ChaKind, ChaMode}; #[derive(Clone, Copy, FromLua)] pub struct Cha(pub yazi_fs::cha::Cha); @@ -25,11 +25,15 @@ impl Cha { lua.globals().raw_set( "Cha", lua.create_function(|lua, t: Table| { - let kind = - ChaKind::from_bits(t.raw_get("kind")?).ok_or_else(|| "Invalid kind".into_lua_err())?; + let kind = ChaKind::from_bits(t.raw_get("kind").unwrap_or_default()) + .ok_or_else(|| "Invalid kind".into_lua_err())?; + + let mode = + ChaMode::from_bits(t.raw_get("mode")?).ok_or_else(|| "Invalid mode".into_lua_err())?; Self(yazi_fs::cha::Cha { kind, + mode, len: t.raw_get("len").unwrap_or_default(), atime: parse_time(t.raw_get("atime").ok())?, btime: parse_time(t.raw_get("btime").ok())?, @@ -37,8 +41,6 @@ impl Cha { ctime: parse_time(t.raw_get("ctime").ok())?, mtime: parse_time(t.raw_get("mtime").ok())?, #[cfg(unix)] - mode: t.raw_get("mode").unwrap_or_default(), - #[cfg(unix)] dev: t.raw_get("dev").unwrap_or_default(), #[cfg(unix)] uid: t.raw_get("uid").unwrap_or_default(), @@ -55,6 +57,7 @@ impl Cha { impl UserData for Cha { fn add_fields>(fields: &mut F) { + fields.add_field_method_get("mode", |_, me| Ok(me.mode.bits())); fields.add_field_method_get("is_dir", |_, me| Ok(me.is_dir())); fields.add_field_method_get("is_hidden", |_, me| Ok(me.is_hidden())); fields.add_field_method_get("is_link", |_, me| Ok(me.is_link())); @@ -70,7 +73,6 @@ impl UserData for Cha { #[cfg(unix)] { use std::ops::Not; - fields.add_field_method_get("mode", |_, me| Ok(me.is_dummy().not().then_some(me.mode))); fields.add_field_method_get("dev", |_, me| Ok(me.is_dummy().not().then_some(me.dev))); fields.add_field_method_get("uid", |_, me| Ok(me.is_dummy().not().then_some(me.uid))); fields.add_field_method_get("gid", |_, me| Ok(me.is_dummy().not().then_some(me.gid))); @@ -94,12 +96,12 @@ impl UserData for Cha { } fn add_methods>(methods: &mut M) { - methods.add_method("perm", |_, _me, ()| { + methods.add_method("perm", |lua, _me, ()| { Ok( #[cfg(unix)] - Some(yazi_fs::permissions(_me.mode, _me.is_dummy())), + lua.create_string(_me.mode.permissions(_me.is_dummy())), #[cfg(windows)] - None::, + Ok::<_, mlua::Error>(mlua::Value::Nil), ) }); } diff --git a/yazi-boot/Cargo.toml b/yazi-boot/Cargo.toml index f0aef482..16620b54 100644 --- a/yazi-boot/Cargo.toml +++ b/yazi-boot/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-boot" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,11 +9,11 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-adapter = { path = "../yazi-adapter", version = "25.6.11" } -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-adapter = { path = "../yazi-adapter", version = "25.9.15" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies clap = { workspace = true } @@ -23,7 +23,7 @@ regex = { workspace = true } serde = { workspace = true } [build-dependencies] -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies clap = { workspace = true } diff --git a/yazi-build/Cargo.toml b/yazi-build/Cargo.toml index bd7f7f7f..d21e1cea 100644 --- a/yazi-build/Cargo.toml +++ b/yazi-build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-build" -version = "0.1.8" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -15,7 +15,7 @@ panic = "abort" strip = true [build-dependencies] -yazi-term = { path = "../yazi-term", version = "25.5.31" } +yazi-term = { path = "../yazi-term", version = "25.9.15" } [[bin]] name = "yazi-build" diff --git a/yazi-cli/Cargo.toml b/yazi-cli/Cargo.toml index 91f08576..8188fdb6 100644 --- a/yazi-cli/Cargo.toml +++ b/yazi-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-cli" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -19,11 +19,11 @@ inherits = "release" panic = "unwind" [dependencies] -yazi-boot = { path = "../yazi-boot", version = "25.6.11" } -yazi-dds = { path = "../yazi-dds", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-boot = { path = "../yazi-boot", version = "25.9.15" } +yazi-dds = { path = "../yazi-dds", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies anyhow = { workspace = true } @@ -36,7 +36,7 @@ toml = { workspace = true } twox-hash = { workspace = true } [build-dependencies] -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External build dependencies anyhow = { workspace = true } diff --git a/yazi-codegen/Cargo.toml b/yazi-codegen/Cargo.toml index fae6e814..97741895 100644 --- a/yazi-codegen/Cargo.toml +++ b/yazi-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-codegen" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] diff --git a/yazi-config/Cargo.toml b/yazi-config/Cargo.toml index 6e1eb31c..ee023832 100644 --- a/yazi-config/Cargo.toml +++ b/yazi-config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-config" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,11 +9,11 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-codegen = { path = "../yazi-codegen", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } -yazi-term = { path = "../yazi-term", version = "25.6.11" } +yazi-codegen = { path = "../yazi-codegen", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-term = { path = "../yazi-term", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-core/Cargo.toml b/yazi-core/Cargo.toml index 0cf91439..208e3d47 100644 --- a/yazi-core/Cargo.toml +++ b/yazi-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-core" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,18 +9,18 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-adapter = { path = "../yazi-adapter", version = "25.6.11" } -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-dds = { path = "../yazi-dds", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-parser = { path = "../yazi-parser", version = "25.6.11" } -yazi-plugin = { path = "../yazi-plugin", version = "25.6.11" } -yazi-proxy = { path = "../yazi-proxy", version = "25.6.11" } -yazi-scheduler = { path = "../yazi-scheduler", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } -yazi-watcher = { path = "../yazi-watcher", version = "25.6.11" } -yazi-widgets = { path = "../yazi-widgets", version = "25.6.11" } +yazi-adapter = { path = "../yazi-adapter", version = "25.9.15" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-dds = { path = "../yazi-dds", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-parser = { path = "../yazi-parser", version = "25.9.15" } +yazi-plugin = { path = "../yazi-plugin", version = "25.9.15" } +yazi-proxy = { path = "../yazi-proxy", version = "25.9.15" } +yazi-scheduler = { path = "../yazi-scheduler", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-watcher = { path = "../yazi-watcher", version = "25.9.15" } +yazi-widgets = { path = "../yazi-widgets", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-dds/Cargo.toml b/yazi-dds/Cargo.toml index e8766dbd..4bff6675 100644 --- a/yazi-dds/Cargo.toml +++ b/yazi-dds/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-dds" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -13,12 +13,12 @@ default = [ "vendored-lua" ] vendored-lua = [ "mlua/vendored" ] [dependencies] -yazi-binding = { path = "../yazi-binding", version = "25.6.11" } -yazi-boot = { path = "../yazi-boot", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-parser = { path = "../yazi-parser", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-binding = { path = "../yazi-binding", version = "25.9.15" } +yazi-boot = { path = "../yazi-boot", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-parser = { path = "../yazi-parser", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-dds/src/state.rs b/yazi-dds/src/state.rs index 8ba5d5c3..584b3ff9 100644 --- a/yazi-dds/src/state.rs +++ b/yazi-dds/src/state.rs @@ -3,7 +3,7 @@ use std::{mem, ops::Deref, sync::atomic::{AtomicU64, Ordering}, time::UNIX_EPOCH use anyhow::Result; use hashbrown::HashMap; use parking_lot::RwLock; -use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufWriter}; +use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, BufWriter}; use yazi_boot::BOOT; use yazi_fs::provider::local::{Gate, Local}; use yazi_shared::{RoCell, timestamp_us}; @@ -79,7 +79,7 @@ impl State { } async fn load(&self) -> Result<()> { - let mut file = Local::open(BOOT.state_dir.join(".dds")).await?.reader(); + let mut file = BufReader::new(Local::open(BOOT.state_dir.join(".dds")).await?); let mut buf = String::new(); let mut inner = HashMap::new(); diff --git a/yazi-ffi/Cargo.toml b/yazi-ffi/Cargo.toml index 2c03bddd..8a911dde 100644 --- a/yazi-ffi/Cargo.toml +++ b/yazi-ffi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-ffi" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,7 +9,7 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-fm/Cargo.toml b/yazi-fm/Cargo.toml index 8f26da5d..1ffd590b 100644 --- a/yazi-fm/Cargo.toml +++ b/yazi-fm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-fm" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -23,22 +23,22 @@ default = [ "vendored-lua" ] vendored-lua = [ "mlua/vendored" ] [dependencies] -yazi-actor = { path = "../yazi-actor", version = "25.6.11" } -yazi-adapter = { path = "../yazi-adapter", version = "25.6.11" } -yazi-binding = { path = "../yazi-binding", version = "25.6.11" } -yazi-boot = { path = "../yazi-boot", version = "25.6.11" } -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-core = { path = "../yazi-core", version = "25.6.11" } -yazi-dds = { path = "../yazi-dds", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-parser = { path = "../yazi-parser", version = "25.6.11" } -yazi-plugin = { path = "../yazi-plugin", version = "25.6.11" } -yazi-proxy = { path = "../yazi-proxy", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } -yazi-term = { path = "../yazi-term", version = "25.6.11" } -yazi-watcher = { path = "../yazi-watcher", version = "25.6.11" } -yazi-widgets = { path = "../yazi-widgets", version = "25.6.11" } +yazi-actor = { path = "../yazi-actor", version = "25.9.15" } +yazi-adapter = { path = "../yazi-adapter", version = "25.9.15" } +yazi-binding = { path = "../yazi-binding", version = "25.9.15" } +yazi-boot = { path = "../yazi-boot", version = "25.9.15" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-core = { path = "../yazi-core", version = "25.9.15" } +yazi-dds = { path = "../yazi-dds", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-parser = { path = "../yazi-parser", version = "25.9.15" } +yazi-plugin = { path = "../yazi-plugin", version = "25.9.15" } +yazi-proxy = { path = "../yazi-proxy", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-term = { path = "../yazi-term", version = "25.9.15" } +yazi-watcher = { path = "../yazi-watcher", version = "25.9.15" } +yazi-widgets = { path = "../yazi-widgets", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-fs/Cargo.toml b/yazi-fs/Cargo.toml index 0a9f540d..a813576b 100644 --- a/yazi-fs/Cargo.toml +++ b/yazi-fs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-fs" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,9 +9,9 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-ffi = { path = "../yazi-ffi", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-ffi = { path = "../yazi-ffi", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-fs/src/cha/cha.rs b/yazi-fs/src/cha/cha.rs index 718562d4..710c41a2 100644 --- a/yazi-fs/src/cha/cha.rs +++ b/yazi-fs/src/cha/cha.rs @@ -1,14 +1,15 @@ -use std::{fs::{FileType, Metadata}, time::SystemTime}; +use std::{fs::{FileType, Metadata}, ops::Deref, time::SystemTime}; use yazi_macro::{unix_either, win_either}; -use yazi_shared::url::{Url, UrlBuf}; +use yazi_shared::url::Url; use super::ChaKind; -use crate::provider; +use crate::{cha::ChaMode, provider}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Cha { pub kind: ChaKind, + pub mode: ChaMode, pub len: u64, pub atime: Option, pub btime: Option, @@ -16,21 +17,26 @@ pub struct Cha { pub ctime: Option, pub mtime: Option, #[cfg(unix)] - pub mode: libc::mode_t, - #[cfg(unix)] pub dev: libc::dev_t, #[cfg(unix)] - pub uid: libc::uid_t, + pub uid: u32, #[cfg(unix)] - pub gid: libc::gid_t, + pub gid: u32, #[cfg(unix)] - pub nlink: libc::nlink_t, + pub nlink: u64, +} + +impl Deref for Cha { + type Target = ChaMode; + + fn deref(&self) -> &Self::Target { &self.mode } } impl Default for Cha { fn default() -> Self { Self { kind: ChaKind::DUMMY, + mode: ChaMode::empty(), len: 0, atime: None, btime: None, @@ -38,8 +44,6 @@ impl Default for Cha { ctime: None, mtime: None, #[cfg(unix)] - mode: 0, - #[cfg(unix)] dev: 0, #[cfg(unix)] uid: 0, @@ -53,8 +57,11 @@ impl Default for Cha { impl Cha { #[inline] - pub fn new<'a>(url: impl Into>, meta: Metadata) -> Self { - Self::from_just_meta(&meta).attach(ChaKind::hidden(url, &meta)) + pub fn new<'a, U>(url: U, meta: Metadata) -> Self + where + U: Into>, + { + Self::from_bare(&meta).attach(ChaKind::hidden(url, &meta)) } #[inline] @@ -63,7 +70,10 @@ impl Cha { Ok(Self::from_follow(url, provider::symlink_metadata(url).await?).await) } - pub async fn from_follow<'a>(url: impl Into>, mut meta: Metadata) -> Self { + pub async fn from_follow<'a, U>(url: U, mut meta: Metadata) -> Self + where + U: Into>, + { let url = url.into(); let mut attached = ChaKind::hidden(url, &meta); @@ -75,74 +85,54 @@ impl Cha { attached |= ChaKind::ORPHAN; } - Self::from_just_meta(&meta).attach(attached) + Self::from_bare(&meta).attach(attached) } - #[inline] - pub fn from_dummy(_url: &UrlBuf, ft: Option) -> Self { - let mut me = ft.map(Self::from_half_ft).unwrap_or_default(); - #[cfg(unix)] - if _url.urn().is_hidden() { - me.kind |= ChaKind::HIDDEN; - } - me - } + pub fn from_dummy<'a, U>(_url: U, ft: Option) -> Self + where + U: Into>, + { + let mode = ft.map(ChaMode::from_bare).unwrap_or_default(); - fn from_half_ft(ft: FileType) -> Self { let mut kind = ChaKind::DUMMY; - - #[cfg(unix)] - let mode = { - use std::os::unix::fs::FileTypeExt; - if ft.is_dir() { - kind |= ChaKind::DIR; - libc::S_IFDIR - } else if ft.is_symlink() { - kind |= ChaKind::LINK; - libc::S_IFLNK - } else if ft.is_block_device() { - libc::S_IFBLK - } else if ft.is_char_device() { - libc::S_IFCHR - } else if ft.is_fifo() { - libc::S_IFIFO - } else if ft.is_socket() { - libc::S_IFSOCK - } else { - 0 - } - }; - - #[cfg(windows)] - { - if ft.is_dir() { - kind |= ChaKind::DIR; - } else if ft.is_symlink() { - kind |= ChaKind::LINK; - } - } - - Self { - kind, - #[cfg(unix)] - mode, - ..Default::default() - } - } - - fn from_just_meta(m: &Metadata) -> Self { - #[cfg(unix)] - use std::{os::unix::{fs::MetadataExt, prelude::PermissionsExt}, time::{Duration, UNIX_EPOCH}}; - - let mut kind = ChaKind::empty(); - if m.is_dir() { - kind |= ChaKind::DIR; - } else if m.is_symlink() { + if mode.is_link() { kind |= ChaKind::LINK; } + #[cfg(unix)] + if _url.into().urn().is_hidden() { + kind |= ChaKind::HIDDEN; + } + + Self { kind, mode, ..Default::default() } + } + + fn from_bare(m: &Metadata) -> Self { + #[cfg(unix)] + use std::{os::unix::fs::MetadataExt, time::{Duration, UNIX_EPOCH}}; + + #[cfg(unix)] + let mode = { + use std::os::unix::fs::PermissionsExt; + ChaMode::from_bits_retain(m.permissions().mode() as u16) + }; + + #[cfg(windows)] + let mode = { + if m.is_file() { + ChaMode::T_FILE + } else if m.is_dir() { + ChaMode::T_DIR + } else if m.is_symlink() { + ChaMode::T_LINK + } else { + ChaMode::empty() + } + }; + Self { - kind, + kind: ChaKind::empty(), + mode, len: m.len(), atime: m.accessed().ok(), btime: m.created().ok(), @@ -150,8 +140,6 @@ impl Cha { ctime: UNIX_EPOCH.checked_add(Duration::new(m.ctime() as u64, m.ctime_nsec() as u32)), mtime: m.modified().ok(), #[cfg(unix)] - mode: m.permissions().mode() as _, - #[cfg(unix)] dev: m.dev() as _, #[cfg(unix)] uid: m.uid() as _, @@ -180,9 +168,6 @@ impl Cha { } impl Cha { - #[inline] - pub const fn is_dir(&self) -> bool { self.kind.contains(ChaKind::DIR) } - #[inline] pub const fn is_hidden(&self) -> bool { win_either!( @@ -191,38 +176,9 @@ impl Cha { ) } - #[inline] - pub const fn is_link(&self) -> bool { self.kind.contains(ChaKind::LINK) } - #[inline] pub const fn is_orphan(&self) -> bool { self.kind.contains(ChaKind::ORPHAN) } #[inline] pub const fn is_dummy(&self) -> bool { self.kind.contains(ChaKind::DUMMY) } - - #[inline] - pub const fn is_block(&self) -> bool { - unix_either!(self.mode & libc::S_IFMT == libc::S_IFBLK, false) - } - - #[inline] - pub const fn is_char(&self) -> bool { - unix_either!(self.mode & libc::S_IFMT == libc::S_IFCHR, false) - } - - #[inline] - pub const fn is_fifo(&self) -> bool { - unix_either!(self.mode & libc::S_IFMT == libc::S_IFIFO, false) - } - - #[inline] - pub const fn is_sock(&self) -> bool { - unix_either!(self.mode & libc::S_IFMT == libc::S_IFSOCK, false) - } - - #[inline] - pub const fn is_exec(&self) -> bool { unix_either!(self.mode & libc::S_IXUSR != 0, false) } - - #[inline] - pub const fn is_sticky(&self) -> bool { unix_either!(self.mode & libc::S_ISVTX != 0, false) } } diff --git a/yazi-fs/src/cha/kind.rs b/yazi-fs/src/cha/kind.rs index 4d850183..291933e1 100644 --- a/yazi-fs/src/cha/kind.rs +++ b/yazi-fs/src/cha/kind.rs @@ -6,21 +6,22 @@ use yazi_shared::url::Url; bitflags! { #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct ChaKind: u8 { - const DIR = 0b00000001; + const HIDDEN = 0b0000_0001; + const SYSTEM = 0b0000_0010; - const HIDDEN = 0b00000010; - const LINK = 0b00000100; - const ORPHAN = 0b00001000; + const LINK = 0b0000_0100; + const ORPHAN = 0b0000_1000; - const DUMMY = 0b00010000; - #[cfg(windows)] - const SYSTEM = 0b00100000; + const DUMMY = 0b0001_0000; } } impl ChaKind { #[inline] - pub(super) fn hidden<'a>(_url: impl Into>, _meta: &Metadata) -> Self { + pub(super) fn hidden<'a, U>(_url: U, _meta: &Metadata) -> Self + where + U: Into>, + { let mut me = Self::empty(); #[cfg(unix)] diff --git a/yazi-fs/src/cha/mod.rs b/yazi-fs/src/cha/mod.rs index aa8136b3..961ce868 100644 --- a/yazi-fs/src/cha/mod.rs +++ b/yazi-fs/src/cha/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(cha kind); +yazi_macro::mod_flat!(cha kind mode); diff --git a/yazi-fs/src/cha/mode.rs b/yazi-fs/src/cha/mode.rs new file mode 100644 index 00000000..9d3babf1 --- /dev/null +++ b/yazi-fs/src/cha/mode.rs @@ -0,0 +1,158 @@ +use std::fs::FileType; + +use bitflags::bitflags; + +bitflags! { + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] + pub struct ChaMode: u16 { + // File type + const T_MASK = 0b1111_0000_0000_0000; + const T_SOCK = 0b1100_0000_0000_0000; + const T_LINK = 0b1010_0000_0000_0000; + const T_FILE = 0b1000_0000_0000_0000; + const T_BLOCK = 0b0110_0000_0000_0000; + const T_DIR = 0b0100_0000_0000_0000; + const T_CHAR = 0b0010_0000_0000_0000; + const T_FIFO = 0b0001_0000_0000_0000; + // Special + const S_SUID = 0b0000_1000_0000_0000; + const S_SGID = 0b0000_0100_0000_0000; + const S_STICKY = 0b0000_0010_0000_0000; + // User + const U_MASK = 0b0000_0001_1100_0000; + const U_READ = 0b0000_0001_0000_0000; + const U_WRITE = 0b0000_0000_1000_0000; + const U_EXEC = 0b0000_0000_0100_0000; + // Group + const G_MASK = 0b0000_0000_0011_1000; + const G_READ = 0b0000_0000_0010_0000; + const G_WRITE = 0b0000_0000_0001_0000; + const G_EXEC = 0b0000_0000_0000_1000; + // Others + const O_MASK = 0b0000_0000_0000_0111; + const O_READ = 0b0000_0000_0000_0100; + const O_WRITE = 0b0000_0000_0000_0010; + const O_EXEC = 0b0000_0000_0000_0001; + } +} + +impl ChaMode { + #[inline] + pub fn r#type(self) -> Self { self & Self::T_MASK } + + // Convert a file mode to a string representation + #[cfg(unix)] + #[allow(clippy::collapsible_else_if)] + pub fn permissions(self, dummy: bool) -> [u8; 10] { + let mut s = *b"-?????????"; + + // File type + s[0] = match self.r#type() { + Self::T_DIR => b'd', + Self::T_LINK => b'l', + Self::T_BLOCK => b'b', + Self::T_CHAR => b'c', + Self::T_SOCK => b's', + Self::T_FIFO => b'p', + _ => b'-', + }; + if dummy { + return s; + } + + // User + s[1] = if self.contains(Self::U_READ) { b'r' } else { b'-' }; + s[2] = if self.contains(Self::U_WRITE) { b'w' } else { b'-' }; + s[3] = if self.contains(Self::U_EXEC) { + if self.contains(Self::S_SUID) { b's' } else { b'x' } + } else { + if self.contains(Self::S_SUID) { b'S' } else { b'-' } + }; + + // Group + s[4] = if self.contains(Self::G_READ) { b'r' } else { b'-' }; + s[5] = if self.contains(Self::G_WRITE) { b'w' } else { b'-' }; + s[6] = if self.contains(Self::G_EXEC) { + if self.contains(Self::S_SGID) { b's' } else { b'x' } + } else { + if self.contains(Self::S_SGID) { b'S' } else { b'-' } + }; + + // Others + s[7] = if self.contains(Self::O_READ) { b'r' } else { b'-' }; + s[8] = if self.contains(Self::O_WRITE) { b'w' } else { b'-' }; + s[9] = if self.contains(Self::O_EXEC) { + if self.contains(Self::S_STICKY) { b't' } else { b'x' } + } else { + if self.contains(Self::S_STICKY) { b'T' } else { b'-' } + }; + + s + } + + pub(super) fn from_bare(ft: FileType) -> Self { + #[cfg(unix)] + { + use std::os::unix::fs::FileTypeExt; + if ft.is_file() { + Self::T_FILE + } else if ft.is_dir() { + Self::T_DIR + } else if ft.is_symlink() { + Self::T_LINK + } else if ft.is_block_device() { + Self::T_BLOCK + } else if ft.is_char_device() { + Self::T_CHAR + } else if ft.is_socket() { + Self::T_SOCK + } else if ft.is_fifo() { + Self::T_FIFO + } else { + Self::empty() + } + } + #[cfg(windows)] + { + if ft.is_file() { + Self::T_FILE + } else if ft.is_dir() { + Self::T_DIR + } else if ft.is_symlink() { + Self::T_LINK + } else { + Self::empty() + } + } + } +} + +impl ChaMode { + #[inline] + pub const fn is_file(self) -> bool { self.contains(Self::T_FILE) } + + #[inline] + pub const fn is_dir(self) -> bool { self.contains(Self::T_DIR) } + + #[inline] + pub const fn is_link(&self) -> bool { self.contains(Self::T_LINK) } + + #[inline] + pub const fn is_block(&self) -> bool { self.contains(Self::T_BLOCK) } + + #[inline] + pub const fn is_char(&self) -> bool { self.contains(Self::T_CHAR) } + + #[inline] + pub const fn is_sock(&self) -> bool { self.contains(Self::T_SOCK) } + + #[inline] + pub const fn is_fifo(&self) -> bool { self.contains(Self::T_FIFO) } + + // TODO: deprecate + #[inline] + pub const fn is_exec(&self) -> bool { self.contains(Self::U_EXEC) } + + #[inline] + pub const fn is_sticky(&self) -> bool { self.contains(Self::S_STICKY) } +} diff --git a/yazi-fs/src/fns.rs b/yazi-fs/src/fns.rs index 2f26f664..843b5bba 100644 --- a/yazi-fs/src/fns.rs +++ b/yazi-fs/src/fns.rs @@ -94,59 +94,6 @@ pub async fn remove_dir_clean(dir: &UrlBuf) { provider::remove_dir(dir).await.ok(); } -// Convert a file mode to a string representation -#[cfg(unix)] -#[allow(clippy::collapsible_else_if)] -pub fn permissions(m: libc::mode_t, dummy: bool) -> String { - use libc::{S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFSOCK, S_IRGRP, S_IROTH, S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR}; - let mut s = String::with_capacity(10); - - // Filetype - s.push(match m & S_IFMT { - S_IFBLK => 'b', - S_IFCHR => 'c', - S_IFDIR => 'd', - S_IFIFO => 'p', - S_IFLNK => 'l', - S_IFSOCK => 's', - _ => '-', - }); - - if dummy { - s.push_str("?????????"); - return s; - } - - // Owner - s.push(if m & S_IRUSR != 0 { 'r' } else { '-' }); - s.push(if m & S_IWUSR != 0 { 'w' } else { '-' }); - s.push(if m & S_IXUSR != 0 { - if m & S_ISUID != 0 { 's' } else { 'x' } - } else { - if m & S_ISUID != 0 { 'S' } else { '-' } - }); - - // Group - s.push(if m & S_IRGRP != 0 { 'r' } else { '-' }); - s.push(if m & S_IWGRP != 0 { 'w' } else { '-' }); - s.push(if m & S_IXGRP != 0 { - if m & S_ISGID != 0 { 's' } else { 'x' } - } else { - if m & S_ISGID != 0 { 'S' } else { '-' } - }); - - // Other - s.push(if m & S_IROTH != 0 { 'r' } else { '-' }); - s.push(if m & S_IWOTH != 0 { 'w' } else { '-' }); - s.push(if m & S_IXOTH != 0 { - if m & S_ISVTX != 0 { 't' } else { 'x' } - } else { - if m & S_ISVTX != 0 { 'T' } else { '-' } - }); - - s -} - // Find the max common root in a list of urls // e.g. /a/b/c, /a/b/d -> /a/b // /aa/bb/cc, /aa/dd/ee -> /aa diff --git a/yazi-fs/src/lib.rs b/yazi-fs/src/lib.rs index a31a472a..99f63d37 100644 --- a/yazi-fs/src/lib.rs +++ b/yazi-fs/src/lib.rs @@ -2,7 +2,7 @@ yazi_macro::mod_pub!(cha mounts provider path); -yazi_macro::mod_flat!(calculator cwd file files filter fns op sorter sorting stage xdg); +yazi_macro::mod_flat!(cwd file files filter fns op sorter sorting stage xdg); pub fn init() { CWD.init(<_>::default()); diff --git a/yazi-fs/src/provider/buffer.rs b/yazi-fs/src/provider/buffer.rs deleted file mode 100644 index 4913981d..00000000 --- a/yazi-fs/src/provider/buffer.rs +++ /dev/null @@ -1,9 +0,0 @@ -// --- BufRead -pub trait BufRead: tokio::io::AsyncRead + Send {} - -impl BufRead for T {} - -// --- BufReadSync -pub trait BufReadSync: std::io::BufRead + std::io::Seek + Send {} - -impl BufReadSync for T {} diff --git a/yazi-fs/src/provider/calculator.rs b/yazi-fs/src/provider/calculator.rs new file mode 100644 index 00000000..aa409e0f --- /dev/null +++ b/yazi-fs/src/provider/calculator.rs @@ -0,0 +1,81 @@ +use std::{collections::VecDeque, io, time::{Duration, Instant}}; + +use yazi_shared::{Either, url::{Url, UrlBuf}}; + +use crate::provider::{self, ReadDir}; + +pub enum SizeCalculator { + File(Option), + Dir(VecDeque>), +} + +impl SizeCalculator { + pub async fn new<'a, U>(url: U) -> io::Result + where + U: Into>, + { + let url: Url = url.into(); + let meta = provider::symlink_metadata(url).await?; + Ok(if meta.is_dir() { + Self::Dir(VecDeque::from([Either::Left(url.to_owned())])) + } else { + Self::File(Some(meta.len())) + }) + } + + pub async fn total<'a, U>(url: U) -> io::Result + where + U: Into>, + { + let mut it = Self::new(url).await?; + let mut total = 0; + while let Some(n) = it.next().await? { + total += n; + } + Ok(total) + } + + pub async fn next(&mut self) -> io::Result> { + Ok(match self { + Self::File(size) => size.take(), + Self::Dir(buf) => Self::next_chunk(buf).await, + }) + } + + async fn next_chunk(buf: &mut VecDeque>) -> Option { + let (mut i, mut size, now) = (0, 0, Instant::now()); + macro_rules! pop_and_continue { + () => {{ + buf.pop_front(); + if buf.is_empty() { + return Some(size); + } + continue; + }}; + } + + while i < 2000 && now.elapsed() < Duration::from_millis(100) { + i += 1; + let front = buf.front_mut()?; + + if let Either::Left(p) = front { + *front = match provider::read_dir(p).await { + Ok(it) => Either::Right(it), + Err(_) => pop_and_continue!(), + }; + } + + let Ok(Some(ent)) = front.right_mut()?.next_entry().await else { + pop_and_continue!(); + }; + + let Ok(ft) = ent.file_type().await else { continue }; + if ft.is_dir() { + buf.push_back(Either::Left(ent.url())); + } else if let Ok(meta) = ent.metadata().await { + size += meta.len(); + } + } + Some(size) + } +} diff --git a/yazi-fs/src/provider/dir_entry.rs b/yazi-fs/src/provider/dir_entry.rs index efb726e8..910a865d 100644 --- a/yazi-fs/src/provider/dir_entry.rs +++ b/yazi-fs/src/provider/dir_entry.rs @@ -33,36 +33,3 @@ impl DirEntry { } } } - -// --- DirEntrySync -pub enum DirEntrySync { - Local(super::local::DirEntrySync), -} - -impl DirEntrySync { - #[must_use] - pub fn url(&self) -> UrlBuf { - match self { - Self::Local(local) => local.url(), - } - } - - #[must_use] - pub fn file_name(&self) -> OsString { - match self { - Self::Local(local) => local.file_name(), - } - } - - pub fn metadata(&self) -> io::Result { - match self { - Self::Local(local) => local.metadata(), - } - } - - pub fn file_type(&self) -> io::Result { - match self { - Self::Local(local) => local.file_type(), - } - } -} diff --git a/yazi-fs/src/calculator.rs b/yazi-fs/src/provider/local/calculator.rs similarity index 70% rename from yazi-fs/src/calculator.rs rename to yazi-fs/src/provider/local/calculator.rs index 32e77171..9aaa89fa 100644 --- a/yazi-fs/src/calculator.rs +++ b/yazi-fs/src/provider/local/calculator.rs @@ -1,11 +1,9 @@ -use std::{collections::VecDeque, future::poll_fn, io, mem, pin::Pin, task::{Poll, ready}, time::{Duration, Instant}}; +use std::{collections::VecDeque, future::poll_fn, io, mem, path::{Path, PathBuf}, pin::Pin, task::{Poll, ready}, time::{Duration, Instant}}; use tokio::task::JoinHandle; -use yazi_shared::{Either, url::UrlBuf}; +use yazi_shared::Either; -use crate::provider::{self, ReadDirSync}; - -type Task = Either; +type Task = Either; pub enum SizeCalculator { Idle((VecDeque, Option)), @@ -13,23 +11,23 @@ pub enum SizeCalculator { } impl SizeCalculator { - pub async fn new(url: &UrlBuf) -> io::Result { - let u = url.to_owned(); + pub async fn new(path: &Path) -> io::Result { + let p = path.to_owned(); tokio::task::spawn_blocking(move || { - let meta = provider::symlink_metadata_sync(&u)?; + let meta = std::fs::symlink_metadata(&p)?; if !meta.is_dir() { return Ok(Self::Idle((VecDeque::new(), Some(meta.len())))); } - let mut buf = VecDeque::from([Either::Right(provider::read_dir_sync(&u)?)]); + let mut buf = VecDeque::from([Either::Right(std::fs::read_dir(&p)?)]); let size = Self::next_chunk(&mut buf); Ok(Self::Idle((buf, size))) }) .await? } - pub async fn total(url: &UrlBuf) -> io::Result { - let mut it = Self::new(url).await?; + pub async fn total(path: &Path) -> io::Result { + let mut it = Self::new(path).await?; let mut total = 0; while let Some(n) = it.next().await? { total += n; @@ -63,7 +61,7 @@ impl SizeCalculator { .await } - fn next_chunk(buf: &mut VecDeque>) -> Option { + fn next_chunk(buf: &mut VecDeque>) -> Option { let (mut i, mut size, now) = (0, 0, Instant::now()); macro_rules! pop_and_continue { () => {{ @@ -79,8 +77,8 @@ impl SizeCalculator { i += 1; let front = buf.front_mut()?; - if let Either::Left(u) = front { - *front = match provider::read_dir_sync(u) { + if let Either::Left(p) = front { + *front = match std::fs::read_dir(p) { Ok(it) => Either::Right(it), Err(_) => pop_and_continue!(), }; @@ -93,7 +91,7 @@ impl SizeCalculator { let Ok(ent) = next else { continue }; let Ok(ft) = ent.file_type() else { continue }; if ft.is_dir() { - buf.push_back(Either::Left(ent.url())); + buf.push_back(Either::Left(ent.path())); } else if let Ok(meta) = ent.metadata() { size += meta.len(); } diff --git a/yazi-fs/src/provider/local/dir_entry.rs b/yazi-fs/src/provider/local/dir_entry.rs index 5506e981..c6078f13 100644 --- a/yazi-fs/src/provider/local/dir_entry.rs +++ b/yazi-fs/src/provider/local/dir_entry.rs @@ -22,25 +22,3 @@ impl DirEntry { #[must_use] pub fn url(&self) -> UrlBuf { self.0.path().into() } } - -// --- DirEntrySync -pub struct DirEntrySync(std::fs::DirEntry); - -impl Deref for DirEntrySync { - type Target = std::fs::DirEntry; - - fn deref(&self) -> &Self::Target { &self.0 } -} - -impl From for DirEntrySync { - fn from(value: std::fs::DirEntry) -> Self { Self(value) } -} - -impl From for crate::provider::DirEntrySync { - fn from(value: DirEntrySync) -> Self { Self::Local(value) } -} - -impl DirEntrySync { - #[must_use] - pub fn url(&self) -> UrlBuf { self.0.path().into() } -} diff --git a/yazi-fs/src/provider/local/local.rs b/yazi-fs/src/provider/local/local.rs index a0c0e714..ac1d767f 100644 --- a/yazi-fs/src/provider/local/local.rs +++ b/yazi-fs/src/provider/local/local.rs @@ -1,6 +1,6 @@ use std::{io, path::{Path, PathBuf}}; -use crate::{cha::Cha, provider::local::{Gate, ReadDir, ReadDirSync, RwFile}}; +use crate::{cha::Cha, provider::local::{Gate, ReadDir, RwFile}}; pub struct Local; @@ -54,14 +54,14 @@ impl Local { tokio::task::spawn_blocking(move || { let mut reader = std::fs::File::open(from)?; let mut writer = std::fs::OpenOptions::new() - .mode(cha.mode as u32) // Do not remove `as u32`, https://github.com/termux/termux-packages/pull/22481 - .write(true) - .create(true) - .truncate(true) - .open(to)?; + .mode(cha.mode.bits() as _) + .write(true) + .create(true) + .truncate(true) + .open(to)?; let written = std::io::copy(&mut reader, &mut writer)?; - unsafe { libc::fchmod(writer.as_raw_fd(), cha.mode) }; + unsafe { libc::fchmod(writer.as_raw_fd(), cha.mode.bits() as _) }; writer.set_times(ft).ok(); Ok(written) @@ -145,14 +145,6 @@ impl Local { tokio::fs::read_dir(path).await.map(Into::into) } - #[inline] - pub fn read_dir_sync

(path: P) -> io::Result - where - P: AsRef, - { - std::fs::read_dir(path).map(Into::into) - } - #[inline] pub async fn read_link

(path: P) -> io::Result where @@ -261,14 +253,6 @@ impl Local { tokio::fs::symlink_metadata(path).await } - #[inline] - pub fn symlink_metadata_sync

(path: P) -> io::Result - where - P: AsRef, - { - std::fs::symlink_metadata(path) - } - pub async fn trash

(path: P) -> io::Result<()> where P: AsRef, diff --git a/yazi-fs/src/provider/local/mod.rs b/yazi-fs/src/provider/local/mod.rs index c8ddd193..32072894 100644 --- a/yazi-fs/src/provider/local/mod.rs +++ b/yazi-fs/src/provider/local/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(casefold dir_entry gate identical local read_dir rw_file); +yazi_macro::mod_flat!(calculator casefold dir_entry gate identical local read_dir rw_file); diff --git a/yazi-fs/src/provider/local/read_dir.rs b/yazi-fs/src/provider/local/read_dir.rs index 7d056841..1aa34bdc 100644 --- a/yazi-fs/src/provider/local/read_dir.rs +++ b/yazi-fs/src/provider/local/read_dir.rs @@ -1,6 +1,6 @@ use std::io; -use super::{DirEntry, DirEntrySync}; +use super::DirEntry; pub struct ReadDir(tokio::fs::ReadDir); @@ -17,22 +17,3 @@ impl ReadDir { self.0.next_entry().await.map(|entry| entry.map(Into::into)) } } - -// --- ReadDirSync -pub struct ReadDirSync(std::fs::ReadDir); - -impl From for ReadDirSync { - fn from(value: std::fs::ReadDir) -> Self { Self(value) } -} - -impl From for crate::provider::ReadDirSync { - fn from(value: ReadDirSync) -> Self { Self::Local(value) } -} - -impl Iterator for ReadDirSync { - type Item = io::Result; - - fn next(&mut self) -> Option> { - self.0.next().map(|result| result.map(Into::into)) - } -} diff --git a/yazi-fs/src/provider/local/rw_file.rs b/yazi-fs/src/provider/local/rw_file.rs index 8153f54c..892c4db3 100644 --- a/yazi-fs/src/provider/local/rw_file.rs +++ b/yazi-fs/src/provider/local/rw_file.rs @@ -1,3 +1,7 @@ +use std::{pin::Pin, task::Poll}; + +use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite}; + pub struct RwFile(tokio::fs::File); impl From for RwFile { @@ -8,11 +12,67 @@ impl From for crate::provider::RwFile { fn from(value: RwFile) -> Self { Self::Local(value) } } -impl From for crate::provider::RwFile { - fn from(value: tokio::fs::File) -> Self { RwFile(value).into() } +impl AsyncRead for RwFile { + #[inline] + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + buf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll> { + Pin::new(&mut self.0).poll_read(cx, buf) + } } -impl RwFile { +impl AsyncSeek for RwFile { #[inline] - pub fn reader(self) -> tokio::io::BufReader { tokio::io::BufReader::new(self.0) } + fn start_seek(mut self: Pin<&mut Self>, position: std::io::SeekFrom) -> std::io::Result<()> { + Pin::new(&mut self.0).start_seek(position) + } + + #[inline] + fn poll_complete( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll> { + Pin::new(&mut self.0).poll_complete(cx) + } +} + +impl AsyncWrite for RwFile { + #[inline] + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + buf: &[u8], + ) -> Poll> { + Pin::new(&mut self.0).poll_write(cx, buf) + } + + #[inline] + fn poll_flush( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll> { + Pin::new(&mut self.0).poll_flush(cx) + } + + #[inline] + fn poll_shutdown( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll> { + Pin::new(&mut self.0).poll_shutdown(cx) + } + + #[inline] + fn poll_write_vectored( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + Pin::new(&mut self.0).poll_write_vectored(cx, bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { self.0.is_write_vectored() } } diff --git a/yazi-fs/src/provider/mod.rs b/yazi-fs/src/provider/mod.rs index ce56650e..68cf430b 100644 --- a/yazi-fs/src/provider/mod.rs +++ b/yazi-fs/src/provider/mod.rs @@ -1,3 +1,3 @@ yazi_macro::mod_pub!(local sftp); -yazi_macro::mod_flat!(buffer dir_entry provider read_dir rw_file); +yazi_macro::mod_flat!(calculator dir_entry provider read_dir rw_file); diff --git a/yazi-fs/src/provider/provider.rs b/yazi-fs/src/provider/provider.rs index 93ea35c8..c0cd1503 100644 --- a/yazi-fs/src/provider/provider.rs +++ b/yazi-fs/src/provider/provider.rs @@ -2,7 +2,7 @@ use std::{io, path::{Path, PathBuf}}; use yazi_shared::url::{Url, UrlBuf}; -use crate::{cha::Cha, provider::{ReadDir, ReadDirSync, RwFile, local::{self, Local}}}; +use crate::{cha::Cha, provider::{ReadDir, RwFile, local::{self, Local}}}; #[inline] pub fn cache<'a, U>(url: U) -> Option @@ -12,6 +12,19 @@ where if let Some(path) = url.into().as_path() { Local::cache(path) } else { None } } +#[inline] +pub async fn calculate<'a, U>(url: U) -> io::Result +where + U: Into>, +{ + let url: Url = url.into(); + if let Some(path) = url.as_path() { + local::SizeCalculator::total(path).await + } else { + super::SizeCalculator::total(url).await + } +} + #[inline] pub async fn canonicalize<'a, U>(url: U) -> io::Result where @@ -156,18 +169,6 @@ where } } -#[inline] -pub fn read_dir_sync<'a, U>(url: U) -> io::Result -where - U: Into>, -{ - if let Some(path) = url.into().as_path() { - Local::read_dir_sync(path).map(Into::into) - } else { - Err(io::Error::new(io::ErrorKind::Unsupported, "Unsupported filesystem")) - } -} - #[inline] pub async fn read_link<'a, U>(url: U) -> io::Result where @@ -278,18 +279,6 @@ where } } -#[inline] -pub fn symlink_metadata_sync<'a, U>(url: U) -> io::Result -where - U: Into>, -{ - if let Some(path) = url.into().as_path() { - Local::symlink_metadata_sync(path) - } else { - Err(io::Error::new(io::ErrorKind::Unsupported, "Unsupported filesystem")) - } -} - #[inline] pub async fn trash<'a, U>(url: U) -> io::Result<()> where diff --git a/yazi-fs/src/provider/read_dir.rs b/yazi-fs/src/provider/read_dir.rs index 25b65ac5..0a1972d9 100644 --- a/yazi-fs/src/provider/read_dir.rs +++ b/yazi-fs/src/provider/read_dir.rs @@ -1,6 +1,6 @@ use std::io; -use super::{DirEntry, DirEntrySync}; +use super::DirEntry; pub enum ReadDir { Local(super::local::ReadDir), @@ -13,18 +13,3 @@ impl ReadDir { } } } - -// --- ReadDirSync -pub enum ReadDirSync { - Local(super::local::ReadDirSync), -} - -impl Iterator for ReadDirSync { - type Item = io::Result; - - fn next(&mut self) -> Option> { - match self { - Self::Local(local) => local.next().map(|result| result.map(Into::into)), - } - } -} diff --git a/yazi-fs/src/provider/rw_file.rs b/yazi-fs/src/provider/rw_file.rs index 3ff74c4a..0156fd6f 100644 --- a/yazi-fs/src/provider/rw_file.rs +++ b/yazi-fs/src/provider/rw_file.rs @@ -1,13 +1,71 @@ -use crate::provider::BufRead; +use std::pin::Pin; + +use tokio::io::{AsyncRead, AsyncWrite}; pub enum RwFile { Local(super::local::RwFile), } -impl RwFile { - pub fn reader(self) -> Box { - match self { - Self::Local(local) => Box::new(local.reader()), +impl AsyncRead for RwFile { + #[inline] + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + buf: &mut tokio::io::ReadBuf<'_>, + ) -> std::task::Poll> { + match &mut *self { + Self::Local(f) => Pin::new(f).poll_read(cx, buf), + } + } +} + +impl AsyncWrite for RwFile { + #[inline] + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + buf: &[u8], + ) -> std::task::Poll> { + match &mut *self { + Self::Local(f) => Pin::new(f).poll_write(cx, buf), + } + } + + #[inline] + fn poll_flush( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + match &mut *self { + Self::Local(f) => Pin::new(f).poll_flush(cx), + } + } + + #[inline] + fn poll_shutdown( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + match &mut *self { + Self::Local(f) => Pin::new(f).poll_shutdown(cx), + } + } + + #[inline] + fn poll_write_vectored( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> std::task::Poll> { + match &mut *self { + Self::Local(f) => Pin::new(f).poll_write_vectored(cx, bufs), + } + } + + #[inline] + fn is_write_vectored(&self) -> bool { + match self { + Self::Local(f) => f.is_write_vectored(), } } } diff --git a/yazi-fs/src/provider/sftp/sftp.rs b/yazi-fs/src/provider/sftp/sftp.rs index 6732e35a..a3f030ba 100644 --- a/yazi-fs/src/provider/sftp/sftp.rs +++ b/yazi-fs/src/provider/sftp/sftp.rs @@ -84,13 +84,6 @@ impl Sftp { todo!() } - pub fn read_dir_sync

(path: P) -> io::Result<()> - where - P: AsRef, - { - todo!() - } - pub async fn read_link

(path: P) -> io::Result where P: AsRef, @@ -166,13 +159,6 @@ impl Sftp { todo!() } - pub fn symlink_metadata_sync

(path: P) -> io::Result - where - P: AsRef, - { - todo!() - } - pub async fn trash

(path: P) -> io::Result<()> where P: AsRef, diff --git a/yazi-macro/Cargo.toml b/yazi-macro/Cargo.toml index 38de735a..e267afe7 100644 --- a/yazi-macro/Cargo.toml +++ b/yazi-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-macro" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] diff --git a/yazi-packing/Cargo.toml b/yazi-packing/Cargo.toml index b2be4419..47f5a87e 100644 --- a/yazi-packing/Cargo.toml +++ b/yazi-packing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-packing" -version = "25.5.28" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] diff --git a/yazi-parser/Cargo.toml b/yazi-parser/Cargo.toml index 7fd56147..37d7d295 100644 --- a/yazi-parser/Cargo.toml +++ b/yazi-parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-parser" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -13,12 +13,12 @@ default = [ "vendored-lua" ] vendored-lua = [ "mlua/vendored" ] [dependencies] -yazi-binding = { path = "../yazi-binding", version = "25.6.11" } -yazi-boot = { path = "../yazi-boot", version = "25.6.11" } -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-binding = { path = "../yazi-binding", version = "25.9.15" } +yazi-boot = { path = "../yazi-boot", version = "25.9.15" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-plugin/Cargo.toml b/yazi-plugin/Cargo.toml index 5da15c92..d82c7bc2 100644 --- a/yazi-plugin/Cargo.toml +++ b/yazi-plugin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-plugin" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -13,17 +13,17 @@ default = [ "vendored-lua" ] vendored-lua = [ "mlua/vendored" ] [dependencies] -yazi-adapter = { path = "../yazi-adapter", version = "25.6.11" } -yazi-binding = { path = "../yazi-binding", version = "25.6.11" } -yazi-boot = { path = "../yazi-boot", version = "25.6.11" } -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-dds = { path = "../yazi-dds", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-parser = { path = "../yazi-parser", version = "25.6.11" } -yazi-proxy = { path = "../yazi-proxy", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } -yazi-widgets = { path = "../yazi-widgets", version = "25.6.11" } +yazi-adapter = { path = "../yazi-adapter", version = "25.9.15" } +yazi-binding = { path = "../yazi-binding", version = "25.9.15" } +yazi-boot = { path = "../yazi-boot", version = "25.9.15" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-dds = { path = "../yazi-dds", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-parser = { path = "../yazi-parser", version = "25.9.15" } +yazi-proxy = { path = "../yazi-proxy", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-widgets = { path = "../yazi-widgets", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-plugin/preset/plugins/archive.lua b/yazi-plugin/preset/plugins/archive.lua index 868c2d9e..596ad1c7 100644 --- a/yazi-plugin/preset/plugins/archive.lua +++ b/yazi-plugin/preset/plugins/archive.lua @@ -16,7 +16,7 @@ function M:peek(job) for _, f in ipairs(files) do local icon = File({ url = Url(f.path), - cha = Cha { kind = f.attr:sub(1, 1) == "D" and 1 or 0 }, + cha = Cha { mode = tonumber(f.attr:sub(1, 1) == "D" and "40700" or "100644", 8) }, }):icon() if f.size > 0 then diff --git a/yazi-plugin/src/bindings/calculator.rs b/yazi-plugin/src/bindings/calculator.rs index 8cf8e11a..2c9f9163 100644 --- a/yazi-plugin/src/bindings/calculator.rs +++ b/yazi-plugin/src/bindings/calculator.rs @@ -1,12 +1,20 @@ use mlua::{IntoLuaMulti, UserData, UserDataMethods, Value}; use yazi_binding::Error; -pub struct SizeCalculator(pub yazi_fs::SizeCalculator); +pub enum SizeCalculator { + Local(yazi_fs::provider::local::SizeCalculator), + Remote(yazi_fs::provider::SizeCalculator), +} impl UserData for SizeCalculator { fn add_methods>(methods: &mut M) { methods.add_async_method_mut("recv", |lua, mut me, ()| async move { - match me.0.next().await { + let next = match &mut *me { + Self::Local(it) => it.next().await, + Self::Remote(it) => it.next().await, + }; + + match next { Ok(value) => value.into_lua_multi(&lua), Err(e) => (Value::Nil, Error::Io(e)).into_lua_multi(&lua), } diff --git a/yazi-plugin/src/external/highlighter.rs b/yazi-plugin/src/external/highlighter.rs index 4386b7cf..9d3b3f10 100644 --- a/yazi-plugin/src/external/highlighter.rs +++ b/yazi-plugin/src/external/highlighter.rs @@ -3,9 +3,9 @@ use std::{borrow::Cow, io::Cursor, mem, path::{Path, PathBuf}, sync::OnceLock}; use anyhow::{Result, anyhow}; use ratatui::{layout::Size, text::{Line, Span, Text}}; use syntect::{LoadingError, dumps, easy::HighlightLines, highlighting::{self, Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}}; -use tokio::io::AsyncBufReadExt; +use tokio::io::{AsyncBufReadExt, AsyncSeekExt, BufReader}; use yazi_config::{THEME, YAZI, preview::PreviewWrap}; -use yazi_fs::provider::local::Local; +use yazi_fs::provider::local::{self, Local}; use yazi_shared::{Ids, errors::PeekError, replace_to_printable}; static INCR: Ids = Ids::new(); @@ -39,9 +39,9 @@ impl Highlighter { pub fn abort() { INCR.next(); } pub async fn highlight(&self, skip: usize, size: Size) -> Result, PeekError> { - let mut reader = Local::open(&self.path).await?.reader(); + let mut reader = BufReader::new(Local::open(&self.path).await?); - let syntax = Self::find_syntax(&self.path).await; + let syntax = Self::find_syntax(&self.path, &mut reader).await; let mut plain = syntax.is_err(); let mut before = Vec::with_capacity(if plain { 0 } else { skip }); @@ -130,7 +130,10 @@ impl Highlighter { .await? } - async fn find_syntax(path: &Path) -> Result<&'static SyntaxReference> { + async fn find_syntax( + path: &Path, + reader: &mut BufReader, + ) -> Result<&'static SyntaxReference> { let (_, syntaxes) = Self::init(); let name = path.file_name().map(|n| n.to_string_lossy()).unwrap_or_default(); if let Some(s) = syntaxes.find_syntax_by_extension(&name) { @@ -143,8 +146,8 @@ impl Highlighter { } let mut line = String::new(); - let mut reader = Local::open(&path).await?.reader(); reader.read_line(&mut line).await?; + reader.rewind().await?; syntaxes.find_syntax_by_first_line(&line).ok_or_else(|| anyhow!("No syntax found")) } diff --git a/yazi-plugin/src/fs/fs.rs b/yazi-plugin/src/fs/fs.rs index 48b76faf..10661ad0 100644 --- a/yazi-plugin/src/fs/fs.rs +++ b/yazi-plugin/src/fs/fs.rs @@ -147,8 +147,14 @@ fn read_dir(lua: &Lua) -> mlua::Result { fn calc_size(lua: &Lua) -> mlua::Result { lua.create_async_function(|lua, url: UrlRef| async move { - match yazi_fs::SizeCalculator::new(&url).await { - Ok(it) => SizeCalculator(it).into_lua_multi(&lua), + let it = if let Some(path) = url.as_path() { + provider::local::SizeCalculator::new(path).await.map(SizeCalculator::Local) + } else { + provider::SizeCalculator::new(&*url).await.map(SizeCalculator::Remote) + }; + + match it { + Ok(it) => it.into_lua_multi(&lua), Err(e) => (Value::Nil, Error::Io(e)).into_lua_multi(&lua), } }) diff --git a/yazi-proxy/Cargo.toml b/yazi-proxy/Cargo.toml index 85193e4c..d794362f 100644 --- a/yazi-proxy/Cargo.toml +++ b/yazi-proxy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-proxy" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,10 +9,10 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-parser = { path = "../yazi-parser", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-parser = { path = "../yazi-parser", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-scheduler/Cargo.toml b/yazi-scheduler/Cargo.toml index 941c66b4..25db85a5 100644 --- a/yazi-scheduler/Cargo.toml +++ b/yazi-scheduler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-scheduler" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,14 +9,14 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-dds = { path = "../yazi-dds", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-parser = { path = "../yazi-parser", version = "25.6.11" } -yazi-plugin = { path = "../yazi-plugin", version = "25.6.11" } -yazi-proxy = { path = "../yazi-proxy", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-dds = { path = "../yazi-dds", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-parser = { path = "../yazi-parser", version = "25.9.15" } +yazi-plugin = { path = "../yazi-plugin", version = "25.9.15" } +yazi-proxy = { path = "../yazi-proxy", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-scheduler/src/prework/prework.rs b/yazi-scheduler/src/prework/prework.rs index e467c208..866b0a1c 100644 --- a/yazi-scheduler/src/prework/prework.rs +++ b/yazi-scheduler/src/prework/prework.rs @@ -8,7 +8,7 @@ use tokio::sync::mpsc; use tokio_util::sync::CancellationToken; use tracing::error; use yazi_config::Priority; -use yazi_fs::{FilesOp, SizeCalculator}; +use yazi_fs::{FilesOp, provider}; use yazi_plugin::isolate; use yazi_shared::{event::CmdCow, url::UrlBuf}; @@ -93,7 +93,7 @@ impl Prework { } pub(crate) async fn size_do(&self, task: PreworkInSize) -> Result<(), PreworkOutSize> { - let length = SizeCalculator::total(&task.target).await.unwrap_or(0); + let length = provider::calculate(&task.target).await.unwrap_or(0); task.throttle.done((task.target, length), |buf| { { let mut loading = self.sizing.write(); diff --git a/yazi-sftp/src/fs/dir_entry.rs b/yazi-sftp/src/fs/dir_entry.rs index aa273649..218f728d 100644 --- a/yazi-sftp/src/fs/dir_entry.rs +++ b/yazi-sftp/src/fs/dir_entry.rs @@ -10,10 +10,13 @@ pub struct DirEntry<'a> { } impl<'a> DirEntry<'a> { + #[must_use] pub fn path(&self) -> PathBuf { self.dir.join(&self.name) } + #[must_use] pub fn name(&self) -> Cow<'_, OsStr> { self.name.to_os_str() } + #[must_use] pub fn long_name(&self) -> Cow<'_, OsStr> { self.long_name.to_os_str() } pub fn attrs(&self) -> &Attrs { &self.attrs } diff --git a/yazi-shared/Cargo.toml b/yazi-shared/Cargo.toml index 562fe753..23c448e5 100644 --- a/yazi-shared/Cargo.toml +++ b/yazi-shared/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-shared" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -10,7 +10,7 @@ repository = "https://github.com/sxyazi/yazi" rust-version = "1.88.0" [dependencies] -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } # External dependencies anyhow = { workspace = true } diff --git a/yazi-term/Cargo.toml b/yazi-term/Cargo.toml index 159af5de..99ab5237 100644 --- a/yazi-term/Cargo.toml +++ b/yazi-term/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-term" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,8 +9,8 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # Logging tracing = { workspace = true } diff --git a/yazi-watcher/Cargo.toml b/yazi-watcher/Cargo.toml index eeb5bff3..1c700a94 100644 --- a/yazi-watcher/Cargo.toml +++ b/yazi-watcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-watcher" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,11 +9,11 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-adapter = { path = "../yazi-adapter", version = "25.6.11" } -yazi-dds = { path = "../yazi-dds", version = "25.6.11" } -yazi-fs = { path = "../yazi-fs", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } +yazi-adapter = { path = "../yazi-adapter", version = "25.9.15" } +yazi-dds = { path = "../yazi-dds", version = "25.9.15" } +yazi-fs = { path = "../yazi-fs", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # Logging tracing = { workspace = true } diff --git a/yazi-widgets/Cargo.toml b/yazi-widgets/Cargo.toml index 5bc5fc64..815eb3c0 100644 --- a/yazi-widgets/Cargo.toml +++ b/yazi-widgets/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yazi-widgets" -version = "25.6.11" +version = "25.9.15" edition = "2024" license = "MIT" authors = [ "sxyazi " ] @@ -9,12 +9,12 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-binding = { path = "../yazi-binding", version = "25.6.11" } -yazi-config = { path = "../yazi-config", version = "25.6.11" } -yazi-macro = { path = "../yazi-macro", version = "25.6.11" } -yazi-parser = { path = "../yazi-parser", version = "25.6.11" } -yazi-shared = { path = "../yazi-shared", version = "25.6.11" } -yazi-term = { path = "../yazi-term", version = "25.6.11" } +yazi-binding = { path = "../yazi-binding", version = "25.9.15" } +yazi-config = { path = "../yazi-config", version = "25.9.15" } +yazi-macro = { path = "../yazi-macro", version = "25.9.15" } +yazi-parser = { path = "../yazi-parser", version = "25.9.15" } +yazi-shared = { path = "../yazi-shared", version = "25.9.15" } +yazi-term = { path = "../yazi-term", version = "25.9.15" } # External dependencies anyhow = { workspace = true }