diff --git a/yazi-core/src/completion/commands/show.rs b/yazi-core/src/completion/commands/show.rs index 707b0cb8..8c3e4461 100644 --- a/yazi-core/src/completion/commands/show.rs +++ b/yazi-core/src/completion/commands/show.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, mem, ops::ControlFlow}; +use std::{borrow::Cow, mem, ops::ControlFlow, path::PathBuf}; use yazi_macro::render; use yazi_shared::event::{Cmd, CmdCow, Data}; @@ -9,7 +9,7 @@ const LIMIT: usize = 30; struct Opt { cache: Vec, - cache_name: Cow<'static, str>, + cache_name: PathBuf, word: Cow<'static, str>, ticket: usize, } @@ -18,7 +18,7 @@ impl From for Opt { fn from(mut c: CmdCow) -> Self { Self { cache: c.take_any("cache").unwrap_or_default(), - cache_name: c.take_str("cache-name").unwrap_or_default(), + cache_name: c.take_any("cache-name").unwrap_or_default(), word: c.take_str("word").unwrap_or_default(), ticket: c.get("ticket").and_then(Data::as_usize).unwrap_or(0), } @@ -37,9 +37,9 @@ impl Completion { } if !opt.cache.is_empty() { - self.caches.insert(opt.cache_name.as_ref().to_owned(), opt.cache); + self.caches.insert(opt.cache_name.clone(), opt.cache); } - let Some(cache) = self.caches.get(opt.cache_name.as_ref()) else { + let Some(cache) = self.caches.get(&opt.cache_name) else { return; }; diff --git a/yazi-core/src/completion/commands/trigger.rs b/yazi-core/src/completion/commands/trigger.rs index 012bd450..8a1f742f 100644 --- a/yazi-core/src/completion/commands/trigger.rs +++ b/yazi-core/src/completion/commands/trigger.rs @@ -1,17 +1,12 @@ -use std::{borrow::Cow, mem, path::{MAIN_SEPARATOR, MAIN_SEPARATOR_STR}}; +use std::{borrow::Cow, mem, path::{MAIN_SEPARATOR_STR, PathBuf}}; use tokio::fs; +use yazi_fs::{CWD, expand_path}; use yazi_macro::{emit, render}; use yazi_shared::{Layer, event::{Cmd, CmdCow, Data}}; use crate::completion::Completion; -#[cfg(windows)] -const SEPARATOR: [char; 2] = ['/', '\\']; - -#[cfg(not(windows))] -const SEPARATOR: char = std::path::MAIN_SEPARATOR; - struct Opt { word: Cow<'static, str>, ticket: usize, @@ -34,13 +29,13 @@ impl Completion { } self.ticket = opt.ticket; - let Some((parent, child)) = Self::split_path(&opt.word) else { + let Some((parent, word)) = Self::split_path(&opt.word) else { return self.close(false); }; if self.caches.contains_key(&parent) { return self.show( - Cmd::default().with("cache-name", parent).with("word", child).with("ticket", opt.ticket), + Cmd::default().with_any("cache-name", parent).with("word", word).with("ticket", opt.ticket), ); } @@ -62,8 +57,8 @@ impl Completion { emit!(Call( Cmd::new("show") .with_any("cache", cache) - .with("cache-name", parent) - .with("word", child) + .with_any("cache-name", parent) + .with("word", word) .with("ticket", ticket), Layer::Completion )); @@ -75,40 +70,42 @@ impl Completion { render!(mem::replace(&mut self.visible, false)); } - fn split_path(s: &str) -> Option<(String, String)> { + fn split_path(s: &str) -> Option<(PathBuf, String)> { if s == "~" { return None; // We don't autocomplete a `~`, but `~/` } - let s = if let Some(rest) = s.strip_prefix("~") { - Cow::Owned(format!( - "{}{rest}", - dirs::home_dir().unwrap_or_default().to_string_lossy().trim_end_matches(SEPARATOR), - )) - } else { - Cow::Borrowed(s) - }; + #[cfg(windows)] + const SEP: [char; 2] = ['/', '\\']; + #[cfg(not(windows))] + const SEP: char = std::path::MAIN_SEPARATOR; - Some(match s.rsplit_once(SEPARATOR) { - Some((p, c)) => (format!("{p}{}", MAIN_SEPARATOR), c.to_owned()), - None => (".".to_owned(), s.into_owned()), + Some(match s.rsplit_once(SEP) { + Some(("", c)) => (PathBuf::from(MAIN_SEPARATOR_STR), c.to_owned()), + Some((p, c)) => (expand_path(p), c.to_owned()), + None => (CWD.load().to_path_buf(), s.to_owned()), }) } } #[cfg(test)] mod tests { + use std::path::Path; + use super::*; fn compare(s: &str, parent: &str, child: &str) -> bool { - matches!(Completion::split_path(s), Some((p, c)) if p == parent && c == child) + let (p, c) = Completion::split_path(s).unwrap(); + let p = p.strip_prefix(yazi_fs::CWD.load().as_ref()).unwrap_or(&p); + p == Path::new(parent) && c == child } #[cfg(unix)] #[test] fn test_split() { - assert!(compare("", ".", "")); - assert!(compare(" ", ".", " ")); + yazi_fs::init(); + assert!(compare("", "", "")); + assert!(compare(" ", "", " ")); assert!(compare("/", "/", "")); assert!(compare("//", "//", "")); assert!(compare("/foo", "/", "foo")); @@ -119,7 +116,8 @@ mod tests { #[cfg(windows)] #[test] fn test_split() { - assert!(compare("foo", ".", "foo")); + yazi_fs::init(); + assert!(compare("foo", "", "foo")); assert!(compare("foo\\", "foo\\", "")); assert!(compare("foo\\bar", "foo\\", "bar")); assert!(compare("foo\\bar\\", "foo\\bar\\", "")); diff --git a/yazi-core/src/completion/completion.rs b/yazi-core/src/completion/completion.rs index 5cad5a00..c283c960 100644 --- a/yazi-core/src/completion/completion.rs +++ b/yazi-core/src/completion/completion.rs @@ -1,8 +1,8 @@ -use std::collections::HashMap; +use std::{collections::HashMap, path::PathBuf}; #[derive(Default)] pub struct Completion { - pub(super) caches: HashMap>, + pub(super) caches: HashMap>, pub(super) cands: Vec, pub(super) offset: usize, pub cursor: usize,