diff --git a/yazi-actor/src/cmp/trigger.rs b/yazi-actor/src/cmp/trigger.rs index c92ef137..07f192ff 100644 --- a/yazi-actor/src/cmp/trigger.rs +++ b/yazi-actor/src/cmp/trigger.rs @@ -68,8 +68,8 @@ impl Actor for Trigger { impl Trigger { fn split_url(s: &str) -> Option<(UrlBuf, PathBufDyn)> { let (scheme, path) = SchemeCow::parse(s.as_bytes()).ok()?; + let scheme = scheme.zeroed(); - tracing::debug!(?scheme, ?path); if scheme.is_local() && path.as_strand() == "~" { return None; // We don't autocomplete a `~`, but `~/` } @@ -86,7 +86,11 @@ impl Trigger { (UrlCow::try_from((scheme, root)).ok()?.into_owned(), c.into()) } Some((p, c)) => (expand_url(UrlCow::try_from((scheme, p)).ok()?), c.into()), - None => (CWD.load().as_ref().clone(), path.into()), + None if CWD.load().scheme().covariant(&scheme) => (CWD.load().as_ref().clone(), path.into()), + None => { + let empty = PathDyn::with_str(scheme.kind(), ""); + (UrlCow::try_from((scheme, empty)).ok()?.into_owned(), path.into()) + } }) } } @@ -108,6 +112,7 @@ mod tests { #[cfg(unix)] #[test] fn test_split() { + yazi_shared::init_tests(); yazi_fs::init(); compare("", "", ""); compare(" ", "", " "); @@ -124,6 +129,12 @@ mod tests { compare("//foo/", "/foo/", ""); compare("/foo/bar", "/foo/", "bar"); compare("///foo/bar", "/foo/", "bar"); + + CWD.set(&"sftp://test/".parse::().unwrap(), || {}); + compare("sftp://test/a", "sftp://test/", "a"); + compare("sftp://test//a", "sftp://test:0//", "a"); + compare("sftp://test2/a", "sftp://test2/", "a"); + compare("sftp://test2//a", "sftp://test2:0//", "a"); } #[cfg(windows)] @@ -131,9 +142,11 @@ mod tests { fn test_split() { yazi_fs::init(); compare("foo", "", "foo"); + compare(r"foo\", r"foo\", ""); compare(r"foo\bar", r"foo\", "bar"); compare(r"foo\bar\", r"foo\bar\", ""); + compare(r"C:\", r"C:\", ""); compare(r"C:\foo", r"C:\", "foo"); compare(r"C:\foo\", r"C:\foo\", ""); diff --git a/yazi-actor/src/mgr/cd.rs b/yazi-actor/src/mgr/cd.rs index 72a9433f..0f855dbc 100644 --- a/yazi-actor/src/mgr/cd.rs +++ b/yazi-actor/src/mgr/cd.rs @@ -9,8 +9,8 @@ use yazi_fs::{File, FilesOp, path::expand_url}; use yazi_macro::{act, err, render, succ}; use yazi_parser::mgr::CdOpt; use yazi_proxy::{CmpProxy, InputProxy, MgrProxy}; -use yazi_shared::{Debounce, data::Data, errors::InputError, url::{UrlBuf, UrlLike}}; -use yazi_vfs::VfsFile; +use yazi_shared::{Debounce, data::Data, errors::InputError, url::{AsUrl, UrlBuf, UrlLike}}; +use yazi_vfs::{VfsFile, provider}; use crate::{Actor, Ctx}; @@ -24,7 +24,7 @@ impl Actor for Cd { fn act(cx: &mut Ctx, opt: Self::Options) -> Result { act!(mgr:escape_visual, cx)?; if opt.interactive { - return Self::cd_interactive(); + return Self::cd_interactive(cx); } let tab = cx.tab_mut(); @@ -59,8 +59,8 @@ impl Actor for Cd { } impl Cd { - fn cd_interactive() -> Result { - let input = InputProxy::show(InputCfg::cd()); + fn cd_interactive(cx: &Ctx) -> Result { + let input = InputProxy::show(InputCfg::cd(cx.cwd().as_url())); tokio::spawn(async move { let rx = Debounce::new(UnboundedReceiverStream::new(input), Duration::from_millis(50)); @@ -70,6 +70,7 @@ impl Cd { match result { Ok(s) => { let Ok(url) = UrlBuf::try_from(s).map(expand_url) else { return }; + let Ok(url) = provider::absolute(&url).await else { return }; let Ok(file) = File::new(&url).await else { return }; if file.is_dir() { @@ -79,10 +80,10 @@ impl Cd { if let Some(p) = url.parent() { FilesOp::Upserting(p.into(), [(url.urn().into(), file)].into()).emit(); } - MgrProxy::reveal(&url); + MgrProxy::reveal(url); } Err(InputError::Completed(before, ticket)) => { - CmpProxy::trigger(&before, ticket); + CmpProxy::trigger(before, ticket); } _ => break, } diff --git a/yazi-actor/src/mgr/displace.rs b/yazi-actor/src/mgr/displace.rs index 3fa0d6ea..ef039798 100644 --- a/yazi-actor/src/mgr/displace.rs +++ b/yazi-actor/src/mgr/displace.rs @@ -1,7 +1,6 @@ -use anyhow::{Result, bail}; -use yazi_fs::FilesOp; -use yazi_macro::{act, succ}; -use yazi_parser::{VoidOpt, mgr::{CdSource, DisplaceDoOpt}}; +use anyhow::Result; +use yazi_macro::succ; +use yazi_parser::{VoidOpt, mgr::DisplaceDoOpt}; use yazi_proxy::MgrProxy; use yazi_shared::{data::Data, url::UrlLike}; use yazi_vfs::provider; @@ -23,42 +22,9 @@ impl Actor for Displace { let tab = cx.tab().id; let from = cx.cwd().to_owned(); tokio::spawn(async move { - MgrProxy::displace_do(tab, DisplaceDoOpt { - to: provider::absolute(&from).await.map(|u| u.into_owned()), - from, - }); + MgrProxy::displace_do(tab, DisplaceDoOpt { to: provider::canonicalize(&from).await, from }); }); succ!(); } } - -// --- Do -pub struct DisplaceDo; - -impl Actor for DisplaceDo { - type Options = DisplaceDoOpt; - - const NAME: &str = "displace_do"; - - fn act(cx: &mut Ctx, opt: Self::Options) -> Result { - if cx.cwd() != opt.from { - succ!() - } - - let to = match opt.to { - Ok(url) => url, - Err(e) => return act!(mgr:update_files, cx, FilesOp::IOErr(opt.from, e.into())), - }; - - if !to.is_absolute() { - bail!("Target URL must be absolute"); - } else if let Some(hovered) = cx.hovered() - && let Ok(url) = to.try_join(hovered.urn()) - { - act!(mgr:reveal, cx, (url, CdSource::Displace)) - } else { - act!(mgr:cd, cx, (to, CdSource::Displace)) - } - } -} diff --git a/yazi-actor/src/mgr/displace_do.rs b/yazi-actor/src/mgr/displace_do.rs new file mode 100644 index 00000000..aa707ed2 --- /dev/null +++ b/yazi-actor/src/mgr/displace_do.rs @@ -0,0 +1,36 @@ +use anyhow::{Result, bail}; +use yazi_fs::FilesOp; +use yazi_macro::{act, succ}; +use yazi_parser::mgr::{CdSource, DisplaceDoOpt}; +use yazi_shared::{data::Data, url::UrlLike}; + +use crate::{Actor, Ctx}; + +pub struct DisplaceDo; + +impl Actor for DisplaceDo { + type Options = DisplaceDoOpt; + + const NAME: &str = "displace_do"; + + fn act(cx: &mut Ctx, opt: Self::Options) -> Result { + if cx.cwd() != opt.from { + succ!() + } + + let to = match opt.to { + Ok(url) => url, + Err(e) => return act!(mgr:update_files, cx, FilesOp::IOErr(opt.from, e.into())), + }; + + if !to.is_absolute() { + bail!("Target URL must be absolute"); + } else if let Some(hovered) = cx.hovered() + && let Ok(url) = to.try_join(hovered.urn()) + { + act!(mgr:reveal, cx, (url, CdSource::Displace)) + } else { + act!(mgr:cd, cx, (to, CdSource::Displace)) + } + } +} diff --git a/yazi-actor/src/mgr/mod.rs b/yazi-actor/src/mgr/mod.rs index 68c0a218..b6bf2d4e 100644 --- a/yazi-actor/src/mgr/mod.rs +++ b/yazi-actor/src/mgr/mod.rs @@ -7,6 +7,7 @@ yazi_macro::mod_flat!( copy create displace + displace_do download enter escape diff --git a/yazi-actor/src/mgr/search.rs b/yazi-actor/src/mgr/search.rs index eac83e7c..af526351 100644 --- a/yazi-actor/src/mgr/search.rs +++ b/yazi-actor/src/mgr/search.rs @@ -8,7 +8,7 @@ use yazi_fs::{FilesOp, cha::Cha}; use yazi_macro::{act, succ}; use yazi_parser::{VoidOpt, mgr::{CdSource, SearchOpt, SearchOptVia}}; use yazi_plugin::external; -use yazi_proxy::{InputProxy, MgrProxy}; +use yazi_proxy::{AppProxy, InputProxy, MgrProxy}; use yazi_shared::{data::Data, url::UrlLike}; use crate::{Actor, Ctx}; @@ -52,8 +52,10 @@ impl Actor for SearchDo { handle.abort(); } - let cwd = tab.cwd().to_search(&opt.subject)?; let hidden = tab.pref.show_hidden; + let Ok(cwd) = tab.cwd().to_search(&opt.subject) else { + succ!(AppProxy::notify_warn("Search", "Only local filesystem searches are supported")); + }; tab.search = Some(tokio::spawn(async move { let rx = match opt.via { diff --git a/yazi-actor/src/mgr/stash.rs b/yazi-actor/src/mgr/stash.rs index afcc8597..2dede4a5 100644 --- a/yazi-actor/src/mgr/stash.rs +++ b/yazi-actor/src/mgr/stash.rs @@ -14,7 +14,7 @@ impl Actor for Stash { const NAME: &str = "stash"; fn act(cx: &mut Ctx, opt: Self::Options) -> Result { - if opt.target.is_internal() { + if opt.target.is_absolute() && opt.target.is_internal() { cx.tab_mut().backstack.push(opt.target.as_url()); } diff --git a/yazi-config/src/popup/options.rs b/yazi-config/src/popup/options.rs index 17dcf238..55a41be1 100644 --- a/yazi-config/src/popup/options.rs +++ b/yazi-config/src/popup/options.rs @@ -1,5 +1,5 @@ use ratatui::{text::{Line, Text}, widgets::{Paragraph, Wrap}}; -use yazi_shared::{strand::ToStrand, url::UrlBuf}; +use yazi_shared::{scheme::Encode as EncodeScheme, strand::ToStrand, url::{Url, UrlBuf}}; use super::{Offset, Position}; use crate::YAZI; @@ -31,9 +31,10 @@ pub struct ConfirmCfg { } impl InputCfg { - pub fn cd() -> Self { + pub fn cd(cwd: Url) -> Self { Self { title: YAZI.input.cd_title.clone(), + value: if cwd.kind().is_local() { String::new() } else { EncodeScheme(cwd).to_string() }, position: Position::new(YAZI.input.cd_origin, YAZI.input.cd_offset), completion: true, ..Default::default() diff --git a/yazi-plugin/src/external/fd.rs b/yazi-plugin/src/external/fd.rs index 2f9585dc..5b0545a5 100644 --- a/yazi-plugin/src/external/fd.rs +++ b/yazi-plugin/src/external/fd.rs @@ -2,8 +2,8 @@ use std::process::Stdio; use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, process::{Child, Command}, sync::mpsc::{self, UnboundedReceiver}}; -use yazi_fs::File; -use yazi_shared::url::{UrlBuf, UrlLike}; +use yazi_fs::{File, FsUrl}; +use yazi_shared::url::{AsUrl, UrlBuf, UrlLike}; use yazi_vfs::VfsFile; pub struct FdOpt { @@ -34,16 +34,9 @@ pub fn fd(opt: FdOpt) -> Result> { } fn spawn(program: &str, opt: &FdOpt) -> std::io::Result { - let Some(path) = opt.cwd.as_local() else { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - "fd can only search local filesystem", - )); - }; - Command::new(program) .arg("--base-directory") - .arg(path) + .arg(&*opt.cwd.as_url().unified_path()) .arg("--regex") .arg(if opt.hidden { "--hidden" } else { "--no-hidden" }) .args(&opt.args) diff --git a/yazi-plugin/src/external/rg.rs b/yazi-plugin/src/external/rg.rs index 4f3c6452..65c72431 100644 --- a/yazi-plugin/src/external/rg.rs +++ b/yazi-plugin/src/external/rg.rs @@ -1,9 +1,9 @@ use std::process::Stdio; -use anyhow::{Result, bail}; +use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}}; -use yazi_fs::File; -use yazi_shared::url::{UrlBuf, UrlLike}; +use yazi_fs::{File, FsUrl}; +use yazi_shared::url::{AsUrl, UrlBuf, UrlLike}; use yazi_vfs::VfsFile; pub struct RgOpt { @@ -14,16 +14,12 @@ pub struct RgOpt { } pub fn rg(opt: RgOpt) -> Result> { - let Some(path) = opt.cwd.as_local() else { - bail!("rg can only search local filesystem"); - }; - let mut child = Command::new("rg") .args(["--color=never", "--files-with-matches", "--smart-case"]) .arg(if opt.hidden { "--hidden" } else { "--no-hidden" }) .args(opt.args) .arg(opt.subject) - .arg(path) + .arg(&*opt.cwd.as_url().unified_path()) .kill_on_drop(true) .stdout(Stdio::piped()) .stderr(Stdio::null()) diff --git a/yazi-plugin/src/external/rga.rs b/yazi-plugin/src/external/rga.rs index d038eae8..a41a5acb 100644 --- a/yazi-plugin/src/external/rga.rs +++ b/yazi-plugin/src/external/rga.rs @@ -1,9 +1,9 @@ use std::process::Stdio; -use anyhow::{Result, bail}; +use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}}; -use yazi_fs::File; -use yazi_shared::url::{UrlBuf, UrlLike}; +use yazi_fs::{File, FsUrl}; +use yazi_shared::url::{AsUrl, UrlBuf, UrlLike}; use yazi_vfs::VfsFile; pub struct RgaOpt { @@ -14,16 +14,12 @@ pub struct RgaOpt { } pub fn rga(opt: RgaOpt) -> Result> { - let Some(path) = opt.cwd.as_local() else { - bail!("rga can only search local filesystem"); - }; - let mut child = Command::new("rga") .args(["--color=never", "--files-with-matches", "--smart-case"]) .arg(if opt.hidden { "--hidden" } else { "--no-hidden" }) .args(opt.args) .arg(opt.subject) - .arg(path) + .arg(&*opt.cwd.as_url().unified_path()) .kill_on_drop(true) .stdout(Stdio::piped()) .stderr(Stdio::null()) diff --git a/yazi-proxy/src/cmp.rs b/yazi-proxy/src/cmp.rs index 2597244e..f77a166e 100644 --- a/yazi-proxy/src/cmp.rs +++ b/yazi-proxy/src/cmp.rs @@ -9,7 +9,7 @@ impl CmpProxy { emit!(Call(relay!(cmp:show).with_any("opt", opt))); } - pub fn trigger(word: &str, ticket: Id) { - emit!(Call(relay!(cmp:trigger, [word]).with("ticket", ticket))); + pub fn trigger(word: impl Into, ticket: Id) { + emit!(Call(relay!(cmp:trigger, [word.into()]).with("ticket", ticket))); } } diff --git a/yazi-proxy/src/mgr.rs b/yazi-proxy/src/mgr.rs index 37826c26..757b0c6b 100644 --- a/yazi-proxy/src/mgr.rs +++ b/yazi-proxy/src/mgr.rs @@ -11,8 +11,8 @@ impl MgrProxy { emit!(Call(relay!(mgr:arrow, [step.into()]))); } - pub fn cd(target: &UrlBuf) { - emit!(Call(relay!(mgr:cd, [target]).with("raw", true))); + pub fn cd(target: impl Into) { + emit!(Call(relay!(mgr:cd, [target.into()]).with("raw", true))); } pub fn displace_do(tab: Id, opt: DisplaceDoOpt) { @@ -41,8 +41,8 @@ impl MgrProxy { )); } - pub fn reveal(target: &UrlBuf) { - emit!(Call(relay!(mgr:reveal, [target]).with("raw", true).with("no-dummy", true))); + pub fn reveal(target: impl Into) { + emit!(Call(relay!(mgr:reveal, [target.into()]).with("raw", true).with("no-dummy", true))); } pub fn search_do(opt: SearchOpt) { diff --git a/yazi-shared/src/scheme/cow.rs b/yazi-shared/src/scheme/cow.rs index 7c92c371..1ec93849 100644 --- a/yazi-shared/src/scheme/cow.rs +++ b/yazi-shared/src/scheme/cow.rs @@ -168,6 +168,14 @@ impl<'a> SchemeCow<'a> { } impl<'a> SchemeCow<'a> { + #[inline] + pub fn into_domain(self) -> Option> { + Some(match self { + SchemeCow::Borrowed(s) => s.domain()?.into(), + SchemeCow::Owned(s) => s.into_domain()?.into(), + }) + } + #[inline] pub fn into_owned(self) -> Scheme { match self { @@ -176,13 +184,15 @@ impl<'a> SchemeCow<'a> { } } - #[inline] - pub fn into_domain(self) -> Option> { - Some(match self { - SchemeCow::Borrowed(s) => s.domain()?.into(), - SchemeCow::Owned(s) => s.into_domain()?.into(), - }) + pub fn with_ports(self, uri: usize, urn: usize) -> Self { + match self { + Self::Borrowed(s) => s.with_ports(uri, urn).into(), + Self::Owned(s) => s.with_ports(uri, urn).into(), + } } + + #[inline] + pub fn zeroed(self) -> Self { self.with_ports(0, 0) } } #[cfg(test)] diff --git a/yazi-shared/src/scheme/ref.rs b/yazi-shared/src/scheme/ref.rs index 1468305e..a6a69beb 100644 --- a/yazi-shared/src/scheme/ref.rs +++ b/yazi-shared/src/scheme/ref.rs @@ -43,13 +43,9 @@ impl From> for Scheme { impl<'a> SchemeRef<'a> { #[inline] - pub const fn kind(self) -> SchemeKind { - match self { - Self::Regular { .. } => SchemeKind::Regular, - Self::Search { .. } => SchemeKind::Search, - Self::Archive { .. } => SchemeKind::Archive, - Self::Sftp { .. } => SchemeKind::Sftp, - } + pub fn covariant(self, other: impl AsScheme) -> bool { + let other = other.as_scheme(); + if self.is_virtual() || other.is_virtual() { self == other } else { true } } #[inline] @@ -62,6 +58,16 @@ impl<'a> SchemeRef<'a> { } } + #[inline] + pub const fn kind(self) -> SchemeKind { + match self { + Self::Regular { .. } => SchemeKind::Regular, + Self::Search { .. } => SchemeKind::Search, + Self::Archive { .. } => SchemeKind::Archive, + Self::Sftp { .. } => SchemeKind::Sftp, + } + } + #[inline] pub const fn ports(self) -> (usize, usize) { match self { @@ -72,22 +78,6 @@ impl<'a> SchemeRef<'a> { } } - #[inline] - pub const fn zeroed(self) -> Self { - match self { - Self::Regular { .. } => Self::Regular { uri: 0, urn: 0 }, - Self::Search { domain, .. } => Self::Search { domain, uri: 0, urn: 0 }, - Self::Archive { domain, .. } => Self::Archive { domain, uri: 0, urn: 0 }, - Self::Sftp { domain, .. } => Self::Sftp { domain, uri: 0, urn: 0 }, - } - } - - #[inline] - pub fn covariant(self, other: impl AsScheme) -> bool { - let other = other.as_scheme(); - if self.is_virtual() || other.is_virtual() { self == other } else { true } - } - pub fn to_owned(self) -> Scheme { match self { Self::Regular { uri, urn } => Scheme::Regular { uri, urn }, @@ -96,4 +86,16 @@ impl<'a> SchemeRef<'a> { Self::Sftp { domain, uri, urn } => Scheme::Sftp { domain: domain.intern(), uri, urn }, } } + + pub const fn with_ports(self, uri: usize, urn: usize) -> Self { + match self { + Self::Regular { .. } => Self::Regular { uri, urn }, + Self::Search { domain, .. } => Self::Search { domain, uri, urn }, + Self::Archive { domain, .. } => Self::Archive { domain, uri, urn }, + Self::Sftp { domain, .. } => Self::Sftp { domain, uri, urn }, + } + } + + #[inline] + pub const fn zeroed(self) -> Self { self.with_ports(0, 0) } } diff --git a/yazi-shared/src/scheme/scheme.rs b/yazi-shared/src/scheme/scheme.rs index 71d6a84f..1d5961f3 100644 --- a/yazi-shared/src/scheme/scheme.rs +++ b/yazi-shared/src/scheme/scheme.rs @@ -38,4 +38,7 @@ impl Scheme { Self::Sftp { domain, .. } => Self::Sftp { domain, uri, urn }, } } + + #[inline] + pub fn zeroed(self) -> Self { self.with_ports(0, 0) } } diff --git a/yazi-vfs/src/provider/copier.rs b/yazi-vfs/src/provider/copier.rs index 805346a0..c07b0946 100644 --- a/yazi-vfs/src/provider/copier.rs +++ b/yazi-vfs/src/provider/copier.rs @@ -44,15 +44,15 @@ pub(super) fn copy_with_progress_impl( Some(f) }; - let chunks = (cha.len + 10485760 - 1) / 10485760; + let chunks = (cha.len + 5242880 - 1) / 5242880; let mut result = futures::stream::iter(0..chunks) .map(|i| { let acc_ = acc_.clone(); let (from, to) = (from.clone(), to.clone()); let (src, dist) = (src.take(), dist.take()); async move { - let offset = i * 10485760; - let take = cha.len.saturating_sub(offset).min(10485760); + let offset = i * 5242880; + let take = cha.len.saturating_sub(offset).min(5242880); let mut src = BufReader::with_capacity(524288, match src { Some(f) => f, @@ -93,7 +93,7 @@ pub(super) fn copy_with_progress_impl( } } }) - .buffer_unordered(3) + .buffer_unordered(4) .try_fold(None, |first, file| async { Ok(first.or(file)) }) .await; diff --git a/yazi-vfs/src/provider/sftp/sftp.rs b/yazi-vfs/src/provider/sftp/sftp.rs index 2be85fdc..87c9928f 100644 --- a/yazi-vfs/src/provider/sftp/sftp.rs +++ b/yazi-vfs/src/provider/sftp/sftp.rs @@ -2,7 +2,7 @@ use std::{io, sync::Arc}; use tokio::{io::{AsyncWriteExt, BufReader, BufWriter}, sync::mpsc::Receiver}; use yazi_config::vfs::{ProviderSftp, Vfs}; -use yazi_fs::provider::{DirReader, FileHolder, Provider}; +use yazi_fs::{CWD, provider::{DirReader, FileHolder, Provider}}; use yazi_sftp::fs::{Attrs, Flags}; use yazi_shared::{loc::LocBuf, path::{AsPath, PathBufDyn}, pool::InternStr, scheme::SchemeKind, url::{Url, UrlBuf, UrlCow, UrlLike}}; @@ -26,7 +26,14 @@ impl<'a> Provider for Sftp<'a> { type UrlCow = UrlCow<'a>; async fn absolute(&self) -> io::Result { - Ok(if self.url.is_absolute() { self.url.into() } else { self.canonicalize().await?.into() }) + let cwd = CWD.load(); + Ok(if self.url.is_absolute() { + self.url.into() + } else if cwd.scheme().covariant(self.url.scheme()) { + cwd.try_join(self.path)?.into() + } else { + self.canonicalize().await?.into() + }) } async fn canonicalize(&self) -> io::Result { diff --git a/yazi-watcher/src/local/linked.rs b/yazi-watcher/src/local/linked.rs index 44a6c4de..41d5b4c1 100644 --- a/yazi-watcher/src/local/linked.rs +++ b/yazi-watcher/src/local/linked.rs @@ -59,7 +59,7 @@ impl Linked { Ok(to) if to != *from => _ = linked.write().entry_ref(from).insert(to), Ok(_) => _ = linked.write().remove(from), Err(e) if e.kind() == std::io::ErrorKind::NotFound => _ = linked.write().remove(from), - Err(_) => {} + Err(e) => tracing::error!("Failed to canonicalize watched path {from:?}: {e:?}"), } } }) diff --git a/yazi-watcher/src/watcher.rs b/yazi-watcher/src/watcher.rs index de7fa1ee..a8ce1dcd 100644 --- a/yazi-watcher/src/watcher.rs +++ b/yazi-watcher/src/watcher.rs @@ -56,9 +56,7 @@ impl Watcher { if !to_unwatch.is_empty() || !to_watch.is_empty() { backend = Self::sync(backend, to_unwatch, to_watch).await; - if !rx.has_changed().unwrap_or(false) { - backend = backend.sync().await; - } + backend = backend.sync().await; } if rx.changed().await.is_err() {