diff --git a/yazi-core/src/manager/commands/open.rs b/yazi-core/src/manager/commands/open.rs index 76ed3205..b0af78bf 100644 --- a/yazi-core/src/manager/commands/open.rs +++ b/yazi-core/src/manager/commands/open.rs @@ -41,7 +41,7 @@ impl Manager { let (mut done, mut todo) = (Vec::with_capacity(selected.len()), vec![]); for u in selected { - if self.mimetype.contains_key(u) { + if self.mimetype.contains(u) { done.push((u.clone(), String::new())); } else if self.guess_folder(u) { done.push((u.clone(), MIME_DIR.to_owned())); @@ -78,7 +78,7 @@ impl Manager { .targets .into_iter() .filter_map(|(u, m)| { - Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.get(&u).cloned()).map(|m| (u, m)) + Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.get_owned(&u)).map(|m| (u, m)) }) .collect(); diff --git a/yazi-core/src/manager/commands/peek.rs b/yazi-core/src/manager/commands/peek.rs index af10b820..0721ff72 100644 --- a/yazi-core/src/manager/commands/peek.rs +++ b/yazi-core/src/manager/commands/peek.rs @@ -55,7 +55,7 @@ impl Manager { return; } - let mime = self.mimetype.get(hovered.url()).cloned().unwrap_or_default(); + let mime = self.mimetype.get_owned(hovered.url()).unwrap_or_default(); if !mime.is_empty() { // Wait till mimetype is resolved to avoid flickering self.active_mut().preview.go(hovered, &mime, opt.force); diff --git a/yazi-core/src/manager/manager.rs b/yazi-core/src/manager/manager.rs index d7c9f98e..246d51bf 100644 --- a/yazi-core/src/manager/manager.rs +++ b/yazi-core/src/manager/manager.rs @@ -1,12 +1,10 @@ -use std::collections::HashMap; - use ratatui::layout::Rect; use yazi_adapter::Dimension; use yazi_config::popup::{Origin, Position}; use yazi_fs::Folder; use yazi_shared::fs::{File, Url}; -use super::{Tabs, Watcher, Yanked}; +use super::{Mimetype, Tabs, Watcher, Yanked}; use crate::tab::Tab; pub struct Manager { @@ -14,7 +12,7 @@ pub struct Manager { pub yanked: Yanked, pub(super) watcher: Watcher, - pub mimetype: HashMap, + pub mimetype: Mimetype, } impl Manager { diff --git a/yazi-core/src/manager/mimetype.rs b/yazi-core/src/manager/mimetype.rs new file mode 100644 index 00000000..63e44a2e --- /dev/null +++ b/yazi-core/src/manager/mimetype.rs @@ -0,0 +1,46 @@ +use std::{collections::HashMap, path::PathBuf}; + +use yazi_shared::fs::{Url, UrlScheme}; + +#[derive(Default)] +pub struct Mimetype(HashMap); + +impl Mimetype { + #[inline] + pub fn get(&self, url: &Url) -> Option<&str> { + let s = match url.scheme() { + UrlScheme::Regular => self.0.get(url.as_path()), + UrlScheme::Search => None, + UrlScheme::SearchItem => self.0.get(url.as_path()), + UrlScheme::Archive => None, + }; + s.map(|s| s.as_str()) + } + + #[inline] + pub fn get_owned(&self, url: &Url) -> Option { self.get(url).map(|s| s.to_owned()) } + + #[inline] + pub fn contains(&self, url: &Url) -> bool { + match url.scheme() { + UrlScheme::Regular => self.0.contains_key(url.as_path()), + UrlScheme::Search => false, + UrlScheme::SearchItem => self.0.contains_key(url.as_path()), + UrlScheme::Archive => false, + } + } + + pub fn extend(&mut self, iter: impl IntoIterator) { + self.0.extend(iter.into_iter().filter_map(|(u, s)| { + Some(( + match u.scheme() { + UrlScheme::Regular => u.into_path(), + UrlScheme::Search => None?, + UrlScheme::SearchItem => u.into_path(), + UrlScheme::Archive => None?, + }, + s, + )) + })) + } +} diff --git a/yazi-core/src/manager/mod.rs b/yazi-core/src/manager/mod.rs index 46c3d35d..d1b3eef3 100644 --- a/yazi-core/src/manager/mod.rs +++ b/yazi-core/src/manager/mod.rs @@ -1,12 +1,14 @@ mod commands; mod linked; mod manager; +mod mimetype; mod tabs; mod watcher; mod yanked; pub use linked::*; pub use manager::*; +pub use mimetype::*; pub use tabs::*; pub use watcher::*; pub use yanked::*; diff --git a/yazi-core/src/tasks/preload.rs b/yazi-core/src/tasks/preload.rs index bbee1eb0..cf86d063 100644 --- a/yazi-core/src/tasks/preload.rs +++ b/yazi-core/src/tasks/preload.rs @@ -1,18 +1,16 @@ -use std::collections::HashMap; - use yazi_config::{manager::SortBy, plugin::MAX_PREWORKERS, PLUGIN}; use yazi_fs::Files; -use yazi_shared::{fs::{File, Url}, MIME_DIR}; +use yazi_shared::{fs::File, MIME_DIR}; use super::Tasks; +use crate::manager::Mimetype; impl Tasks { - pub fn fetch_paged(&self, paged: &[File], mimetype: &HashMap) { + pub fn fetch_paged(&self, paged: &[File], mimetype: &Mimetype) { let mut loaded = self.scheduler.prework.loaded.lock(); let mut tasks: [Vec<_>; MAX_PREWORKERS as usize] = Default::default(); for f in paged { - let mime = - if f.is_dir() { MIME_DIR } else { mimetype.get(f.url()).map(|s| &**s).unwrap_or_default() }; + let mime = if f.is_dir() { MIME_DIR } else { mimetype.get(f.url()).unwrap_or_default() }; let factors = |s: &str| match s { "mime" => !mime.is_empty(), _ => false, @@ -36,11 +34,10 @@ impl Tasks { } } - pub fn preload_paged(&self, paged: &[File], mimetype: &HashMap) { + pub fn preload_paged(&self, paged: &[File], mimetype: &Mimetype) { let mut loaded = self.scheduler.prework.loaded.lock(); for f in paged { - let mime = - if f.is_dir() { MIME_DIR } else { mimetype.get(f.url()).map(|s| &**s).unwrap_or_default() }; + let mime = if f.is_dir() { MIME_DIR } else { mimetype.get(f.url()).unwrap_or_default() }; for p in PLUGIN.preloaders(f.url(), mime) { match loaded.get_mut(f.url()) { Some(n) if *n & (1 << p.idx) != 0 => continue, @@ -52,7 +49,7 @@ impl Tasks { } } - pub fn prework_affected(&self, affected: &[File], mimetype: &HashMap) { + pub fn prework_affected(&self, affected: &[File], mimetype: &Mimetype) { let mask = PLUGIN.fetchers_mask(); { let mut loaded = self.scheduler.prework.loaded.lock(); diff --git a/yazi-fm/src/lives/file.rs b/yazi-fm/src/lives/file.rs index c8fafa4f..852812f8 100644 --- a/yazi-fm/src/lives/file.rs +++ b/yazi-fm/src/lives/file.rs @@ -43,7 +43,7 @@ impl File { }); reg.add_method("mime", |lua, me, ()| { let cx = lua.named_registry_value::("cx")?; - Ok(cx.manager.mimetype.get(me.url()).cloned()) + Ok(cx.manager.mimetype.get_owned(me.url())) }); reg.add_method("prefix", |lua, me, ()| { if !me.folder().loc.is_search() { @@ -59,7 +59,7 @@ impl File { let mime = if me.is_dir() { MIME_DIR } else { - cx.manager.mimetype.get(me.url()).map(|x| &**x).unwrap_or_default() + cx.manager.mimetype.get(me.url()).unwrap_or_default() }; Ok(THEME.filetypes.iter().find(|&x| x.matches(me, mime)).map(|x| Style::from(x.style))) diff --git a/yazi-shared/src/fs/url.rs b/yazi-shared/src/fs/url.rs index 16574c21..7d1fc90a 100644 --- a/yazi-shared/src/fs/url.rs +++ b/yazi-shared/src/fs/url.rs @@ -17,6 +17,7 @@ pub enum UrlScheme { #[default] Regular, Search, + SearchItem, Archive, } @@ -98,12 +99,12 @@ impl AsRef for Url { impl Display for Url { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - if self.scheme == UrlScheme::Regular { + if matches!(self.scheme, UrlScheme::Regular | UrlScheme::SearchItem) { return f.write_str(&self.path.to_string_lossy()); } let scheme = match self.scheme { - UrlScheme::Regular => unreachable!(), + UrlScheme::Regular | UrlScheme::SearchItem => unreachable!(), UrlScheme::Search => "search://", UrlScheme::Archive => "archive://", }; @@ -128,7 +129,8 @@ impl Url { let url = Self::from(self.path.join(path)); match self.scheme { UrlScheme::Regular => url, - UrlScheme::Search => url.into_search(), + UrlScheme::Search => url.into_search_item(), + UrlScheme::SearchItem => url, UrlScheme::Archive => url.into_archive(), } } @@ -140,6 +142,7 @@ impl Url { match self.scheme { UrlScheme::Regular => url, UrlScheme::Search => url, + UrlScheme::SearchItem => url, UrlScheme::Archive => url, } }) @@ -187,8 +190,8 @@ impl Url { } #[inline] - pub fn into_search(mut self) -> Self { - self.scheme = UrlScheme::Search; + pub fn into_search_item(mut self) -> Self { + self.scheme = UrlScheme::SearchItem; self.frag = String::new(); self } @@ -208,10 +211,17 @@ impl Url { self } + // --- Scheme + #[inline] + pub fn scheme(&self) -> UrlScheme { self.scheme } + // --- Path #[inline] pub fn set_path(&mut self, path: PathBuf) { self.path = path; } + #[inline] + pub fn into_path(self) -> PathBuf { self.path } + // --- Frag #[inline] pub fn frag(&self) -> &str { &self.frag }