diff --git a/Cargo.lock b/Cargo.lock index ac14342e..f8e9e705 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3415,6 +3415,7 @@ dependencies = [ "futures", "indexmap", "libc", + "lru 0.13.0", "notify", "parking_lot", "ratatui", diff --git a/yazi-boot/src/actions/debug.rs b/yazi-boot/src/actions/debug.rs index 9acc7696..65662417 100644 --- a/yazi-boot/src/actions/debug.rs +++ b/yazi-boot/src/actions/debug.rs @@ -100,6 +100,11 @@ impl Actions { writeln!(s, " xclip : {}", Self::process_output("xclip", "-version"))?; writeln!(s, " xsel : {}", Self::process_output("xsel", "--version"))?; + writeln!( + s, + "\n\nSee https://yazi-rs.github.io/docs/plugins/overview#debugging on how to enable logging or debug runtime errors." + )?; + Ok(s) } diff --git a/yazi-core/Cargo.toml b/yazi-core/Cargo.toml index 76cd4e73..4dd6a20e 100644 --- a/yazi-core/Cargo.toml +++ b/yazi-core/Cargo.toml @@ -28,6 +28,7 @@ crossterm = { workspace = true } dirs = { workspace = true } futures = { workspace = true } indexmap = { workspace = true } +lru = { workspace = true } notify = { version = "8.0.0", default-features = false, features = [ "macos_fsevent" ] } parking_lot = { workspace = true } ratatui = { workspace = true } diff --git a/yazi-core/src/manager/commands/open.rs b/yazi-core/src/manager/commands/open.rs index aa6ad355..eabecb75 100644 --- a/yazi-core/src/manager/commands/open.rs +++ b/yazi-core/src/manager/commands/open.rs @@ -42,9 +42,9 @@ impl Manager { let (mut done, mut todo) = (Vec::with_capacity(selected.len()), vec![]); for u in selected { if self.mimetype.contains(u) { - done.push((u.clone(), Cow::Borrowed(""))); + done.push((u.clone(), "")); } else if self.guess_folder(u) { - done.push((u.clone(), Cow::Borrowed(MIME_DIR))); + done.push((u.clone(), MIME_DIR)); } else { todo.push(u.clone()); } @@ -63,7 +63,7 @@ impl Manager { } } - done.extend(files.iter().map(|f| (f.url_owned(), Cow::Borrowed("")))); + done.extend(files.iter().map(|f| (f.url_owned(), ""))); 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}"); @@ -85,7 +85,7 @@ impl Manager { .targets .into_iter() .filter_map(|(u, m)| { - Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.by_url_owned(&u)).map(|m| (u, m)) + Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.by_url(&u)).map(|m| (u, m)) }) .collect(); diff --git a/yazi-core/src/manager/tabs.rs b/yazi-core/src/manager/tabs.rs index 2e53d70a..0a32ff18 100644 --- a/yazi-core/src/manager/tabs.rs +++ b/yazi-core/src/manager/tabs.rs @@ -2,10 +2,11 @@ use std::ops::{Deref, DerefMut}; use yazi_boot::BOOT; use yazi_dds::Pubsub; +use yazi_fs::File; use yazi_proxy::ManagerProxy; use yazi_shared::{Id, url::Url}; -use crate::tab::Tab; +use crate::tab::{Folder, Tab}; pub struct Tabs { pub cursor: usize, @@ -70,6 +71,12 @@ impl Tabs { } } + #[inline] + pub fn current(&self) -> &Folder { &self.active().current } + + #[inline] + pub fn hovered(&self) -> Option<&File> { self.current().hovered() } + #[inline] pub fn find_mut(&mut self, id: Id) -> Option<&mut Tab> { self.iter_mut().find(|t| t.id == id) } } diff --git a/yazi-core/src/tasks/process.rs b/yazi-core/src/tasks/process.rs index bcfc518a..4294755d 100644 --- a/yazi-core/src/tasks/process.rs +++ b/yazi-core/src/tasks/process.rs @@ -7,7 +7,7 @@ use yazi_shared::url::Url; use super::Tasks; impl Tasks { - pub fn process_from_files(&self, cwd: Url, hovered: Url, targets: Vec<(Url, Cow)>) { + pub fn process_from_files(&self, cwd: Url, hovered: Url, targets: Vec<(Url, &str)>) { let mut openers = HashMap::new(); for (url, mime) in targets { if let Some(opener) = OPEN.openers(&url, mime).and_then(|o| o.first().copied()) { diff --git a/yazi-proxy/src/options/open.rs b/yazi-proxy/src/options/open.rs index 0e063ffe..22517483 100644 --- a/yazi-proxy/src/options/open.rs +++ b/yazi-proxy/src/options/open.rs @@ -8,7 +8,7 @@ use yazi_shared::{event::CmdCow, url::Url}; pub struct OpenDoOpt { pub cwd: Url, pub hovered: Url, - pub targets: Vec<(Url, Cow<'static, str>)>, + pub targets: Vec<(Url, &'static str)>, pub interactive: bool, } diff --git a/yazi-shared/src/url/url.rs b/yazi-shared/src/url/url.rs index 144b853d..8155ad3d 100644 --- a/yazi-shared/src/url/url.rs +++ b/yazi-shared/src/url/url.rs @@ -1,4 +1,4 @@ -use std::{ffi::OsStr, fmt::{Debug, Display, Formatter}, ops::Deref, path::{Path, PathBuf}}; +use std::{ffi::OsStr, fmt::{Debug, Display, Formatter}, hash::{Hash, Hasher}, ops::Deref, path::{Path, PathBuf}}; use percent_encoding::{AsciiSet, CONTROLS, percent_decode_str, percent_encode}; use serde::{Deserialize, Serialize}; @@ -8,7 +8,7 @@ use crate::url::Loc; const ENCODE_SET: &AsciiSet = &CONTROLS.add(b'#'); -#[derive(Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Default, Eq, Ord, PartialEq, PartialOrd)] pub struct Url { loc: Loc, scheme: UrlScheme, @@ -112,7 +112,7 @@ impl AsRef for Url { impl Display for Url { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { if matches!(self.scheme, UrlScheme::Regular | UrlScheme::SearchItem) { - return f.write_str(&self.loc.to_string_lossy()); + return write!(f, "{}", self.loc.display()); } let scheme = match self.scheme { @@ -265,6 +265,20 @@ impl From<&str> for UrlScheme { } } +impl Hash for Url { + fn hash(&self, state: &mut H) { + self.loc.hash(state); + + match self.scheme { + UrlScheme::Regular | UrlScheme::SearchItem => {} + UrlScheme::Search | UrlScheme::Archive => { + self.scheme.hash(state); + self.frag.hash(state); + } + } + } +} + impl Serialize for Url { fn serialize(&self, serializer: S) -> Result { serializer.collect_str(self)