From 59eec67c35bc28bdd20889b60743eb16ba4800ce Mon Sep 17 00:00:00 2001 From: sxyazi Date: Wed, 6 Sep 2023 22:53:07 +0800 Subject: [PATCH] .. --- core/src/event.rs | 4 +- core/src/external/zoxide.rs | 3 +- core/src/files/files.rs | 20 ++++++++-- core/src/files/op.rs | 3 +- core/src/input/input.rs | 2 +- core/src/manager/manager.rs | 10 ++--- core/src/manager/preview/preview.rs | 6 +-- core/src/manager/tab.rs | 15 +++++--- core/src/manager/watcher.rs | 7 +++- core/src/tasks/tasks.rs | 4 +- core/src/tasks/workers/file.rs | 6 +-- core/src/which/which.rs | 2 +- shared/src/url.rs | 58 ++++++++++++++++++++--------- 13 files changed, 91 insertions(+), 49 deletions(-) diff --git a/core/src/event.rs b/core/src/event.rs index 97039857..762d6e46 100644 --- a/core/src/event.rs +++ b/core/src/event.rs @@ -71,8 +71,8 @@ macro_rules! emit { $crate::Event::Ctrl($exec, $layer).emit(); }; - (Cd($op:expr)) => { - $crate::Event::Cd($op).emit(); + (Cd($url:expr)) => { + $crate::Event::Cd($url).emit(); }; (Files($op:expr)) => { $crate::Event::Files($op).emit(); diff --git a/core/src/external/zoxide.rs b/core/src/external/zoxide.rs index ae46e07d..d947f1dd 100644 --- a/core/src/external/zoxide.rs +++ b/core/src/external/zoxide.rs @@ -17,12 +17,11 @@ pub fn zoxide(opt: ZoxideOpt) -> Result>> { .spawn()?; let (tx, rx) = oneshot::channel(); - let cwd = opt.cwd.clone(); tokio::spawn(async move { if let Ok(output) = child.wait_with_output().await { let selected = String::from_utf8_lossy(&output.stdout).trim().to_string(); if !selected.is_empty() { - tx.send(Ok(Url::new(selected, &cwd))).ok(); + tx.send(Ok(Url::from(selected))).ok(); return; } } diff --git a/core/src/files/files.rs b/core/src/files/files.rs index 0a81a05f..2c69bba7 100644 --- a/core/src/files/files.rs +++ b/core/src/files/files.rs @@ -46,13 +46,12 @@ impl Files { let mut it = fs::read_dir(url).await?; let (tx, rx) = mpsc::unbounded_channel(); - let url = url.clone(); tokio::spawn(async move { while let Ok(Some(item)) = it.next_entry().await { select! { _ = tx.closed() => break, Ok(meta) = item.metadata() => { - tx.send(File::from_meta(Url::new(item.path(), &url), meta).await).ok(); + tx.send(File::from_meta(Url::from(item.path()), meta).await).ok(); } } } @@ -82,10 +81,23 @@ impl Files { pub fn select_all(&mut self, state: Option) -> bool { match state { Some(true) => { + let b = if self.selected.len() < self.items.len() { + true + } else { + self.items.iter().any(|f| !self.selected.contains(&f.url)) + }; + self.selected = self.iter().map(|f| f.url_owned()).collect(); + b } Some(false) => { + if self.selected.is_empty() { + return false; + } + + let b = self.items.iter().any(|f| self.selected.contains(&f.url)); self.selected.clear(); + b } None => { for item in &self.items { @@ -95,9 +107,9 @@ impl Files { self.selected.insert(item.url_owned()); } } + !self.items.is_empty() } } - !self.items.is_empty() } pub fn select_index(&mut self, indices: &BTreeSet, state: Option) -> bool { @@ -169,7 +181,7 @@ impl Files { } #[inline] - pub fn position(&self, url: &Url) -> Option { self.iter().position(|f| f.url == *url) } + pub fn position(&self, url: &Url) -> Option { self.iter().position(|f| &f.url == url) } #[inline] pub fn duplicate(&self, idx: usize) -> Option { self.items.get(idx).cloned() } diff --git a/core/src/files/op.rs b/core/src/files/op.rs index 2ed3191a..346d880a 100644 --- a/core/src/files/op.rs +++ b/core/src/files/op.rs @@ -17,14 +17,13 @@ pub enum FilesOp { impl FilesOp { #[inline] - pub fn url(&self) -> Url { + pub fn url(&self) -> &Url { match self { Self::Full(url, _) => url, Self::Part(url, ..) => url, Self::Size(url, _) => url, Self::IOErr(url) => url, } - .clone() } #[inline] diff --git a/core/src/input/input.rs b/core/src/input/input.rs index 31752fb7..ca71e08d 100644 --- a/core/src/input/input.rs +++ b/core/src/input/input.rs @@ -308,7 +308,7 @@ impl Input { }; snap.cursor = snap.count().saturating_sub(snap.mode.delta()).min(snap.cursor); - if *snap == old { + if snap == &old { return false; } if !matches!(old.op, InputOp::None | InputOp::Select(_)) { diff --git a/core/src/manager/manager.rs b/core/src/manager/manager.rs index 3bdd93db..a4730b9a 100644 --- a/core/src/manager/manager.rs +++ b/core/src/manager/manager.rs @@ -189,7 +189,7 @@ impl Manager { fs::File::create(path).await?; } - if let Ok(file) = File::from(Url::new(hovered, &cwd)).await { + if let Ok(file) = File::from(Url::from(hovered)).await { emit!(Hover(file)); emit!(Refresh); } @@ -326,7 +326,7 @@ impl Manager { } pub fn update_read(&mut self, op: FilesOp) -> bool { - let url = op.url(); + let url = op.url().clone(); let cwd = self.cwd().to_owned(); let hovered = self.hovered().map(|h| h.url_owned()); @@ -337,7 +337,7 @@ impl Manager { } else { self.active_mut().history.entry(url.clone()).or_insert_with(|| Folder::from(&url)).update(op); - matches!(self.hovered(), Some(h) if *h.url() == url) + matches!(self.hovered(), Some(h) if h.url() == &url) }; b |= self.active_mut().parent.as_mut().map_or(false, |p| p.hover(&cwd)); @@ -353,9 +353,9 @@ impl Manager { let url = op.url(); let op = FilesOp::Full(url.clone(), Vec::new()); - if url == *self.cwd() { + if url == self.cwd() { self.current_mut().update(op); - } else if matches!(self.parent(), Some(p) if p.cwd == url) { + } else if matches!(self.parent(), Some(p) if &p.cwd == url) { self.active_mut().parent.as_mut().unwrap().update(op); } else { return false; diff --git a/core/src/manager/preview/preview.rs b/core/src/manager/preview/preview.rs index 31a1f6db..d7353f78 100644 --- a/core/src/manager/preview/preview.rs +++ b/core/src/manager/preview/preview.rs @@ -169,7 +169,7 @@ impl Preview { #[inline] pub fn same(&self, url: &Url, mime: &str) -> bool { if let Some(ref lock) = self.lock { - return lock.url == *url && lock.mime == mime && lock.skip == self.skip; + return &lock.url == url && lock.mime == mime && lock.skip == self.skip; } false } @@ -177,7 +177,7 @@ impl Preview { #[inline] pub fn same_mime(&self, url: &Url, mime: &str) -> bool { if let Some(ref lock) = self.lock { - return lock.url == *url && lock.mime == mime; + return &lock.url == url && lock.mime == mime; } false } @@ -185,7 +185,7 @@ impl Preview { #[inline] pub fn same_path(&self, url: &Url) -> bool { if let Some(ref lock) = self.lock { - return lock.url == *url; + return &lock.url == url; } false } diff --git a/core/src/manager/tab.rs b/core/src/manager/tab.rs index 25a44637..9bb6a96d 100644 --- a/core/src/manager/tab.rs +++ b/core/src/manager/tab.rs @@ -106,7 +106,7 @@ impl Tab { let rep = self.history_new(&target); let rep = mem::replace(&mut self.current, rep); - if !rep.cwd.is_search() { + if rep.cwd.is_regular() { self.history.insert(rep.cwd.clone(), rep); } @@ -127,7 +127,7 @@ impl Tab { emit!(Input(InputOpt::top("Change directory:").with_value(target.to_string_lossy()))); if let Ok(s) = result.await { - emit!(Cd(Url::new(s, &target))); + emit!(Cd(Url::from(s))); } }); false @@ -143,7 +143,7 @@ impl Tab { let rep = self.history_new(hovered.url()); let rep = mem::replace(&mut self.current, rep); - if !rep.cwd.is_search() { + if rep.cwd.is_regular() { self.history.insert(rep.cwd.clone(), rep); } @@ -178,7 +178,7 @@ impl Tab { let rep = self.history_new(¤t); let rep = mem::replace(&mut self.current, rep); - if !rep.cwd.is_search() { + if rep.cwd.is_regular() { self.history.insert(rep.cwd.clone(), rep); } @@ -253,7 +253,12 @@ impl Tab { pin!(rx); let version = FilesOp::prepare(&cwd); + let mut first = true; while let Some(chunk) = rx.next().await { + if first { + emit!(Cd(cwd.clone())); + first = false; + } emit!(Files(FilesOp::Part(cwd.clone(), version, chunk))); } Ok(()) @@ -268,7 +273,7 @@ impl Tab { if self.current.cwd.is_search() { self.preview_reset_image(); - let rep = self.history_new(&self.current.cwd.to_none()); + let rep = self.history_new(&self.current.cwd.to_regular()); drop(mem::replace(&mut self.current, rep)); emit!(Refresh); } diff --git a/core/src/manager/watcher.rs b/core/src/manager/watcher.rs index 0bb5aa4c..d501de04 100644 --- a/core/src/manager/watcher.rs +++ b/core/src/manager/watcher.rs @@ -67,6 +67,7 @@ impl Watcher { } pub(super) fn watch(&mut self, mut watched: BTreeSet<&Url>) { + watched.retain(|&u| u.is_regular()); let (to_unwatch, to_watch): (BTreeSet<_>, BTreeSet<_>) = { let guard = self.watched.read(); let keys = guard.keys().collect::>(); @@ -119,8 +120,12 @@ impl Watcher { } pub(super) fn trigger_dirs(&self, dirs: &[&Url]) { + let dirs: Vec<_> = dirs.iter().filter(|&u| u.is_regular()).map(|&u| u.clone()).collect(); + if dirs.is_empty() { + return; + } + let watched = self.watched.clone(); - let dirs: Vec<_> = dirs.iter().map(|&u| u.clone()).collect(); tokio::spawn(async move { for dir in dirs { Self::dir_changed(&dir, watched.clone()).await; diff --git a/core/src/tasks/tasks.rs b/core/src/tasks/tasks.rs index e7f0e27d..8614087a 100644 --- a/core/src/tasks/tasks.rs +++ b/core/src/tasks/tasks.rs @@ -157,7 +157,7 @@ impl Tasks { pub fn file_cut(&self, src: &HashSet, dest: Url, force: bool) -> bool { for p in src { let to = dest.join(p.file_name().unwrap()); - if force && *p == to { + if force && p == &to { trace!("file_cut: same file, skipping {:?}", to); } else { self.scheduler.file_cut(p.clone(), to, force); @@ -169,7 +169,7 @@ impl Tasks { pub fn file_copy(&self, src: &HashSet, dest: Url, force: bool, follow: bool) -> bool { for p in src { let to = dest.join(p.file_name().unwrap()); - if force && *p == to { + if force && p == &to { trace!("file_copy: same file, skipping {:?}", to); } else { self.scheduler.file_copy(p.clone(), to, force, follow); diff --git a/core/src/tasks/workers/file.rs b/core/src/tasks/workers/file.rs index 4f52eacb..c55258a6 100644 --- a/core/src/tasks/workers/file.rs +++ b/core/src/tasks/workers/file.rs @@ -256,7 +256,7 @@ impl File { let mut dirs = VecDeque::from([task.target]); while let Some(target) = dirs.pop_front() { - let mut it = match fs::read_dir(&target).await { + let mut it = match fs::read_dir(target).await { Ok(it) => it, Err(_) => continue, }; @@ -268,11 +268,11 @@ impl File { }; if meta.is_dir() { - dirs.push_front(Url::new(entry.path(), &target)); + dirs.push_front(Url::from(entry.path())); continue; } - task.target = Url::new(entry.path(), &target); + task.target = Url::from(entry.path()); task.length = meta.len(); self.sch.send(TaskOp::New(task.id, meta.len()))?; self.tx.send(FileOp::Delete(task.clone())).await?; diff --git a/core/src/which/which.rs b/core/src/which/which.rs index a18f7e6d..21dd4a3a 100644 --- a/core/src/which/which.rs +++ b/core/src/which/which.rs @@ -23,7 +23,7 @@ impl Which { self.layer = layer; self.times = 1; self.cands = - KEYMAP.get(layer).iter().filter(|s| s.on.len() > 1 && s.on[0] == *key).cloned().collect(); + KEYMAP.get(layer).iter().filter(|s| s.on.len() > 1 && &s.on[0] == key).cloned().collect(); self.switch(true); true } diff --git a/shared/src/url.rs b/shared/src/url.rs index 72a8172a..39c317f5 100644 --- a/shared/src/url.rs +++ b/shared/src/url.rs @@ -9,7 +9,7 @@ pub struct Url { #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum UrlScheme { #[default] - None, + Regular, Search, Archive, } @@ -62,14 +62,26 @@ impl AsRef for Url { impl Url { #[inline] - pub fn new(url: impl Into, ctx: &Url) -> Self { - let mut url: Self = url.into(); - url.scheme = ctx.scheme; - url + pub fn join(&self, path: impl AsRef) -> Self { + let url = Self::from(self.path.join(path)); + match self.scheme { + UrlScheme::Regular => url, + UrlScheme::Search => url, + UrlScheme::Archive => url.into_archive(), + } } #[inline] - pub fn join(&self, path: impl AsRef) -> Self { Self::new(self.path.join(path), self) } + pub fn parent_url(&self) -> Option { + self.path.parent().map(|p| { + let url = Self::from(p); + match self.scheme { + UrlScheme::Regular => url, + UrlScheme::Search => url, + UrlScheme::Archive => url, + } + }) + } #[inline] pub fn strip_prefix(&self, base: impl AsRef) -> Option<&Path> { @@ -83,32 +95,42 @@ impl Url { impl Url { // --- Scheme #[inline] - pub fn is_none(&self) -> bool { self.scheme == UrlScheme::None } + pub fn is_regular(&self) -> bool { self.scheme == UrlScheme::Regular } #[inline] - pub fn to_none(&self) -> Self { - let mut url = self.clone(); - url.scheme = UrlScheme::None; - url + pub fn to_regular(&self) -> Self { self.clone().into_regular() } + + #[inline] + pub fn into_regular(mut self) -> Self { + self.scheme = UrlScheme::Regular; + self } #[inline] pub fn is_search(&self) -> bool { self.scheme == UrlScheme::Search } #[inline] - pub fn to_search(&self) -> Self { - let mut url = self.clone(); - url.scheme = UrlScheme::Search; - url + pub fn to_search(&self) -> Self { self.clone().into_search() } + + #[inline] + pub fn into_search(mut self) -> Self { + self.scheme = UrlScheme::Search; + self } #[inline] pub fn is_archive(&self) -> bool { self.scheme == UrlScheme::Archive } + #[inline] + pub fn to_archive(&self) -> Self { self.clone().into_archive() } + + #[inline] + pub fn into_archive(mut self) -> Self { + self.scheme = UrlScheme::Archive; + self + } + // --- Path #[inline] pub fn set_path(&mut self, path: PathBuf) { self.path = path; } - - #[inline] - pub fn parent_url(&self) -> Option { self.path.parent().map(|p| Self::new(p, self)) } }