From 510884287bd37a5a4e7a46c57f4af0682cc8f2e0 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Sat, 4 Nov 2023 06:30:24 +0800 Subject: [PATCH] .. --- yazi-core/src/completion/commands/close.rs | 6 +-- yazi-core/src/completion/commands/show.rs | 3 +- yazi-core/src/completion/commands/trigger.rs | 47 +++++++++++++++++--- yazi-core/src/input/commands/complete.rs | 2 +- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/yazi-core/src/completion/commands/close.rs b/yazi-core/src/completion/commands/close.rs index f5a4c91e..ea3eaa65 100644 --- a/yazi-core/src/completion/commands/close.rs +++ b/yazi-core/src/completion/commands/close.rs @@ -8,10 +8,6 @@ impl From<&Exec> for Opt { fn from(e: &Exec) -> Self { Self(e.named.contains_key("submit")) } } -impl From for Opt { - fn from(b: bool) -> Self { Self(b) } -} - impl Completion { pub fn close(&mut self, opt: impl Into) -> bool { let submit = opt.into().0; @@ -22,7 +18,7 @@ impl Completion { )); } - self.cursor = 0; + self.caches.clear(); self.visible = false; true } diff --git a/yazi-core/src/completion/commands/show.rs b/yazi-core/src/completion/commands/show.rs index f9c811bc..7040200a 100644 --- a/yazi-core/src/completion/commands/show.rs +++ b/yazi-core/src/completion/commands/show.rs @@ -46,7 +46,6 @@ impl Completion { ControlFlow::Continue(v) }); - self.close(false); self.cands = match flow { ControlFlow::Continue(v) => v, ControlFlow::Break(v) => v, @@ -54,6 +53,8 @@ impl Completion { self.ticket = opt.ticket; if !self.cands.is_empty() { + self.offset = 0; + self.cursor = 0; self.visible = true; } true diff --git a/yazi-core/src/completion/commands/trigger.rs b/yazi-core/src/completion/commands/trigger.rs index 617d94e2..5ed07e07 100644 --- a/yazi-core/src/completion/commands/trigger.rs +++ b/yazi-core/src/completion/commands/trigger.rs @@ -1,3 +1,5 @@ +use std::mem; + use tokio::fs; use yazi_config::keymap::{Exec, KeymapLayer}; @@ -18,17 +20,24 @@ impl<'a> From<&'a Exec> for Opt<'a> { } impl Completion { + #[inline] + fn split_path(s: &str) -> (String, String) { + match s.rsplit_once(|c| c == '/' || c == '\\') { + Some((p, c)) => (format!("{p}/"), c.to_owned()), + None => (".".to_owned(), s.to_owned()), + } + } + pub fn trigger<'a>(&mut self, opt: impl Into>) -> bool { let opt = opt.into(); - if self.ticket >= opt.ticket { + if opt.ticket < self.ticket { return false; } - self.close(false); self.ticket = opt.ticket; + let (parent, child) = Self::split_path(opt.before); - let (parent, child) = opt.before.rsplit_once('/').unwrap_or((".", opt.before)); - if self.caches.contains_key(parent) { + if self.caches.contains_key(&parent) { return self.show( &Exec::call("show", vec![]) .with("cache-name", parent) @@ -38,7 +47,6 @@ impl Completion { } let ticket = self.ticket; - let (parent, child) = (parent.to_owned(), child.to_owned()); tokio::spawn(async move { let mut dir = fs::read_dir(&parent).await?; let mut cache = Vec::new(); @@ -70,6 +78,33 @@ impl Completion { Ok::<(), anyhow::Error>(()) }); - false + + mem::replace(&mut self.visible, false) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_explode() { + assert_eq!(Completion::split_path(""), (".".to_owned(), "".to_owned())); + assert_eq!(Completion::split_path(" "), (".".to_owned(), " ".to_owned())); + assert_eq!(Completion::split_path("/"), ("/".to_owned(), "".to_owned())); + assert_eq!(Completion::split_path("//"), ("//".to_owned(), "".to_owned())); + assert_eq!(Completion::split_path("/foo"), ("/".to_owned(), "foo".to_owned())); + assert_eq!(Completion::split_path("/foo/"), ("/foo/".to_owned(), "".to_owned())); + assert_eq!(Completion::split_path("/foo/bar"), ("/foo/".to_owned(), "bar".to_owned())); + + // Windows + assert_eq!(Completion::split_path("foo"), (".".to_owned(), "foo".to_owned())); + assert_eq!(Completion::split_path("foo\\"), ("foo/".to_owned(), "".to_owned())); + assert_eq!(Completion::split_path("foo\\bar"), ("foo/".to_owned(), "bar".to_owned())); + assert_eq!(Completion::split_path("foo\\bar\\"), ("foo\\bar/".to_owned(), "".to_owned())); + assert_eq!(Completion::split_path("C:\\"), ("C:/".to_owned(), "".to_owned())); + assert_eq!(Completion::split_path("C:\\foo"), ("C:/".to_owned(), "foo".to_owned())); + assert_eq!(Completion::split_path("C:\\foo\\"), ("C:\\foo/".to_owned(), "".to_owned())); + assert_eq!(Completion::split_path("C:\\foo\\bar"), ("C:\\foo/".to_owned(), "bar".to_owned())); } } diff --git a/yazi-core/src/input/commands/complete.rs b/yazi-core/src/input/commands/complete.rs index e73612cc..83d4c68c 100644 --- a/yazi-core/src/input/commands/complete.rs +++ b/yazi-core/src/input/commands/complete.rs @@ -11,7 +11,7 @@ impl<'a> From<&'a Exec> for Opt<'a> { fn from(e: &'a Exec) -> Self { Self { word: e.args.first().map(|w| w.as_str()).unwrap_or_default(), - ticket: e.named.get("ticket").and_then(|v| v.parse().ok()).unwrap_or(0), + ticket: e.named.get("ticket").and_then(|s| s.parse().ok()).unwrap_or(0), } } }