mirror of
https://github.com/sxyazi/yazi.git
synced 2024-09-11 10:26:35 +03:00
feat: add a next
property to the preloader rules to allow running multiple preloaders (#1058)
This commit is contained in:
parent
0ff4835f8d
commit
c2affae3a9
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -120,9 +120,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.83"
|
version = "1.0.86"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"
|
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arc-swap"
|
name = "arc-swap"
|
||||||
@ -1086,9 +1086,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.154"
|
version = "0.2.155"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
@ -2924,6 +2924,7 @@ dependencies = [
|
|||||||
"ratatui",
|
"ratatui",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
|
"shell-words",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
12
flake.lock
12
flake.lock
@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1713805509,
|
"lastModified": 1716097317,
|
||||||
"narHash": "sha256-YgSEan4CcrjivCNO5ZNzhg7/8ViLkZ4CB/GrGBVSudo=",
|
"narHash": "sha256-1UMrLtgzielG/Sop6gl6oTSM4pDt7rF9j9VuxhDWDlY=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "1e1dc66fe68972a76679644a5577828b6a7e8be4",
|
"rev": "8535fb92661f37ff9f0da3007fbc942f7d134b41",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -51,11 +51,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1713924823,
|
"lastModified": 1716085073,
|
||||||
"narHash": "sha256-kOeyS3GFwgnKvzuBMmFqEAX0xwZ7Nj4/5tXuvpZ0d4U=",
|
"narHash": "sha256-3+9gI93XxszWA2+9S2xZfws1QArPX/MC6nahOGpcMB4=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "8a2edac3ae926a2a6ce60f4595dcc4540fc8cad4",
|
"rev": "cfc8776011bd83508324115d353222475e1601c0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -13,7 +13,7 @@ yazi-config = { path = "../yazi-config", version = "0.2.5" }
|
|||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
arc-swap = "1.7.1"
|
arc-swap = "1.7.1"
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
color_quant = "1.1.0"
|
color_quant = "1.1.0"
|
||||||
|
@ -13,7 +13,7 @@ yazi-dds = { path = "../yazi-dds", version = "0.2.5" }
|
|||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
clap = { version = "4.5.4", features = [ "derive" ] }
|
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
md-5 = "0.10.6"
|
md-5 = "0.10.6"
|
||||||
@ -22,7 +22,7 @@ tokio = { version = "1.37.0", features = [ "full" ] }
|
|||||||
toml_edit = "0.22.13"
|
toml_edit = "0.22.13"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
clap = { version = "4.5.4", features = [ "derive" ] }
|
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||||
clap_complete = "4.5.2"
|
clap_complete = "4.5.2"
|
||||||
clap_complete_fig = "4.5.0"
|
clap_complete_fig = "4.5.0"
|
||||||
|
@ -12,7 +12,7 @@ repository = "https://github.com/sxyazi/yazi"
|
|||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
arc-swap = "1.7.1"
|
arc-swap = "1.7.1"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
globset = "0.4.14"
|
globset = "0.4.14"
|
||||||
|
@ -80,7 +80,7 @@ suppress_preload = false
|
|||||||
[plugin]
|
[plugin]
|
||||||
|
|
||||||
preloaders = [
|
preloaders = [
|
||||||
{ name = "*", cond = "!mime", run = "mime", multi = true, prio = "high" },
|
{ name = "*", cond = "!mime", run = "mime", next = true, multi = true, prio = "high" },
|
||||||
# Image
|
# Image
|
||||||
{ mime = "image/svg+xml", run = "magick" },
|
{ mime = "image/svg+xml", run = "magick" },
|
||||||
{ mime = "image/heic", run = "magick" },
|
{ mime = "image/heic", run = "magick" },
|
||||||
|
@ -23,10 +23,10 @@ impl Open {
|
|||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
M: AsRef<str>,
|
M: AsRef<str>,
|
||||||
{
|
{
|
||||||
let is_folder = mime.as_ref() == MIME_DIR;
|
let is_dir = mime.as_ref() == MIME_DIR;
|
||||||
self.rules.iter().find_map(|rule| {
|
self.rules.iter().find_map(|rule| {
|
||||||
if rule.mime.as_ref().is_some_and(|p| p.match_mime(&mime))
|
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
|
let openers = rule
|
||||||
.use_
|
.use_
|
||||||
|
@ -7,8 +7,8 @@ use serde::Deserialize;
|
|||||||
#[serde(try_from = "String")]
|
#[serde(try_from = "String")]
|
||||||
pub struct Pattern {
|
pub struct Pattern {
|
||||||
inner: globset::GlobMatcher,
|
inner: globset::GlobMatcher,
|
||||||
|
is_dir: bool,
|
||||||
is_star: bool,
|
is_star: bool,
|
||||||
is_folder: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pattern {
|
impl Pattern {
|
||||||
@ -16,15 +16,15 @@ impl Pattern {
|
|||||||
pub fn match_mime(&self, str: impl AsRef<str>) -> bool { self.inner.is_match(str.as_ref()) }
|
pub fn match_mime(&self, str: impl AsRef<str>) -> bool { self.inner.is_match(str.as_ref()) }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn match_path(&self, path: impl AsRef<Path>, is_folder: bool) -> bool {
|
pub fn match_path(&self, path: impl AsRef<Path>, is_dir: bool) -> bool {
|
||||||
is_folder == self.is_folder && (self.is_star || self.inner.is_match(path))
|
is_dir == self.is_dir && (self.is_star || self.inner.is_match(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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]
|
#[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 {
|
impl TryFrom<&str> for Pattern {
|
||||||
@ -42,7 +42,7 @@ impl TryFrom<&str> for Pattern {
|
|||||||
.build()?
|
.build()?
|
||||||
.compile_matcher();
|
.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 == "*" })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
mod plugin;
|
mod plugin;
|
||||||
mod props;
|
mod preloader;
|
||||||
mod rule;
|
mod previewer;
|
||||||
mod run;
|
|
||||||
|
|
||||||
pub use plugin::*;
|
pub use plugin::*;
|
||||||
pub use props::*;
|
pub use preloader::*;
|
||||||
pub use rule::*;
|
pub use previewer::*;
|
||||||
#[allow(unused_imports)]
|
|
||||||
pub use run::*;
|
|
||||||
|
|
||||||
pub const MAX_PRELOADERS: u8 = 32;
|
pub const MAX_PRELOADERS: u8 = 32;
|
||||||
|
@ -3,13 +3,13 @@ use std::path::Path;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use yazi_shared::MIME_DIR;
|
use yazi_shared::MIME_DIR;
|
||||||
|
|
||||||
use super::PluginRule;
|
use super::{Preloader, Previewer};
|
||||||
use crate::{plugin::MAX_PRELOADERS, Preset, MERGED_YAZI};
|
use crate::{plugin::MAX_PRELOADERS, Preset, MERGED_YAZI};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Plugin {
|
pub struct Plugin {
|
||||||
pub preloaders: Vec<PluginRule>,
|
pub preloaders: Vec<Preloader>,
|
||||||
pub previewers: Vec<PluginRule>,
|
pub previewers: Vec<Previewer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Plugin {
|
impl Default for Plugin {
|
||||||
@ -21,17 +21,17 @@ impl Default for Plugin {
|
|||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Shadow {
|
struct Shadow {
|
||||||
preloaders: Vec<PluginRule>,
|
preloaders: Vec<Preloader>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
prepend_preloaders: Vec<PluginRule>,
|
prepend_preloaders: Vec<Preloader>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
append_preloaders: Vec<PluginRule>,
|
append_preloaders: Vec<Preloader>,
|
||||||
|
|
||||||
previewers: Vec<PluginRule>,
|
previewers: Vec<Previewer>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
prepend_previewers: Vec<PluginRule>,
|
prepend_previewers: Vec<Previewer>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
append_previewers: Vec<PluginRule>,
|
append_previewers: Vec<Previewer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut shadow = toml::from_str::<Outer>(&MERGED_YAZI).unwrap().plugin;
|
let mut shadow = toml::from_str::<Outer>(&MERGED_YAZI).unwrap().plugin;
|
||||||
@ -50,9 +50,6 @@ impl Default for Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i, preloader) in shadow.preloaders.iter_mut().enumerate() {
|
for (i, preloader) in shadow.preloaders.iter_mut().enumerate() {
|
||||||
if preloader.sync {
|
|
||||||
panic!("Preloaders cannot be synchronous");
|
|
||||||
}
|
|
||||||
preloader.id = i as u8;
|
preloader.id = i as u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,24 +63,34 @@ impl Plugin {
|
|||||||
path: &Path,
|
path: &Path,
|
||||||
mime: Option<&str>,
|
mime: Option<&str>,
|
||||||
f: impl Fn(&str) -> bool + Copy,
|
f: impl Fn(&str) -> bool + Copy,
|
||||||
) -> Vec<&PluginRule> {
|
) -> Vec<&Preloader> {
|
||||||
let is_folder = mime == Some(MIME_DIR);
|
let is_dir = mime == Some(MIME_DIR);
|
||||||
self
|
let mut preloaders = Vec::with_capacity(1);
|
||||||
.preloaders
|
|
||||||
.iter()
|
for p in &self.preloaders {
|
||||||
.filter(|&rule| {
|
if p.cond.as_ref().and_then(|c| c.eval(f)) == Some(false) {
|
||||||
rule.cond.as_ref().and_then(|c| c.eval(f)) != Some(false)
|
continue;
|
||||||
&& (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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn previewer(&self, path: &Path, mime: &str) -> Option<&PluginRule> {
|
if !p.mime.as_ref().zip(mime).map_or(false, |(p, m)| p.match_mime(m))
|
||||||
let is_folder = mime == MIME_DIR;
|
&& !p.name.as_ref().is_some_and(|p| p.match_path(path, is_dir))
|
||||||
self.previewers.iter().find(|&rule| {
|
{
|
||||||
rule.mime.as_ref().is_some_and(|p| p.match_mime(mime))
|
continue;
|
||||||
|| rule.name.as_ref().is_some_and(|p| p.match_path(path, is_folder))
|
}
|
||||||
|
|
||||||
|
preloaders.push(p);
|
||||||
|
if !p.next {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preloaders
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
yazi-config/src/plugin/preloader.rs
Normal file
39
yazi-config/src/plugin/preloader.rs
Normal file
@ -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<Condition>,
|
||||||
|
pub name: Option<Pattern>,
|
||||||
|
pub mime: Option<Pattern>,
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
yazi-config/src/plugin/previewer.rs
Normal file
21
yazi-config/src/plugin/previewer.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
use yazi_shared::event::Cmd;
|
||||||
|
|
||||||
|
use crate::Pattern;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Previewer {
|
||||||
|
pub name: Option<Pattern>,
|
||||||
|
pub mime: Option<Pattern>,
|
||||||
|
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()) }
|
||||||
|
}
|
@ -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 }
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<Condition>,
|
|
||||||
pub name: Option<Pattern>,
|
|
||||||
pub mime: Option<Pattern>,
|
|
||||||
#[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()) }
|
|
||||||
}
|
|
@ -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<Cmd, D::Error>
|
|
||||||
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<A>(self, _: A) -> Result<Self::Value, A::Error>
|
|
||||||
where
|
|
||||||
A: de::SeqAccess<'de>,
|
|
||||||
{
|
|
||||||
Err(de::Error::custom("`run` within [plugin] must be a string"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
|
||||||
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)
|
|
||||||
}
|
|
@ -19,7 +19,7 @@ yazi-scheduler = { path = "../yazi-scheduler", version = "0.2.5" }
|
|||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
bitflags = "2.5.0"
|
bitflags = "2.5.0"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
futures = "0.3.30"
|
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" ] }
|
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
||||||
|
|
||||||
[target."cfg(unix)".dependencies]
|
[target."cfg(unix)".dependencies]
|
||||||
libc = "0.2.154"
|
libc = "0.2.155"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::{collections::HashMap, mem};
|
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 yazi_shared::{fs::{File, Url}, MIME_DIR};
|
||||||
|
|
||||||
use super::Tasks;
|
use super::Tasks;
|
||||||
@ -34,15 +34,15 @@ impl Tasks {
|
|||||||
drop(loaded);
|
drop(loaded);
|
||||||
let mut loaded = self.scheduler.preload.rule_loaded.write();
|
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 {
|
for &f in &targets {
|
||||||
if let Some(n) = loaded.get_mut(&f.url) {
|
if let Some(n) = loaded.get_mut(&f.url) {
|
||||||
*n |= 1 << rule.id;
|
*n |= 1 << preloader.id;
|
||||||
} else {
|
} 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)]
|
#[allow(clippy::needless_range_loop)]
|
||||||
|
@ -17,7 +17,7 @@ yazi-boot = { path = "../yazi-boot", version = "0.2.5" }
|
|||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
mlua = { version = "0.9.8", features = [ "lua54" ] }
|
mlua = { version = "0.9.8", features = [ "lua54" ] }
|
||||||
parking_lot = "0.12.2"
|
parking_lot = "0.12.2"
|
||||||
serde = { version = "1.0.202", features = [ "derive" ] }
|
serde = { version = "1.0.202", features = [ "derive" ] }
|
||||||
|
@ -23,7 +23,7 @@ yazi-proxy = { path = "../yazi-proxy", version = "0.2.5" }
|
|||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
better-panic = "0.3.0"
|
better-panic = "0.3.0"
|
||||||
crossterm = { version = "0.27.0", features = [ "event-stream" ] }
|
crossterm = { version = "0.27.0", features = [ "event-stream" ] }
|
||||||
fdlimit = "0.3.0"
|
fdlimit = "0.3.0"
|
||||||
@ -41,7 +41,7 @@ tracing-appender = "0.2.3"
|
|||||||
tracing-subscriber = "0.3.18"
|
tracing-subscriber = "0.3.18"
|
||||||
|
|
||||||
[target."cfg(unix)".dependencies]
|
[target."cfg(unix)".dependencies]
|
||||||
libc = "0.2.154"
|
libc = "0.2.155"
|
||||||
signal-hook-tokio = { version = "0.3.1", features = [ "futures-v0_3" ] }
|
signal-hook-tokio = { version = "0.3.1", features = [ "futures-v0_3" ] }
|
||||||
|
|
||||||
[target.'cfg(all(not(target_os = "macos"), not(target_os = "windows")))'.dependencies]
|
[target.'cfg(all(not(target_os = "macos"), not(target_os = "windows")))'.dependencies]
|
||||||
|
@ -22,7 +22,7 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
|||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
ansi-to-tui = "3.1.0"
|
ansi-to-tui = "3.1.0"
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
@ -50,10 +50,12 @@ end
|
|||||||
|
|
||||||
local function entry()
|
local function entry()
|
||||||
local st = state()
|
local st = state()
|
||||||
if st.empty == true then
|
if st.empty == nil then
|
||||||
return fail("No directory history in the database, check out the `zoxide` docs to set it up.")
|
st.empty = head(st.cwd) < 2
|
||||||
elseif st.empty == nil and head(st.cwd) < 2 then
|
set_state(st.empty)
|
||||||
set_state(true)
|
end
|
||||||
|
|
||||||
|
if st.empty then
|
||||||
return fail("No directory history in the database, check out the `zoxide` docs to set it up.")
|
return fail("No directory history in the database, check out the `zoxide` docs to set it up.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -17,6 +17,6 @@ yazi-config = { path = "../yazi-config", version = "0.2.5" }
|
|||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
mlua = { version = "0.9.8", features = [ "lua54" ] }
|
mlua = { version = "0.9.8", features = [ "lua54" ] }
|
||||||
tokio = { version = "1.37.0", features = [ "full" ] }
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
|
@ -16,7 +16,7 @@ yazi-proxy = { path = "../yazi-proxy", version = "0.2.5" }
|
|||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
async-priority-channel = "0.2.0"
|
async-priority-channel = "0.2.0"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
parking_lot = "0.12.2"
|
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" ] }
|
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
||||||
|
|
||||||
[target."cfg(unix)".dependencies]
|
[target."cfg(unix)".dependencies]
|
||||||
libc = "0.2.154"
|
libc = "0.2.155"
|
||||||
|
|
||||||
[target.'cfg(not(target_os = "android"))'.dependencies]
|
[target.'cfg(not(target_os = "android"))'.dependencies]
|
||||||
trash = "4.1.1"
|
trash = "4.1.1"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use yazi_config::plugin::PluginProps;
|
use yazi_config::plugin::PreloaderProps;
|
||||||
use yazi_shared::{fs::Url, Throttle};
|
use yazi_shared::{fs::Url, Throttle};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -21,7 +21,7 @@ impl PreloadOp {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PreloadOpRule {
|
pub struct PreloadOpRule {
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
pub plugin: PluginProps,
|
pub plugin: PreloaderProps,
|
||||||
pub targets: Vec<yazi_shared::fs::File>,
|
pub targets: Vec<yazi_shared::fs::File>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use anyhow::Result;
|
|||||||
use futures::{future::BoxFuture, FutureExt};
|
use futures::{future::BoxFuture, FutureExt};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use tokio::{fs, select, sync::{mpsc::{self, UnboundedReceiver}, oneshot}, task::JoinHandle};
|
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_dds::Pump;
|
||||||
use yazi_shared::{event::Data, fs::{unique_path, Url}, Throttle};
|
use yazi_shared::{event::Data, fs::{unique_path, Url}, Throttle};
|
||||||
|
|
||||||
@ -218,13 +218,13 @@ impl Scheduler {
|
|||||||
self.plugin.macro_(PluginOpEntry { id, name, args }).ok();
|
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(
|
let id = self.ongoing.lock().add(
|
||||||
TaskKind::Preload,
|
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 targets = targets.into_iter().cloned().collect();
|
||||||
let preload = self.preload.clone();
|
let preload = self.preload.clone();
|
||||||
_ = self.micro.try_send(
|
_ = self.micro.try_send(
|
||||||
|
@ -7,9 +7,10 @@ authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
|||||||
description = "Yazi shared library"
|
description = "Yazi shared library"
|
||||||
homepage = "https://yazi-rs.github.io"
|
homepage = "https://yazi-rs.github.io"
|
||||||
repository = "https://github.com/sxyazi/yazi"
|
repository = "https://github.com/sxyazi/yazi"
|
||||||
|
rust-version = "1.78.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.86"
|
||||||
bitflags = "2.5.0"
|
bitflags = "2.5.0"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
@ -20,10 +21,11 @@ percent-encoding = "2.3.1"
|
|||||||
ratatui = "=0.26.1"
|
ratatui = "=0.26.1"
|
||||||
regex = "1.10.4"
|
regex = "1.10.4"
|
||||||
serde = { version = "1.0.202", features = [ "derive" ] }
|
serde = { version = "1.0.202", features = [ "derive" ] }
|
||||||
|
shell-words = "1.1.0"
|
||||||
tokio = { version = "1.37.0", features = [ "full" ] }
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
||||||
|
|
||||||
[target."cfg(unix)".dependencies]
|
[target."cfg(unix)".dependencies]
|
||||||
libc = "0.2.154"
|
libc = "0.2.155"
|
||||||
|
@ -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;
|
use super::Data;
|
||||||
|
|
||||||
@ -112,3 +115,46 @@ impl Display for Cmd {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for Cmd {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
#[allow(clippy::explicit_counter_loop)]
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
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<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
<_>::from_str(&String::deserialize(deserializer)?).map_err(de::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -61,8 +61,7 @@ impl From<Metadata> for Cha {
|
|||||||
kind: ck,
|
kind: ck,
|
||||||
len: m.len(),
|
len: m.len(),
|
||||||
accessed: m.accessed().ok(),
|
accessed: m.accessed().ok(),
|
||||||
// TODO: remove this once https://github.com/rust-lang/rust/issues/108277 is fixed.
|
created: m.created().ok(),
|
||||||
created: None,
|
|
||||||
modified: m.modified().ok(),
|
modified: m.modified().ok(),
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
Loading…
Reference in New Issue
Block a user