feat: true custom mime fetcher support - using user rules even during open or in watcher (#1976)

This commit is contained in:
三咲雅 · Misaki Masa 2024-12-01 00:15:43 +08:00 committed by GitHub
parent d72f90356b
commit 4194befb88
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 44 additions and 14 deletions

1
Cargo.lock generated
View file

@ -3453,6 +3453,7 @@ dependencies = [
"regex",
"serde",
"toml",
"tracing",
"validator",
"yazi-macro",
"yazi-shared",

View file

@ -22,6 +22,7 @@ ratatui = { workspace = true }
regex = { workspace = true }
serde = { workspace = true }
toml = { version = "0.8.19", features = [ "preserve_order" ] }
tracing = { workspace = true }
validator = { version = "0.19.0", features = [ "derive" ] }
[target.'cfg(target_os = "macos")'.dependencies]

View file

@ -79,8 +79,8 @@ keymap = [
{ on = ";", run = "shell --interactive", desc = "Run a shell command" },
{ on = ":", run = "shell --block --interactive", desc = "Run a shell command (block until finishes)" },
{ on = ".", run = "hidden toggle", desc = "Toggle the visibility of hidden files" },
{ on = "s", run = "search fd", desc = "Search files by name via fd" },
{ on = "S", run = "search rg", desc = "Search files by content via ripgrep" },
{ on = "s", run = "search --via=fd", desc = "Search files by name via fd" },
{ on = "S", run = "search --via=rg", desc = "Search files by content via ripgrep" },
{ on = "<C-s>", run = "escape --search", desc = "Cancel the ongoing search" },
{ on = "z", run = "plugin zoxide", desc = "Jump to a directory via zoxide" },
{ on = "Z", run = "plugin fzf", desc = "Jump to a file/directory via fzf" },

View file

@ -2,6 +2,8 @@ use std::{collections::HashSet, path::Path, str::FromStr};
use anyhow::Context;
use serde::{Deserialize, Deserializer};
use tracing::warn;
use yazi_shared::fs::File;
use super::{Fetcher, Preloader, Previewer, Spotter};
use crate::{Preset, plugin::MAX_PREWORKERS};
@ -30,6 +32,27 @@ impl Plugin {
})
}
pub fn mime_fetchers(&self, files: Vec<File>) -> impl Iterator<Item = (&Fetcher, Vec<File>)> {
let mut tasks: [Vec<_>; MAX_PREWORKERS as usize] = Default::default();
for f in files {
let factors = |s: &str| match s {
"dummy" => f.cha.is_dummy(),
_ => false,
};
let found = self.fetchers.iter().find(|&g| g.id == "mime" && g.matches(&f.url, "", factors));
if let Some(g) = found {
tasks[g.idx as usize].push(f);
} else {
warn!("No mime fetcher for {f:?}");
}
}
tasks.into_iter().enumerate().filter_map(|(i, tasks)| {
if tasks.is_empty() { None } else { Some((&self.fetchers[i], tasks)) }
})
}
#[inline]
pub fn fetchers_mask(&self) -> u32 {
self.fetchers.iter().fold(0, |n, f| if f.mime.is_some() { n } else { n | 1 << f.idx as u32 })

View file

@ -2,12 +2,12 @@ use std::{borrow::Cow, ffi::OsString};
use tracing::error;
use yazi_boot::ARGS;
use yazi_config::{OPEN, popup::PickCfg};
use yazi_config::{OPEN, PLUGIN, popup::PickCfg};
use yazi_fs::Folder;
use yazi_macro::emit;
use yazi_plugin::isolate;
use yazi_proxy::{ManagerProxy, TasksProxy, options::OpenDoOpt};
use yazi_shared::{MIME_DIR, event::{Cmd, CmdCow, EventQuit}, fs::{File, Url}};
use yazi_shared::{MIME_DIR, event::{CmdCow, EventQuit}, fs::{File, Url}};
use crate::{manager::Manager, tasks::Tasks};
@ -65,8 +65,10 @@ impl Manager {
}
done.extend(files.iter().map(|f| (f.url_owned(), String::new())));
if let Err(e) = isolate::fetch(Cmd::new("mime").into(), files).await {
error!("Fetch `mime` failed in opening: {e}");
for (fetcher, files) in PLUGIN.mime_fetchers(files) {
if let Err(e) = isolate::fetch(CmdCow::from(&fetcher.run), files).await {
error!("Fetch mime failed on opening: {e}");
}
}
ManagerProxy::open_do(OpenDoOpt { hovered, targets: done, interactive: opt.interactive });

View file

@ -6,10 +6,11 @@ use parking_lot::RwLock;
use tokio::{fs, pin, sync::{mpsc::{self, UnboundedReceiver}, watch}};
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
use tracing::error;
use yazi_config::PLUGIN;
use yazi_fs::{Files, Folder};
use yazi_plugin::isolate;
use yazi_proxy::WATCHER;
use yazi_shared::{RoCell, event::Cmd, fs::{Cha, File, FilesOp, Url, realname_unchecked}};
use yazi_shared::{RoCell, event::CmdCow, fs::{Cha, File, FilesOp, Url, realname_unchecked}};
use super::Linked;
@ -151,8 +152,10 @@ impl Watcher {
}
FilesOp::mutate(ops);
if let Err(e) = isolate::fetch(Cmd::new("mime").into(), reload).await {
error!("Fetch `mime` failed in watcher: {e}");
for (fetcher, files) in PLUGIN.mime_fetchers(reload) {
if let Err(e) = isolate::fetch(CmdCow::from(&fetcher.run), files).await {
error!("Fetch mime failed in watcher: {e}");
}
}
}
}

View file

@ -17,13 +17,13 @@ impl Tasks {
_ => false,
};
for p in PLUGIN.fetchers(&f.url, mime, factors) {
for g in PLUGIN.fetchers(&f.url, mime, factors) {
match loaded.get_mut(&f.url) {
Some(n) if *n & (1 << p.idx) != 0 => continue,
Some(n) => *n |= 1 << p.idx,
None => _ = loaded.insert(f.url_owned(), 1 << p.idx),
Some(n) if *n & (1 << g.idx) != 0 => continue,
Some(n) => *n |= 1 << g.idx,
None => _ = loaded.insert(f.url_owned(), 1 << g.idx),
}
tasks[p.idx as usize].push(f.clone());
tasks[g.idx as usize].push(f.clone());
}
}