feat: size calculator for remote file systems (#3170)

This commit is contained in:
三咲雅 misaki masa 2025-09-15 21:42:33 +08:00 committed by sxyazi
parent a3fc9a0ec7
commit 7deeaa4356
No known key found for this signature in database
53 changed files with 721 additions and 567 deletions

84
Cargo.lock generated
View file

@ -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",

View file

@ -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"

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-actor"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-adapter"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
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-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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-binding"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }

View file

@ -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<F: UserDataFields<Self>>(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<M: UserDataMethods<Self>>(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::<String>,
Ok::<_, mlua::Error>(mlua::Value::Nil),
)
});
}

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-boot"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
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.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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-build"
version = "0.1.8"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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"

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-cli"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-codegen"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-config"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
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-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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-core"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
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.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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-dds"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }

View file

@ -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();

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-ffi"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
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.6.11" }
yazi-macro = { path = "../yazi-macro", version = "25.9.15" }
# External dependencies
anyhow = { workspace = true }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-fm"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-fs"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
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.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 }

View file

@ -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<SystemTime>,
pub btime: Option<SystemTime>,
@ -16,21 +17,26 @@ pub struct Cha {
pub ctime: Option<SystemTime>,
pub mtime: Option<SystemTime>,
#[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<Url<'a>>, 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<Url<'a>>,
{
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<Url<'a>>, mut meta: Metadata) -> Self {
pub async fn from_follow<'a, U>(url: U, mut meta: Metadata) -> Self
where
U: Into<Url<'a>>,
{
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<FileType>) -> 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<FileType>) -> Self
where
U: Into<Url<'a>>,
{
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) }
}

View file

@ -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<Url<'a>>, _meta: &Metadata) -> Self {
pub(super) fn hidden<'a, U>(_url: U, _meta: &Metadata) -> Self
where
U: Into<Url<'a>>,
{
let mut me = Self::empty();
#[cfg(unix)]

View file

@ -1 +1 @@
yazi_macro::mod_flat!(cha kind);
yazi_macro::mod_flat!(cha kind mode);

158
yazi-fs/src/cha/mode.rs Normal file
View file

@ -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) }
}

View file

@ -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

View file

@ -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());

View file

@ -1,9 +0,0 @@
// --- BufRead
pub trait BufRead: tokio::io::AsyncRead + Send {}
impl<T: tokio::io::AsyncRead + Send> BufRead for T {}
// --- BufReadSync
pub trait BufReadSync: std::io::BufRead + std::io::Seek + Send {}
impl<T: std::io::BufRead + std::io::Seek + Send> BufReadSync for T {}

View file

@ -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<u64>),
Dir(VecDeque<Either<UrlBuf, ReadDir>>),
}
impl SizeCalculator {
pub async fn new<'a, U>(url: U) -> io::Result<Self>
where
U: Into<Url<'a>>,
{
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<u64>
where
U: Into<Url<'a>>,
{
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<Option<u64>> {
Ok(match self {
Self::File(size) => size.take(),
Self::Dir(buf) => Self::next_chunk(buf).await,
})
}
async fn next_chunk(buf: &mut VecDeque<Either<UrlBuf, ReadDir>>) -> Option<u64> {
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)
}
}

View file

@ -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<std::fs::Metadata> {
match self {
Self::Local(local) => local.metadata(),
}
}
pub fn file_type(&self) -> io::Result<std::fs::FileType> {
match self {
Self::Local(local) => local.file_type(),
}
}
}

View file

@ -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<UrlBuf, ReadDirSync>;
type Task = Either<PathBuf, std::fs::ReadDir>;
pub enum SizeCalculator {
Idle((VecDeque<Task>, Option<u64>)),
@ -13,23 +11,23 @@ pub enum SizeCalculator {
}
impl SizeCalculator {
pub async fn new(url: &UrlBuf) -> io::Result<Self> {
let u = url.to_owned();
pub async fn new(path: &Path) -> io::Result<Self> {
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<u64> {
let mut it = Self::new(url).await?;
pub async fn total(path: &Path) -> io::Result<u64> {
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<Either<UrlBuf, ReadDirSync>>) -> Option<u64> {
fn next_chunk(buf: &mut VecDeque<Either<PathBuf, std::fs::ReadDir>>) -> Option<u64> {
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();
}

View file

@ -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<std::fs::DirEntry> for DirEntrySync {
fn from(value: std::fs::DirEntry) -> Self { Self(value) }
}
impl From<DirEntrySync> 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() }
}

View file

@ -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<P>(path: P) -> io::Result<ReadDirSync>
where
P: AsRef<Path>,
{
std::fs::read_dir(path).map(Into::into)
}
#[inline]
pub async fn read_link<P>(path: P) -> io::Result<PathBuf>
where
@ -261,14 +253,6 @@ impl Local {
tokio::fs::symlink_metadata(path).await
}
#[inline]
pub fn symlink_metadata_sync<P>(path: P) -> io::Result<std::fs::Metadata>
where
P: AsRef<Path>,
{
std::fs::symlink_metadata(path)
}
pub async fn trash<P>(path: P) -> io::Result<()>
where
P: AsRef<Path>,

View file

@ -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);

View file

@ -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<std::fs::ReadDir> for ReadDirSync {
fn from(value: std::fs::ReadDir) -> Self { Self(value) }
}
impl From<ReadDirSync> for crate::provider::ReadDirSync {
fn from(value: ReadDirSync) -> Self { Self::Local(value) }
}
impl Iterator for ReadDirSync {
type Item = io::Result<DirEntrySync>;
fn next(&mut self) -> Option<io::Result<DirEntrySync>> {
self.0.next().map(|result| result.map(Into::into))
}
}

View file

@ -1,3 +1,7 @@
use std::{pin::Pin, task::Poll};
use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite};
pub struct RwFile(tokio::fs::File);
impl From<tokio::fs::File> for RwFile {
@ -8,11 +12,67 @@ impl From<RwFile> for crate::provider::RwFile {
fn from(value: RwFile) -> Self { Self::Local(value) }
}
impl From<tokio::fs::File> 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<std::io::Result<()>> {
Pin::new(&mut self.0).poll_read(cx, buf)
}
}
impl RwFile {
impl AsyncSeek for RwFile {
#[inline]
pub fn reader(self) -> tokio::io::BufReader<tokio::fs::File> { 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<std::io::Result<u64>> {
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<Result<usize, std::io::Error>> {
Pin::new(&mut self.0).poll_write(cx, buf)
}
#[inline]
fn poll_flush(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Result<(), std::io::Error>> {
Pin::new(&mut self.0).poll_flush(cx)
}
#[inline]
fn poll_shutdown(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Result<(), std::io::Error>> {
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<Result<usize, std::io::Error>> {
Pin::new(&mut self.0).poll_write_vectored(cx, bufs)
}
#[inline]
fn is_write_vectored(&self) -> bool { self.0.is_write_vectored() }
}

View file

@ -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);

View file

@ -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<PathBuf>
@ -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<u64>
where
U: Into<Url<'a>>,
{
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<UrlBuf>
where
@ -156,18 +169,6 @@ where
}
}
#[inline]
pub fn read_dir_sync<'a, U>(url: U) -> io::Result<ReadDirSync>
where
U: Into<Url<'a>>,
{
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<PathBuf>
where
@ -278,18 +279,6 @@ where
}
}
#[inline]
pub fn symlink_metadata_sync<'a, U>(url: U) -> io::Result<std::fs::Metadata>
where
U: Into<Url<'a>>,
{
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

View file

@ -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<DirEntrySync>;
fn next(&mut self) -> Option<io::Result<DirEntrySync>> {
match self {
Self::Local(local) => local.next().map(|result| result.map(Into::into)),
}
}
}

View file

@ -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<dyn BufRead> {
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<std::io::Result<()>> {
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<Result<usize, std::io::Error>> {
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<Result<(), std::io::Error>> {
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<Result<(), std::io::Error>> {
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<Result<usize, std::io::Error>> {
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(),
}
}
}

View file

@ -84,13 +84,6 @@ impl Sftp {
todo!()
}
pub fn read_dir_sync<P>(path: P) -> io::Result<()>
where
P: AsRef<Path>,
{
todo!()
}
pub async fn read_link<P>(path: P) -> io::Result<PathBuf>
where
P: AsRef<Path>,
@ -166,13 +159,6 @@ impl Sftp {
todo!()
}
pub fn symlink_metadata_sync<P>(path: P) -> io::Result<std::fs::Metadata>
where
P: AsRef<Path>,
{
todo!()
}
pub async fn trash<P>(path: P) -> io::Result<()>
where
P: AsRef<Path>,

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-macro"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-packing"
version = "25.5.28"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-parser"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-plugin"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }

View file

@ -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

View file

@ -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<M: UserDataMethods<Self>>(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),
}

View file

@ -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<Text<'static>, 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<local::RwFile>,
) -> 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"))
}

View file

@ -147,8 +147,14 @@ fn read_dir(lua: &Lua) -> mlua::Result<Function> {
fn calc_size(lua: &Lua) -> mlua::Result<Function> {
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),
}
})

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-proxy"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
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-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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-scheduler"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }

View file

@ -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();

View file

@ -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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-shared"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-term"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-watcher"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
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.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 }

View file

@ -1,6 +1,6 @@
[package]
name = "yazi-widgets"
version = "25.6.11"
version = "25.9.15"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
@ -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 }