mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
117 lines
3.1 KiB
Rust
117 lines
3.1 KiB
Rust
use std::{path::Path, str::FromStr};
|
|
|
|
use serde::Deserialize;
|
|
use yazi_shared::MIME_DIR;
|
|
|
|
use super::{Fetcher, Preloader, Previewer};
|
|
use crate::{plugin::MAX_PREWORKERS, Preset};
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct Plugin {
|
|
pub fetchers: Vec<Fetcher>,
|
|
pub preloaders: Vec<Preloader>,
|
|
pub previewers: Vec<Previewer>,
|
|
}
|
|
|
|
impl Plugin {
|
|
pub fn fetchers<'a>(
|
|
&'a self,
|
|
path: &'a Path,
|
|
mime: Option<&'a str>,
|
|
factor: impl Fn(&str) -> bool + Copy,
|
|
) -> impl Iterator<Item = &'a Fetcher> {
|
|
let is_dir = mime == Some(MIME_DIR);
|
|
self.fetchers.iter().filter(move |&f| {
|
|
f.if_.as_ref().and_then(|c| c.eval(factor)) != Some(false)
|
|
&& (f.mime.as_ref().zip(mime).map_or(false, |(p, m)| p.match_mime(m))
|
|
|| f.name.as_ref().is_some_and(|p| p.match_path(path, is_dir)))
|
|
})
|
|
}
|
|
|
|
pub fn preloaders(&self, path: &Path, mime: Option<&str>) -> Vec<&Preloader> {
|
|
let is_dir = mime == Some(MIME_DIR);
|
|
let mut preloaders = Vec::with_capacity(1);
|
|
|
|
for p in &self.preloaders {
|
|
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<&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))
|
|
})
|
|
}
|
|
}
|
|
impl FromStr for Plugin {
|
|
type Err = toml::de::Error;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
#[derive(Deserialize)]
|
|
struct Outer {
|
|
plugin: Shadow,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct Shadow {
|
|
fetchers: Vec<Fetcher>,
|
|
#[serde(default)]
|
|
prepend_fetchers: Vec<Fetcher>,
|
|
#[serde(default)]
|
|
append_fetchers: Vec<Fetcher>,
|
|
|
|
preloaders: Vec<Preloader>,
|
|
#[serde(default)]
|
|
prepend_preloaders: Vec<Preloader>,
|
|
#[serde(default)]
|
|
append_preloaders: Vec<Preloader>,
|
|
|
|
previewers: Vec<Previewer>,
|
|
#[serde(default)]
|
|
prepend_previewers: Vec<Previewer>,
|
|
#[serde(default)]
|
|
append_previewers: Vec<Previewer>,
|
|
}
|
|
|
|
let mut shadow = toml::from_str::<Outer>(s)?.plugin;
|
|
if shadow.append_previewers.iter().any(|r| r.any_file()) {
|
|
shadow.previewers.retain(|r| !r.any_file());
|
|
}
|
|
if shadow.append_previewers.iter().any(|r| r.any_dir()) {
|
|
shadow.previewers.retain(|r| !r.any_dir());
|
|
}
|
|
|
|
Preset::mix(&mut shadow.fetchers, shadow.prepend_fetchers, shadow.append_fetchers);
|
|
Preset::mix(&mut shadow.preloaders, shadow.prepend_preloaders, shadow.append_preloaders);
|
|
Preset::mix(&mut shadow.previewers, shadow.prepend_previewers, shadow.append_previewers);
|
|
|
|
if shadow.fetchers.len() + shadow.preloaders.len() > MAX_PREWORKERS as usize {
|
|
panic!("Fetchers and preloaders exceed the limit of {MAX_PREWORKERS}");
|
|
}
|
|
|
|
for (i, p) in shadow.fetchers.iter_mut().enumerate() {
|
|
p.idx = i as u8;
|
|
}
|
|
for (i, p) in shadow.preloaders.iter_mut().enumerate() {
|
|
p.idx = shadow.fetchers.len() as u8 + i as u8;
|
|
}
|
|
|
|
Ok(Self {
|
|
fetchers: shadow.fetchers,
|
|
preloaders: shadow.preloaders,
|
|
previewers: shadow.previewers,
|
|
})
|
|
}
|
|
}
|