From c2affae3a9e7d33e69fc5a2d6dfb01dd252e25b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Sun, 19 May 2024 18:07:36 +0800 Subject: [PATCH] feat: add a `next` property to the preloader rules to allow running multiple preloaders (#1058) --- Cargo.lock | 9 ++-- flake.lock | 12 ++--- yazi-adaptor/Cargo.toml | 2 +- yazi-cli/Cargo.toml | 4 +- yazi-config/Cargo.toml | 2 +- yazi-config/preset/yazi.toml | 18 ++++---- yazi-config/src/open/open.rs | 4 +- yazi-config/src/pattern.rs | 16 +++---- yazi-config/src/plugin/mod.rs | 11 ++--- yazi-config/src/plugin/plugin.rs | 63 +++++++++++++++------------ yazi-config/src/plugin/preloader.rs | 39 +++++++++++++++++ yazi-config/src/plugin/previewer.rs | 21 +++++++++ yazi-config/src/plugin/props.rs | 16 ------- yazi-config/src/plugin/rule.rs | 29 ------------ yazi-config/src/plugin/run.rs | 39 ----------------- yazi-core/Cargo.toml | 4 +- yazi-core/src/tasks/preload.rs | 10 ++--- yazi-dds/Cargo.toml | 2 +- yazi-fm/Cargo.toml | 4 +- yazi-plugin/Cargo.toml | 2 +- yazi-plugin/preset/plugins/zoxide.lua | 10 +++-- yazi-proxy/Cargo.toml | 2 +- yazi-scheduler/Cargo.toml | 4 +- yazi-scheduler/src/preload/op.rs | 4 +- yazi-scheduler/src/scheduler.rs | 8 ++-- yazi-shared/Cargo.toml | 22 +++++----- yazi-shared/src/event/cmd.rs | 48 +++++++++++++++++++- yazi-shared/src/fs/cha.rs | 3 +- 28 files changed, 219 insertions(+), 189 deletions(-) create mode 100644 yazi-config/src/plugin/preloader.rs create mode 100644 yazi-config/src/plugin/previewer.rs delete mode 100644 yazi-config/src/plugin/props.rs delete mode 100644 yazi-config/src/plugin/rule.rs delete mode 100644 yazi-config/src/plugin/run.rs diff --git a/Cargo.lock b/Cargo.lock index 15a5d348..b6521c07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arc-swap" @@ -1086,9 +1086,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libredox" @@ -2924,6 +2924,7 @@ dependencies = [ "ratatui", "regex", "serde", + "shell-words", "tokio", "tracing", ] diff --git a/flake.lock b/flake.lock index 25404c6f..f0a731ee 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1713805509, - "narHash": "sha256-YgSEan4CcrjivCNO5ZNzhg7/8ViLkZ4CB/GrGBVSudo=", + "lastModified": 1716097317, + "narHash": "sha256-1UMrLtgzielG/Sop6gl6oTSM4pDt7rF9j9VuxhDWDlY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1e1dc66fe68972a76679644a5577828b6a7e8be4", + "rev": "8535fb92661f37ff9f0da3007fbc942f7d134b41", "type": "github" }, "original": { @@ -51,11 +51,11 @@ ] }, "locked": { - "lastModified": 1713924823, - "narHash": "sha256-kOeyS3GFwgnKvzuBMmFqEAX0xwZ7Nj4/5tXuvpZ0d4U=", + "lastModified": 1716085073, + "narHash": "sha256-3+9gI93XxszWA2+9S2xZfws1QArPX/MC6nahOGpcMB4=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "8a2edac3ae926a2a6ce60f4595dcc4540fc8cad4", + "rev": "cfc8776011bd83508324115d353222475e1601c0", "type": "github" }, "original": { diff --git a/yazi-adaptor/Cargo.toml b/yazi-adaptor/Cargo.toml index eb0efecd..1aa1ad56 100644 --- a/yazi-adaptor/Cargo.toml +++ b/yazi-adaptor/Cargo.toml @@ -13,7 +13,7 @@ yazi-config = { path = "../yazi-config", version = "0.2.5" } yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies -anyhow = "1.0.83" +anyhow = "1.0.86" arc-swap = "1.7.1" base64 = "0.22.1" color_quant = "1.1.0" diff --git a/yazi-cli/Cargo.toml b/yazi-cli/Cargo.toml index 37c6b86c..7b14c060 100644 --- a/yazi-cli/Cargo.toml +++ b/yazi-cli/Cargo.toml @@ -13,7 +13,7 @@ yazi-dds = { path = "../yazi-dds", version = "0.2.5" } yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies -anyhow = "1.0.83" +anyhow = "1.0.86" clap = { version = "4.5.4", features = [ "derive" ] } crossterm = "0.27.0" md-5 = "0.10.6" @@ -22,7 +22,7 @@ tokio = { version = "1.37.0", features = [ "full" ] } toml_edit = "0.22.13" [build-dependencies] -anyhow = "1.0.83" +anyhow = "1.0.86" clap = { version = "4.5.4", features = [ "derive" ] } clap_complete = "4.5.2" clap_complete_fig = "4.5.0" diff --git a/yazi-config/Cargo.toml b/yazi-config/Cargo.toml index 86ad1138..53cc643d 100644 --- a/yazi-config/Cargo.toml +++ b/yazi-config/Cargo.toml @@ -12,7 +12,7 @@ repository = "https://github.com/sxyazi/yazi" yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies -anyhow = "1.0.83" +anyhow = "1.0.86" arc-swap = "1.7.1" crossterm = "0.27.0" globset = "0.4.14" diff --git a/yazi-config/preset/yazi.toml b/yazi-config/preset/yazi.toml index 0bad8712..d0935c5c 100644 --- a/yazi-config/preset/yazi.toml +++ b/yazi-config/preset/yazi.toml @@ -80,12 +80,12 @@ suppress_preload = false [plugin] preloaders = [ - { name = "*", cond = "!mime", run = "mime", multi = true, prio = "high" }, + { name = "*", cond = "!mime", run = "mime", next = true, multi = true, prio = "high" }, # Image - { mime = "image/svg+xml", run = "magick" }, - { mime = "image/heic", run = "magick" }, - { mime = "image/jxl", run = "magick" }, - { mime = "image/*", run = "image" }, + { mime = "image/svg+xml", run = "magick" }, + { mime = "image/heic", run = "magick" }, + { mime = "image/jxl", run = "magick" }, + { mime = "image/*", run = "image" }, # Video { mime = "video/*", run = "video" }, # PDF @@ -102,10 +102,10 @@ previewers = [ # JSON { mime = "application/json", run = "json" }, # Image - { mime = "image/svg+xml", run = "magick" }, - { mime = "image/heic", run = "magick" }, - { mime = "image/jxl", run = "magick" }, - { mime = "image/*", run = "image" }, + { mime = "image/svg+xml", run = "magick" }, + { mime = "image/heic", run = "magick" }, + { mime = "image/jxl", run = "magick" }, + { mime = "image/*", run = "image" }, # Video { mime = "video/*", run = "video" }, # PDF diff --git a/yazi-config/src/open/open.rs b/yazi-config/src/open/open.rs index 610bdc62..6d5fc5e2 100644 --- a/yazi-config/src/open/open.rs +++ b/yazi-config/src/open/open.rs @@ -23,10 +23,10 @@ impl Open { P: AsRef, M: AsRef, { - let is_folder = mime.as_ref() == MIME_DIR; + let is_dir = mime.as_ref() == MIME_DIR; self.rules.iter().find_map(|rule| { if rule.mime.as_ref().is_some_and(|p| p.match_mime(&mime)) - || rule.name.as_ref().is_some_and(|p| p.match_path(&path, is_folder)) + || rule.name.as_ref().is_some_and(|p| p.match_path(&path, is_dir)) { let openers = rule .use_ diff --git a/yazi-config/src/pattern.rs b/yazi-config/src/pattern.rs index cbe874d8..b183f04e 100644 --- a/yazi-config/src/pattern.rs +++ b/yazi-config/src/pattern.rs @@ -6,9 +6,9 @@ use serde::Deserialize; #[derive(Debug, Deserialize)] #[serde(try_from = "String")] pub struct Pattern { - inner: globset::GlobMatcher, - is_star: bool, - is_folder: bool, + inner: globset::GlobMatcher, + is_dir: bool, + is_star: bool, } impl Pattern { @@ -16,15 +16,15 @@ impl Pattern { pub fn match_mime(&self, str: impl AsRef) -> bool { self.inner.is_match(str.as_ref()) } #[inline] - pub fn match_path(&self, path: impl AsRef, is_folder: bool) -> bool { - is_folder == self.is_folder && (self.is_star || self.inner.is_match(path)) + pub fn match_path(&self, path: impl AsRef, is_dir: bool) -> bool { + is_dir == self.is_dir && (self.is_star || self.inner.is_match(path)) } #[inline] - pub fn any_file(&self) -> bool { self.is_star && !self.is_folder } + pub fn any_file(&self) -> bool { self.is_star && !self.is_dir } #[inline] - pub fn any_dir(&self) -> bool { self.is_star && self.is_folder } + pub fn any_dir(&self) -> bool { self.is_star && self.is_dir } } impl TryFrom<&str> for Pattern { @@ -42,7 +42,7 @@ impl TryFrom<&str> for Pattern { .build()? .compile_matcher(); - Ok(Self { inner, is_star: b == "*", is_folder: b.len() < a.len() }) + Ok(Self { inner, is_dir: b.len() < a.len(), is_star: b == "*" }) } } diff --git a/yazi-config/src/plugin/mod.rs b/yazi-config/src/plugin/mod.rs index 6147d1b8..c49d10a9 100644 --- a/yazi-config/src/plugin/mod.rs +++ b/yazi-config/src/plugin/mod.rs @@ -1,12 +1,9 @@ mod plugin; -mod props; -mod rule; -mod run; +mod preloader; +mod previewer; pub use plugin::*; -pub use props::*; -pub use rule::*; -#[allow(unused_imports)] -pub use run::*; +pub use preloader::*; +pub use previewer::*; pub const MAX_PRELOADERS: u8 = 32; diff --git a/yazi-config/src/plugin/plugin.rs b/yazi-config/src/plugin/plugin.rs index 0d226037..00c60965 100644 --- a/yazi-config/src/plugin/plugin.rs +++ b/yazi-config/src/plugin/plugin.rs @@ -3,13 +3,13 @@ use std::path::Path; use serde::Deserialize; use yazi_shared::MIME_DIR; -use super::PluginRule; +use super::{Preloader, Previewer}; use crate::{plugin::MAX_PRELOADERS, Preset, MERGED_YAZI}; #[derive(Deserialize)] pub struct Plugin { - pub preloaders: Vec, - pub previewers: Vec, + pub preloaders: Vec, + pub previewers: Vec, } impl Default for Plugin { @@ -21,17 +21,17 @@ impl Default for Plugin { #[derive(Deserialize)] struct Shadow { - preloaders: Vec, + preloaders: Vec, #[serde(default)] - prepend_preloaders: Vec, + prepend_preloaders: Vec, #[serde(default)] - append_preloaders: Vec, + append_preloaders: Vec, - previewers: Vec, + previewers: Vec, #[serde(default)] - prepend_previewers: Vec, + prepend_previewers: Vec, #[serde(default)] - append_previewers: Vec, + append_previewers: Vec, } let mut shadow = toml::from_str::(&MERGED_YAZI).unwrap().plugin; @@ -50,9 +50,6 @@ impl Default for Plugin { } for (i, preloader) in shadow.preloaders.iter_mut().enumerate() { - if preloader.sync { - panic!("Preloaders cannot be synchronous"); - } preloader.id = i as u8; } @@ -66,24 +63,34 @@ impl Plugin { path: &Path, mime: Option<&str>, f: impl Fn(&str) -> bool + Copy, - ) -> Vec<&PluginRule> { - let is_folder = mime == Some(MIME_DIR); - self - .preloaders - .iter() - .filter(|&rule| { - rule.cond.as_ref().and_then(|c| c.eval(f)) != Some(false) - && (rule.mime.as_ref().zip(mime).map_or(false, |(p, m)| p.match_mime(m)) - || rule.name.as_ref().is_some_and(|p| p.match_path(path, is_folder))) - }) - .collect() + ) -> Vec<&Preloader> { + let is_dir = mime == Some(MIME_DIR); + let mut preloaders = Vec::with_capacity(1); + + for p in &self.preloaders { + if p.cond.as_ref().and_then(|c| c.eval(f)) == Some(false) { + continue; + } + + if !p.mime.as_ref().zip(mime).map_or(false, |(p, m)| p.match_mime(m)) + && !p.name.as_ref().is_some_and(|p| p.match_path(path, is_dir)) + { + continue; + } + + preloaders.push(p); + if !p.next { + break; + } + } + preloaders } - pub fn previewer(&self, path: &Path, mime: &str) -> Option<&PluginRule> { - let is_folder = mime == MIME_DIR; - self.previewers.iter().find(|&rule| { - rule.mime.as_ref().is_some_and(|p| p.match_mime(mime)) - || rule.name.as_ref().is_some_and(|p| p.match_path(path, is_folder)) + pub fn previewer(&self, path: &Path, mime: &str) -> Option<&Previewer> { + let is_dir = mime == MIME_DIR; + self.previewers.iter().find(|&p| { + p.mime.as_ref().is_some_and(|p| p.match_mime(mime)) + || p.name.as_ref().is_some_and(|p| p.match_path(path, is_dir)) }) } } diff --git a/yazi-config/src/plugin/preloader.rs b/yazi-config/src/plugin/preloader.rs new file mode 100644 index 00000000..64a43b3b --- /dev/null +++ b/yazi-config/src/plugin/preloader.rs @@ -0,0 +1,39 @@ +use serde::Deserialize; +use yazi_shared::{event::Cmd, Condition}; + +use crate::{Pattern, Priority}; + +#[derive(Debug, Deserialize)] +pub struct Preloader { + #[serde(skip)] + pub id: u8, + pub cond: Option, + pub name: Option, + pub mime: Option, + pub run: Cmd, + #[serde(default)] + pub next: bool, + #[serde(default)] + pub multi: bool, + #[serde(default)] + pub prio: Priority, +} + +#[derive(Debug, Clone)] +pub struct PreloaderProps { + pub id: u8, + pub name: String, + pub multi: bool, + pub prio: Priority, +} + +impl From<&Preloader> for PreloaderProps { + fn from(preloader: &Preloader) -> Self { + Self { + id: preloader.id, + name: preloader.run.name.to_owned(), + multi: preloader.multi, + prio: preloader.prio, + } + } +} diff --git a/yazi-config/src/plugin/previewer.rs b/yazi-config/src/plugin/previewer.rs new file mode 100644 index 00000000..a960201f --- /dev/null +++ b/yazi-config/src/plugin/previewer.rs @@ -0,0 +1,21 @@ +use serde::Deserialize; +use yazi_shared::event::Cmd; + +use crate::Pattern; + +#[derive(Debug, Deserialize)] +pub struct Previewer { + pub name: Option, + pub mime: Option, + pub run: Cmd, + #[serde(default)] + pub sync: bool, +} + +impl Previewer { + #[inline] + pub fn any_file(&self) -> bool { self.name.as_ref().is_some_and(|p| p.any_file()) } + + #[inline] + pub fn any_dir(&self) -> bool { self.name.as_ref().is_some_and(|p| p.any_dir()) } +} diff --git a/yazi-config/src/plugin/props.rs b/yazi-config/src/plugin/props.rs deleted file mode 100644 index 91035c60..00000000 --- a/yazi-config/src/plugin/props.rs +++ /dev/null @@ -1,16 +0,0 @@ -use super::PluginRule; -use crate::Priority; - -#[derive(Debug, Clone)] -pub struct PluginProps { - pub id: u8, - pub name: String, - pub multi: bool, - pub prio: Priority, -} - -impl From<&PluginRule> for PluginProps { - fn from(rule: &PluginRule) -> Self { - Self { id: rule.id, name: rule.run.name.to_owned(), multi: rule.multi, prio: rule.prio } - } -} diff --git a/yazi-config/src/plugin/rule.rs b/yazi-config/src/plugin/rule.rs deleted file mode 100644 index b08c20e4..00000000 --- a/yazi-config/src/plugin/rule.rs +++ /dev/null @@ -1,29 +0,0 @@ -use serde::Deserialize; -use yazi_shared::{event::Cmd, Condition}; - -use crate::{Pattern, Priority}; - -#[derive(Debug, Deserialize)] -pub struct PluginRule { - #[serde(skip)] - pub id: u8, - pub cond: Option, - pub name: Option, - pub mime: Option, - #[serde(deserialize_with = "super::run_deserialize")] - pub run: Cmd, - #[serde(default)] - pub sync: bool, - #[serde(default)] - pub multi: bool, - #[serde(default)] - pub prio: Priority, -} - -impl PluginRule { - #[inline] - pub fn any_file(&self) -> bool { self.name.as_ref().is_some_and(|p| p.any_file()) } - - #[inline] - pub fn any_dir(&self) -> bool { self.name.as_ref().is_some_and(|p| p.any_dir()) } -} diff --git a/yazi-config/src/plugin/run.rs b/yazi-config/src/plugin/run.rs deleted file mode 100644 index 1ddcb561..00000000 --- a/yazi-config/src/plugin/run.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::fmt; - -use anyhow::Result; -use serde::{de::{self, Visitor}, Deserializer}; -use yazi_shared::event::Cmd; - -pub(super) fn run_deserialize<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - struct RunVisitor; - - impl<'de> Visitor<'de> for RunVisitor { - type Value = Cmd; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a `run` string or array of strings") - } - - fn visit_seq(self, _: A) -> Result - where - A: de::SeqAccess<'de>, - { - Err(de::Error::custom("`run` within [plugin] must be a string")) - } - - fn visit_str(self, value: &str) -> Result - where - E: de::Error, - { - if value.is_empty() { - return Err(de::Error::custom("`run` within [plugin] cannot be empty")); - } - Ok(Cmd { name: value.to_owned(), ..Default::default() }) - } - } - - deserializer.deserialize_any(RunVisitor) -} diff --git a/yazi-core/Cargo.toml b/yazi-core/Cargo.toml index 982fb9ab..ac5cd106 100644 --- a/yazi-core/Cargo.toml +++ b/yazi-core/Cargo.toml @@ -19,7 +19,7 @@ yazi-scheduler = { path = "../yazi-scheduler", version = "0.2.5" } yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies -anyhow = "1.0.83" +anyhow = "1.0.86" bitflags = "2.5.0" crossterm = "0.27.0" futures = "0.3.30" @@ -39,4 +39,4 @@ shell-words = "1.1.0" tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] } [target."cfg(unix)".dependencies] -libc = "0.2.154" +libc = "0.2.155" diff --git a/yazi-core/src/tasks/preload.rs b/yazi-core/src/tasks/preload.rs index 8f1915df..71c0697d 100644 --- a/yazi-core/src/tasks/preload.rs +++ b/yazi-core/src/tasks/preload.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, mem}; -use yazi_config::{manager::SortBy, plugin::{PluginRule, MAX_PRELOADERS}, PLUGIN}; +use yazi_config::{manager::SortBy, plugin::{Preloader, MAX_PRELOADERS}, PLUGIN}; use yazi_shared::{fs::{File, Url}, MIME_DIR}; use super::Tasks; @@ -34,15 +34,15 @@ impl Tasks { drop(loaded); let mut loaded = self.scheduler.preload.rule_loaded.write(); - let mut go = |rule: &PluginRule, targets: Vec<&File>| { + let mut go = |preloader: &Preloader, targets: Vec<&File>| { for &f in &targets { if let Some(n) = loaded.get_mut(&f.url) { - *n |= 1 << rule.id; + *n |= 1 << preloader.id; } else { - loaded.insert(f.url.clone(), 1 << rule.id); + loaded.insert(f.url.clone(), 1 << preloader.id); } } - self.scheduler.preload_paged(rule, targets); + self.scheduler.preload_paged(preloader, targets); }; #[allow(clippy::needless_range_loop)] diff --git a/yazi-dds/Cargo.toml b/yazi-dds/Cargo.toml index ee016479..2fefb249 100644 --- a/yazi-dds/Cargo.toml +++ b/yazi-dds/Cargo.toml @@ -17,7 +17,7 @@ yazi-boot = { path = "../yazi-boot", version = "0.2.5" } yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies -anyhow = "1.0.83" +anyhow = "1.0.86" mlua = { version = "0.9.8", features = [ "lua54" ] } parking_lot = "0.12.2" serde = { version = "1.0.202", features = [ "derive" ] } diff --git a/yazi-fm/Cargo.toml b/yazi-fm/Cargo.toml index 7a376924..89c93979 100644 --- a/yazi-fm/Cargo.toml +++ b/yazi-fm/Cargo.toml @@ -23,7 +23,7 @@ yazi-proxy = { path = "../yazi-proxy", version = "0.2.5" } yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies -anyhow = "1.0.83" +anyhow = "1.0.86" better-panic = "0.3.0" crossterm = { version = "0.27.0", features = [ "event-stream" ] } fdlimit = "0.3.0" @@ -41,7 +41,7 @@ tracing-appender = "0.2.3" tracing-subscriber = "0.3.18" [target."cfg(unix)".dependencies] -libc = "0.2.154" +libc = "0.2.155" signal-hook-tokio = { version = "0.3.1", features = [ "futures-v0_3" ] } [target.'cfg(all(not(target_os = "macos"), not(target_os = "windows")))'.dependencies] diff --git a/yazi-plugin/Cargo.toml b/yazi-plugin/Cargo.toml index e1808d2f..dba5f3d5 100644 --- a/yazi-plugin/Cargo.toml +++ b/yazi-plugin/Cargo.toml @@ -22,7 +22,7 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies ansi-to-tui = "3.1.0" -anyhow = "1.0.83" +anyhow = "1.0.86" base64 = "0.22.1" crossterm = "0.27.0" futures = "0.3.30" diff --git a/yazi-plugin/preset/plugins/zoxide.lua b/yazi-plugin/preset/plugins/zoxide.lua index 2a57d87b..208a5285 100644 --- a/yazi-plugin/preset/plugins/zoxide.lua +++ b/yazi-plugin/preset/plugins/zoxide.lua @@ -50,10 +50,12 @@ end local function entry() local st = state() - if st.empty == true then - return fail("No directory history in the database, check out the `zoxide` docs to set it up.") - elseif st.empty == nil and head(st.cwd) < 2 then - set_state(true) + if st.empty == nil then + st.empty = head(st.cwd) < 2 + set_state(st.empty) + end + + if st.empty then return fail("No directory history in the database, check out the `zoxide` docs to set it up.") end diff --git a/yazi-proxy/Cargo.toml b/yazi-proxy/Cargo.toml index 374a663f..041828a4 100644 --- a/yazi-proxy/Cargo.toml +++ b/yazi-proxy/Cargo.toml @@ -17,6 +17,6 @@ yazi-config = { path = "../yazi-config", version = "0.2.5" } yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies -anyhow = "1.0.83" +anyhow = "1.0.86" mlua = { version = "0.9.8", features = [ "lua54" ] } tokio = { version = "1.37.0", features = [ "full" ] } diff --git a/yazi-scheduler/Cargo.toml b/yazi-scheduler/Cargo.toml index ca1a1122..fa793313 100644 --- a/yazi-scheduler/Cargo.toml +++ b/yazi-scheduler/Cargo.toml @@ -16,7 +16,7 @@ yazi-proxy = { path = "../yazi-proxy", version = "0.2.5" } yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies -anyhow = "1.0.83" +anyhow = "1.0.86" async-priority-channel = "0.2.0" futures = "0.3.30" parking_lot = "0.12.2" @@ -27,7 +27,7 @@ tokio = { version = "1.37.0", features = [ "full" ] } tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] } [target."cfg(unix)".dependencies] -libc = "0.2.154" +libc = "0.2.155" [target.'cfg(not(target_os = "android"))'.dependencies] trash = "4.1.1" diff --git a/yazi-scheduler/src/preload/op.rs b/yazi-scheduler/src/preload/op.rs index 6e4b4d01..baacbba8 100644 --- a/yazi-scheduler/src/preload/op.rs +++ b/yazi-scheduler/src/preload/op.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use yazi_config::plugin::PluginProps; +use yazi_config::plugin::PreloaderProps; use yazi_shared::{fs::Url, Throttle}; #[derive(Debug)] @@ -21,7 +21,7 @@ impl PreloadOp { #[derive(Clone, Debug)] pub struct PreloadOpRule { pub id: usize, - pub plugin: PluginProps, + pub plugin: PreloaderProps, pub targets: Vec, } diff --git a/yazi-scheduler/src/scheduler.rs b/yazi-scheduler/src/scheduler.rs index f51186b6..e238d297 100644 --- a/yazi-scheduler/src/scheduler.rs +++ b/yazi-scheduler/src/scheduler.rs @@ -4,7 +4,7 @@ use anyhow::Result; use futures::{future::BoxFuture, FutureExt}; use parking_lot::Mutex; use tokio::{fs, select, sync::{mpsc::{self, UnboundedReceiver}, oneshot}, task::JoinHandle}; -use yazi_config::{open::Opener, plugin::PluginRule, TASKS}; +use yazi_config::{open::Opener, plugin::Preloader, TASKS}; use yazi_dds::Pump; use yazi_shared::{event::Data, fs::{unique_path, Url}, Throttle}; @@ -218,13 +218,13 @@ impl Scheduler { self.plugin.macro_(PluginOpEntry { id, name, args }).ok(); } - pub fn preload_paged(&self, rule: &PluginRule, targets: Vec<&yazi_shared::fs::File>) { + pub fn preload_paged(&self, preloader: &Preloader, targets: Vec<&yazi_shared::fs::File>) { let id = self.ongoing.lock().add( TaskKind::Preload, - format!("Run preloader `{}` with {} target(s)", rule.run.name, targets.len()), + format!("Run preloader `{}` with {} target(s)", preloader.run.name, targets.len()), ); - let plugin = rule.into(); + let plugin = preloader.into(); let targets = targets.into_iter().cloned().collect(); let preload = self.preload.clone(); _ = self.micro.try_send( diff --git a/yazi-shared/Cargo.toml b/yazi-shared/Cargo.toml index d177a061..e8029ddf 100644 --- a/yazi-shared/Cargo.toml +++ b/yazi-shared/Cargo.toml @@ -1,15 +1,16 @@ [package] -name = "yazi-shared" -version = "0.2.5" -edition = "2021" -license = "MIT" -authors = [ "sxyazi " ] -description = "Yazi shared library" -homepage = "https://yazi-rs.github.io" -repository = "https://github.com/sxyazi/yazi" +name = "yazi-shared" +version = "0.2.5" +edition = "2021" +license = "MIT" +authors = [ "sxyazi " ] +description = "Yazi shared library" +homepage = "https://yazi-rs.github.io" +repository = "https://github.com/sxyazi/yazi" +rust-version = "1.78.0" [dependencies] -anyhow = "1.0.83" +anyhow = "1.0.86" bitflags = "2.5.0" crossterm = "0.27.0" dirs = "5.0.1" @@ -20,10 +21,11 @@ percent-encoding = "2.3.1" ratatui = "=0.26.1" regex = "1.10.4" serde = { version = "1.0.202", features = [ "derive" ] } +shell-words = "1.1.0" tokio = { version = "1.37.0", features = [ "full" ] } # Logging tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] } [target."cfg(unix)".dependencies] -libc = "0.2.154" +libc = "0.2.155" diff --git a/yazi-shared/src/event/cmd.rs b/yazi-shared/src/event/cmd.rs index 82685827..f9708e10 100644 --- a/yazi-shared/src/event/cmd.rs +++ b/yazi-shared/src/event/cmd.rs @@ -1,4 +1,7 @@ -use std::{any::Any, collections::HashMap, fmt::{self, Display}}; +use std::{any::Any, collections::HashMap, fmt::{self, Display}, mem, str::FromStr}; + +use anyhow::bail; +use serde::{de, Deserialize}; use super::Data; @@ -112,3 +115,46 @@ impl Display for Cmd { Ok(()) } } + +impl FromStr for Cmd { + type Err = anyhow::Error; + + #[allow(clippy::explicit_counter_loop)] + fn from_str(s: &str) -> Result { + let mut args = shell_words::split(s)?; + if args.is_empty() || args[0].is_empty() { + bail!("command name cannot be empty"); + } + + let mut cmd = Cmd { name: mem::take(&mut args[0]), ..Default::default() }; + let mut i = 0usize; + for arg in args.into_iter().skip(1) { + let Some(arg) = arg.strip_prefix("--") else { + cmd.args.insert(i.to_string(), Data::String(arg)); + i += 1; + continue; + }; + + let mut parts = arg.splitn(2, '='); + let Some(key) = parts.next().map(|s| s.to_owned()) else { + bail!("invalid argument: {arg}"); + }; + + if let Some(val) = parts.next() { + cmd.args.insert(key, Data::String(val.to_owned())); + } else { + cmd.args.insert(key, Data::Boolean(true)); + } + } + Ok(cmd) + } +} + +impl<'de> Deserialize<'de> for Cmd { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + <_>::from_str(&String::deserialize(deserializer)?).map_err(de::Error::custom) + } +} diff --git a/yazi-shared/src/fs/cha.rs b/yazi-shared/src/fs/cha.rs index a1b116ba..0ee52427 100644 --- a/yazi-shared/src/fs/cha.rs +++ b/yazi-shared/src/fs/cha.rs @@ -61,8 +61,7 @@ impl From for Cha { kind: ck, len: m.len(), accessed: m.accessed().ok(), - // TODO: remove this once https://github.com/rust-lang/rust/issues/108277 is fixed. - created: None, + created: m.created().ok(), modified: m.modified().ok(), #[cfg(unix)]