refactor!: return Path instead of Url from File.link_to (#3385)

This commit is contained in:
三咲雅 misaki masa 2025-11-30 12:08:59 +08:00 committed by GitHub
parent ade1025a74
commit 76196aab70
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 50 additions and 65 deletions

View file

@ -45,7 +45,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
- Rename `name` to `url` for open, fetchers, spotters, preloaders, previewers, filetype, and `globs` icon rules to support virtual file system ([#3034])
- Rename `mime` fetcher to `mime.local`, and introduce `mime.dir` fetcher to support folder MIME types ([#3222])
- Remove `$0` parameter in opener rules to make the `open` command work under empty directories ([#3226])
- Return `Path` instead of `Url` from `Url:strip_prefix()` to enforce type safety ([#3361])
- Return `Path` instead of `Url` from `Url:strip_prefix()` and `File.link_to` to enforce type safety ([#3361], [#3385])
- Use `body` instead of the term `content` in confirmations ([#2921])
- Use `u16` instead of `u32` as the type of `max_width` and `max_height` options to avoid memory exhaustion ([#3313])
- Implement `__pairs` metamethod instead of `__index` for the callback argument of the `@yank` DDS event ([#2997])
@ -1543,3 +1543,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
[#3360]: https://github.com/sxyazi/yazi/pull/3360
[#3364]: https://github.com/sxyazi/yazi/pull/3364
[#3369]: https://github.com/sxyazi/yazi/pull/3369
[#3385]: https://github.com/sxyazi/yazi/pull/3385

4
Cargo.lock generated
View file

@ -1764,9 +1764,9 @@ dependencies = [
[[package]]
name = "instability"
version = "0.3.9"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435d80800b936787d62688c927b6490e887c7ef5ff9ce922c6c6050fca75eb9a"
checksum = "6778b0196eefee7df739db78758e5cf9b37412268bfa5650bfeed028aed20d9c"
dependencies = [
"darling",
"indoc",

View file

@ -1,7 +1,7 @@
use anyhow::Result;
use yazi_macro::{act, succ};
use yazi_parser::{VoidOpt, mgr::CdSource};
use yazi_shared::data::Data;
use yazi_shared::{data::Data, url::UrlLike};
use crate::{Actor, Ctx};

View file

@ -2,7 +2,7 @@ use anyhow::{Result, bail};
use yazi_macro::{act, render, render_and, succ};
use yazi_parser::{VoidOpt, mgr::EscapeOpt};
use yazi_proxy::AppProxy;
use yazi_shared::data::Data;
use yazi_shared::{data::Data, url::UrlLike};
use crate::{Actor, Ctx};

View file

@ -1,7 +1,7 @@
use anyhow::Result;
use yazi_fs::path::clean_url;
use yazi_macro::{act, succ};
use yazi_parser::VoidOpt;
use yazi_parser::{VoidOpt, mgr::CdSource};
use yazi_shared::{data::Data, url::UrlLike};
use crate::{Actor, Ctx};
@ -18,6 +18,6 @@ impl Actor for Follow {
let Some(link_to) = &file.link_to else { succ!() };
let Some(parent) = file.url.parent() else { succ!() };
let Ok(joined) = parent.try_join(link_to) else { succ!() };
act!(mgr:reveal, cx, clean_url(joined))
act!(mgr:reveal, cx, (clean_url(joined), CdSource::Follow))
}
}

View file

@ -57,8 +57,11 @@ impl Refresh {
}
}
let futs: Vec<_> =
folders.iter().filter(|&f| f.url.is_internal()).map(|&f| go(f.url.clone(), f.cha)).collect();
let futs: Vec<_> = folders
.iter()
.filter(|&f| f.url.is_absolute() && f.url.is_internal())
.map(|&f| go(f.url.clone(), f.cha))
.collect();
if !futs.is_empty() {
tokio::spawn(futures::future::join_all(futs));

View file

@ -9,7 +9,7 @@ use yazi_macro::{act, succ};
use yazi_parser::{VoidOpt, mgr::{CdSource, SearchOpt, SearchOptVia}};
use yazi_plugin::external;
use yazi_proxy::{InputProxy, MgrProxy};
use yazi_shared::data::Data;
use yazi_shared::{data::Data, url::UrlLike};
use crate::{Actor, Ctx};

View file

@ -2,7 +2,7 @@ use anyhow::Result;
use yazi_dds::spark::SparkKind;
use yazi_macro::succ;
use yazi_parser::mgr::StashOpt;
use yazi_shared::{Source, data::Data, url::AsUrl};
use yazi_shared::{Source, data::Data, url::{AsUrl, UrlLike}};
use crate::{Actor, Ctx};
@ -14,7 +14,7 @@ impl Actor for Stash {
const NAME: &str = "stash";
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
if opt.target.is_regular() {
if opt.target.is_internal() {
cx.tab_mut().backstack.push(opt.target.as_url());
}

View file

@ -3,7 +3,7 @@ use yazi_core::tab::Tab;
use yazi_macro::{act, render, succ};
use yazi_parser::mgr::{CdSource, TabCreateOpt};
use yazi_proxy::AppProxy;
use yazi_shared::data::Data;
use yazi_shared::{data::Data, url::UrlLike};
use crate::{Actor, Ctx};

View file

@ -151,7 +151,7 @@ macro_rules! impl_file_fields {
($fields:ident) => {
$crate::cached_field!($fields, cha, |_, me| Ok($crate::Cha(me.cha)));
$crate::cached_field!($fields, url, |_, me| Ok($crate::Url::new(me.url_owned())));
$crate::cached_field!($fields, link_to, |_, me| Ok(me.link_to_url().map($crate::Url::new)));
$crate::cached_field!($fields, link_to, |_, me| Ok(me.link_to.as_ref().map($crate::Path::new)));
$crate::cached_field!($fields, name, |lua, me| {
me.name().map(|s| lua.create_string(s.encoded_bytes())).transpose()

View file

@ -9,7 +9,7 @@ use yazi_fs::{File, Files, FilesOp, cha::Cha};
use yazi_macro::render;
use yazi_parser::mgr::PreviewLock;
use yazi_plugin::{external::Highlighter, isolate};
use yazi_shared::{pool::Symbol, url::UrlBuf};
use yazi_shared::{pool::Symbol, url::{UrlBuf, UrlLike}};
use yazi_vfs::{VfsFiles, VfsFilesOp};
#[derive(Default)]

View file

@ -1,6 +1,6 @@
use std::{hash::{Hash, Hasher}, ops::Deref, path::Path};
use yazi_shared::{loc::Loc, path::{PathBufDyn, PathDyn, PathLike}, strand::Strand, url::{Url, UrlBuf, UrlLike}};
use yazi_shared::{path::{PathBufDyn, PathDyn}, strand::Strand, url::{UrlBuf, UrlLike}};
use crate::cha::{Cha, ChaType};
@ -47,23 +47,6 @@ impl File {
#[inline]
pub fn stem(&self) -> Option<Strand<'_>> { self.url.stem() }
pub fn link_to_url(&self) -> Option<Url<'_>> {
let to = self.link_to.as_ref()?;
let kind = self.url.kind();
Some(match &self.url {
UrlBuf::Regular(_) => Url::Regular(Loc::bare(to.as_os().ok()?)),
UrlBuf::Search { domain, .. } => {
Url::Search { loc: Loc::saturated(to.as_os().ok()?, kind), domain }
}
UrlBuf::Archive { domain, .. } => {
Url::Archive { loc: Loc::saturated(to.as_os().ok()?, kind), domain }
}
UrlBuf::Sftp { domain, .. } => {
Url::Sftp { loc: Loc::saturated(to.as_unix().ok()?, kind), domain }
}
})
}
}
impl Hash for File {

View file

@ -55,6 +55,7 @@ pub enum CdSource {
Reveal,
Enter,
Leave,
Follow,
Forward,
Back,
Escape,

View file

@ -63,9 +63,13 @@ end
function Tasks:icon(snap)
if snap.prog.kind == "FilePaste" then
return " "
return snap.name:find("Copy ", 1, true) == 1 and "" or " "
elseif snap.prog.kind == "FileDelete" then
return ""
elseif snap.prog.kind == "FileDownload" then
return ""
elseif snap.prog.kind == "FileUpload" then
return ""
else
return ""
end
@ -73,7 +77,7 @@ end
function Tasks:progress_redraw(snap, y)
local kind = snap.prog.kind
if kind == "FilePaste" or kind == "FileDelete" then
if kind == "FilePaste" or kind == "FileDelete" or kind == "FileDownload" or kind == "FileUpload" then
local percent
if snap.success then
percent = "Cleaning…"

View file

@ -3,7 +3,7 @@ use std::{borrow::Cow, fmt::{Debug, Formatter}, hash::{Hash, Hasher}, path::{Pat
use anyhow::Result;
use serde::{Deserialize, Serialize};
use crate::{loc::LocBuf, path::{PathBufDyn, PathDynError, SetNameError}, pool::{InternStr, Pool, Symbol}, scheme::{Scheme, SchemeKind}, strand::AsStrand, url::{AsUrl, Url, UrlCow, UrlLike}};
use crate::{loc::LocBuf, path::{PathBufDyn, PathDynError, SetNameError}, pool::{InternStr, Pool, Symbol}, scheme::Scheme, strand::AsStrand, url::{AsUrl, Url, UrlCow, UrlLike}};
#[derive(Clone, Eq)]
pub enum UrlBuf {
@ -171,10 +171,6 @@ impl UrlBuf {
}
impl UrlBuf {
// --- Regular
#[inline]
pub fn is_regular(&self) -> bool { self.as_url().is_regular() }
#[inline]
pub fn to_regular(&self) -> Result<Self, PathDynError> { Ok(self.as_url().as_regular()?.into()) }
@ -183,10 +179,6 @@ impl UrlBuf {
Ok(Self::Regular(self.into_loc().into_os()?.into()))
}
// --- Search
#[inline]
pub fn is_search(&self) -> bool { self.kind() == SchemeKind::Search }
#[inline]
pub fn to_search(&self, domain: impl AsRef<str>) -> Result<Self, PathDynError> {
Ok(Self::Search {
@ -202,20 +194,6 @@ impl UrlBuf {
domain: Pool::<str>::intern(domain),
})
}
// --- Archive
#[inline]
pub fn is_archive(&self) -> bool { self.kind() == SchemeKind::Archive }
// --- Internal
#[inline]
pub fn is_internal(&self) -> bool {
match self.kind() {
SchemeKind::Regular | SchemeKind::Sftp => true,
SchemeKind::Search => !self.uri().is_empty(),
SchemeKind::Archive => false,
}
}
}
impl Debug for UrlBuf {

View file

@ -249,11 +249,6 @@ impl<'a> UrlCow<'a> {
pub fn to_owned(&self) -> UrlBuf { self.as_url().into() }
}
impl UrlCow<'_> {
#[inline]
pub fn is_regular(&self) -> bool { self.as_url().is_regular() }
}
impl Serialize for UrlCow<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where

View file

@ -28,6 +28,14 @@ where
fn is_absolute(&self) -> bool { self.as_url().is_absolute() }
fn is_archive(&self) -> bool { self.as_url().is_archive() }
fn is_internal(&self) -> bool { self.as_url().is_internal() }
fn is_regular(&self) -> bool { self.as_url().is_regular() }
fn is_search(&self) -> bool { self.as_url().is_search() }
fn kind(&self) -> SchemeKind { self.as_url().kind() }
fn loc(&self) -> PathDyn<'_> { self.as_url().loc() }

View file

@ -112,6 +112,18 @@ impl<'a> Url<'a> {
#[inline]
pub fn is_absolute(self) -> bool { self.loc().is_absolute() }
#[inline]
pub fn is_archive(self) -> bool { matches!(self, Self::Archive { .. }) }
#[inline]
pub fn is_internal(self) -> bool {
match self {
Self::Regular(_) | Self::Sftp { .. } => true,
Self::Search { .. } => !self.uri().is_empty(),
Self::Archive { .. } => false,
}
}
#[inline]
pub fn is_regular(self) -> bool { matches!(self, Self::Regular(_)) }
@ -119,7 +131,7 @@ impl<'a> Url<'a> {
pub fn is_search(self) -> bool { matches!(self, Self::Search { .. }) }
#[inline]
pub fn kind(&self) -> SchemeKind {
pub fn kind(self) -> SchemeKind {
match self {
Self::Regular(_) => SchemeKind::Regular,
Self::Search { .. } => SchemeKind::Search,

View file

@ -38,7 +38,7 @@ impl VfsFiles for Files {
async fn from_dir_bulk(dir: &UrlBuf) -> std::io::Result<Vec<File>> {
let mut it = provider::read_dir(dir).await?;
let mut entries = Vec::with_capacity(5000);
let mut entries = Vec::new();
while let Ok(Some(entry)) = it.next().await {
entries.push(entry);
}