diff --git a/Cargo.lock b/Cargo.lock
index ed5798b3..5bc92796 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -243,9 +243,9 @@ dependencies = [
[[package]]
name = "bit_field"
-version = "0.10.2"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
+checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6"
[[package]]
name = "bitflags"
@@ -382,9 +382,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.45"
+version = "4.5.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
+checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57"
dependencies = [
"clap_builder",
"clap_derive",
@@ -392,9 +392,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.44"
+version = "4.5.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
+checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41"
dependencies = [
"anstream",
"anstyle",
@@ -895,6 +895,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+[[package]]
+name = "foldhash"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
+
[[package]]
name = "fsevent-sys"
version = "4.1.0"
@@ -1047,8 +1053,8 @@ dependencies = [
"aho-corasick",
"bstr",
"log",
- "regex-automata 0.4.9",
- "regex-syntax 0.8.5",
+ "regex-automata 0.4.10",
+ "regex-syntax 0.8.6",
]
[[package]]
@@ -1069,7 +1075,7 @@ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
- "foldhash",
+ "foldhash 0.1.5",
"serde",
]
@@ -1132,9 +1138,9 @@ dependencies = [
[[package]]
name = "image-webp"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6970fe7a5300b4b42e62c52efa0187540a5bef546c60edaf554ef595d2e6f0b"
+checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3"
dependencies = [
"byteorder-lite",
"quick-error",
@@ -1259,9 +1265,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jobserver"
-version = "0.1.33"
+version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
+checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
dependencies = [
"getrandom 0.3.3",
"libc",
@@ -1967,9 +1973,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quick-xml"
-version = "0.38.2"
+version = "0.38.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d200a41a7797e6461bd04e4e95c3347053a731c32c87f066f2f0dda22dbdbba8"
+checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89"
dependencies = [
"memchr",
]
@@ -2158,14 +2164,14 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.11.1"
+version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
dependencies = [
"aho-corasick",
"memchr",
- "regex-automata 0.4.9",
- "regex-syntax 0.8.5",
+ "regex-automata 0.4.10",
+ "regex-syntax 0.8.6",
]
[[package]]
@@ -2179,13 +2185,13 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.9"
+version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
dependencies = [
"aho-corasick",
"memchr",
- "regex-syntax 0.8.5",
+ "regex-syntax 0.8.6",
]
[[package]]
@@ -2196,9 +2202,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
[[package]]
name = "rgb"
@@ -2267,9 +2273,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "safe_arch"
-version = "0.7.4"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
+checksum = "3fb5032219cc30e5bb98749b19a18ceb2cf15e24ba8d517a7e64dff4f1f1eca5"
dependencies = [
"bytemuck",
]
@@ -2519,7 +2525,7 @@ dependencies = [
"once_cell",
"onig",
"plist",
- "regex-syntax 0.8.5",
+ "regex-syntax 0.8.6",
"serde",
"serde_derive",
"serde_json",
@@ -3127,9 +3133,9 @@ dependencies = [
[[package]]
name = "wide"
-version = "0.7.33"
+version = "0.7.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03"
+checksum = "5a0ab08c041f0cbb00a12fd091b2877dcec2311f90f87a88391d4b0961ffb4fe"
dependencies = [
"bytemuck",
"safe_arch",
@@ -3727,7 +3733,7 @@ dependencies = [
"bitflags 2.9.3",
"core-foundation-sys",
"dirs",
- "foldhash",
+ "foldhash 0.2.0",
"futures",
"hashbrown",
"libc",
@@ -3859,7 +3865,7 @@ version = "25.6.11"
dependencies = [
"anyhow",
"crossterm 0.29.0",
- "foldhash",
+ "foldhash 0.2.0",
"futures",
"hashbrown",
"libc",
diff --git a/Cargo.toml b/Cargo.toml
index 608016f3..0546eab2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,11 +24,11 @@ ansi-to-tui = "7.0.0"
anyhow = "1.0.99"
base64 = "0.22.1"
bitflags = { version = "2.9.3", features = [ "serde" ] }
-clap = { version = "4.5.45", features = [ "derive" ] }
+clap = { version = "4.5.46", features = [ "derive" ] }
core-foundation-sys = "0.8.7"
crossterm = { version = "0.29.0", features = [ "event-stream" ] }
dirs = "6.0.0"
-foldhash = "0.1.5"
+foldhash = "0.2.0"
futures = "0.3.31"
globset = "0.4.16"
hashbrown = { version = "0.15.5", features = [ "serde" ] }
@@ -41,7 +41,7 @@ ordered-float = { version = "5.0.0", features = [ "serde" ] }
parking_lot = "0.12.4"
paste = "1.0.15"
ratatui = { version = "0.29.0", features = [ "unstable-rendered-line-info" ] }
-regex = "1.11.1"
+regex = "1.11.2"
scopeguard = "1.2.0"
serde = { version = "1.0.219", features = [ "derive" ] }
serde_json = "1.0.143"
diff --git a/README.md b/README.md
index c0d0bab9..67b220ee 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,13 @@
@@ -52,25 +52,25 @@ Yazi is currently in heavy development, expect breaking changes.
## Image Preview
-| Platform | Protocol | Support |
-| ---------------------------------------------------------------------------- | -------------------------------------- | ----------------------------------------------------- |
-| [kitty](https://github.com/kovidgoyal/kitty) (>= 0.28.0) | [Kitty unicode placeholders][kgp] | ✅ Built-in |
-| [iTerm2](https://iterm2.com) | [Inline images protocol][iip] | ✅ Built-in |
-| [WezTerm](https://github.com/wez/wezterm) | [Inline images protocol][iip] | ✅ Built-in |
-| [Konsole](https://invent.kde.org/utilities/konsole) | [Kitty old protocol][kgp-old] | ✅ Built-in |
-| [foot](https://codeberg.org/dnkl/foot) | [Sixel graphics format][sixel] | ✅ Built-in |
-| [Ghostty](https://github.com/ghostty-org/ghostty) | [Kitty unicode placeholders][kgp] | ✅ Built-in |
-| [Windows Terminal](https://github.com/microsoft/terminal) (>= v1.22.10352.0) | [Sixel graphics format][sixel] | ✅ Built-in |
-| [st with Sixel patch](https://github.com/bakkeby/st-flexipatch) | [Sixel graphics format][sixel] | ✅ Built-in |
-| [Warp](https://www.warp.dev) (macOS/Linux only) | [Inline images protocol][iip] | ✅ Built-in |
-| [Tabby](https://github.com/Eugeny/tabby) | [Inline images protocol][iip] | ✅ Built-in |
-| [VSCode](https://github.com/microsoft/vscode) | [Inline images protocol][iip] | ✅ Built-in |
-| [Rio](https://github.com/raphamorim/rio) | [Inline images protocol][iip] | ✅ Built-in |
-| [Black Box](https://gitlab.gnome.org/raggesilver/blackbox) | [Sixel graphics format][sixel] | ✅ Built-in |
-| [Hyper](https://github.com/vercel/hyper) | [Inline images protocol][iip] | ✅ Built-in |
-| [Bobcat](https://github.com/ismail-yilmaz/Bobcat) | [Inline images protocol][iip] | ✅ Built-in |
-| X11 / Wayland | Window system protocol | ☑️ [Überzug++][ueberzug] required |
-| Fallback | [ASCII art (Unicode block)][ascii-art] | ☑️ [Chafa][chafa] required |
+| Platform | Protocol | Support |
+| ---------------------------------------------------------------------------- | -------------------------------------- | --------------------------------- |
+| [kitty](https://github.com/kovidgoyal/kitty) (>= 0.28.0) | [Kitty unicode placeholders][kgp] | ✅ Built-in |
+| [iTerm2](https://iterm2.com) | [Inline images protocol][iip] | ✅ Built-in |
+| [WezTerm](https://github.com/wez/wezterm) | [Inline images protocol][iip] | ✅ Built-in |
+| [Konsole](https://invent.kde.org/utilities/konsole) | [Kitty old protocol][kgp-old] | ✅ Built-in |
+| [foot](https://codeberg.org/dnkl/foot) | [Sixel graphics format][sixel] | ✅ Built-in |
+| [Ghostty](https://github.com/ghostty-org/ghostty) | [Kitty unicode placeholders][kgp] | ✅ Built-in |
+| [Windows Terminal](https://github.com/microsoft/terminal) (>= v1.22.10352.0) | [Sixel graphics format][sixel] | ✅ Built-in |
+| [st with Sixel patch](https://github.com/bakkeby/st-flexipatch) | [Sixel graphics format][sixel] | ✅ Built-in |
+| [Warp](https://www.warp.dev) (macOS/Linux only) | [Inline images protocol][iip] | ✅ Built-in |
+| [Tabby](https://github.com/Eugeny/tabby) | [Inline images protocol][iip] | ✅ Built-in |
+| [VSCode](https://github.com/microsoft/vscode) | [Inline images protocol][iip] | ✅ Built-in |
+| [Rio](https://github.com/raphamorim/rio) | [Inline images protocol][iip] | ✅ Built-in |
+| [Black Box](https://gitlab.gnome.org/raggesilver/blackbox) | [Sixel graphics format][sixel] | ✅ Built-in |
+| [Hyper](https://github.com/vercel/hyper) | [Inline images protocol][iip] | ✅ Built-in |
+| [Bobcat](https://github.com/ismail-yilmaz/Bobcat) | [Inline images protocol][iip] | ✅ Built-in |
+| X11 / Wayland | Window system protocol | ☑️ [Überzug++][ueberzug] required |
+| Fallback | [ASCII art (Unicode block)][ascii-art] | ☑️ [Chafa][chafa] required |
See https://yazi-rs.github.io/docs/image-preview for details.
diff --git a/flake.lock b/flake.lock
index 2f328745..98ef9989 100644
--- a/flake.lock
+++ b/flake.lock
@@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1752596105,
- "narHash": "sha256-lFNVsu/mHLq3q11MuGkMhUUoSXEdQjCHvpReaGP1S2k=",
+ "lastModified": 1756288264,
+ "narHash": "sha256-Om8adB1lfkU7D33VpR+/haZ2gI5r3Q+ZbIPzE5sYnwE=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "dab3a6e781554f965bde3def0aa2fda4eb8f1708",
+ "rev": "ddd1826f294a0ee5fdc198ab72c8306a0ea73aa9",
"type": "github"
},
"original": {
@@ -48,11 +48,11 @@
]
},
"locked": {
- "lastModified": 1752633862,
- "narHash": "sha256-Bj7ozT1+5P7NmvDcuAXJvj56txcXuAhk3Vd9FdWFQzk=",
+ "lastModified": 1756348497,
+ "narHash": "sha256-xJp3VnoYh4kpsaKFO/7SsGbwOz7pI1ZmjbqpXEuR2cw=",
"owner": "oxalica",
"repo": "rust-overlay",
- "rev": "8668ca94858206ac3db0860a9dec471de0d995f8",
+ "rev": "0adf92c70d23fb4f703aea5d3ebb51ac65994f7f",
"type": "github"
},
"original": {
diff --git a/yazi-actor/src/cmp/trigger.rs b/yazi-actor/src/cmp/trigger.rs
index 324fc60e..066a6f67 100644
--- a/yazi-actor/src/cmp/trigger.rs
+++ b/yazi-actor/src/cmp/trigger.rs
@@ -79,8 +79,10 @@ impl Trigger {
const SEP: char = std::path::MAIN_SEPARATOR;
Some(match path.as_os_str().rsplit_once(SEP) {
- Some((p, c)) if p.is_empty() => (UrlBuf { loc: MAIN_SEPARATOR_STR.into(), scheme }, c.into()),
- Some((p, c)) => (expand_url(UrlBuf { loc: p.into(), scheme }), c.into()),
+ Some((p, c)) if p.is_empty() => {
+ (UrlBuf { loc: MAIN_SEPARATOR_STR.into(), scheme: scheme.into() }, c.into())
+ }
+ Some((p, c)) => (expand_url(UrlBuf { loc: p.into(), scheme: scheme.into() }), c.into()),
None => (CWD.load().as_ref().clone(), path.into()),
})
}
diff --git a/yazi-actor/src/mgr/cd.rs b/yazi-actor/src/mgr/cd.rs
index 7b9a2160..8a623d81 100644
--- a/yazi-actor/src/mgr/cd.rs
+++ b/yazi-actor/src/mgr/cd.rs
@@ -53,7 +53,7 @@ impl Actor for Cd {
// Parent
if let Some(parent) = opt.target.parent() {
- tab.parent = Some(tab.history.remove_or(&parent));
+ tab.parent = Some(tab.history.remove_or(parent));
}
err!(Pubsub::pub_after_cd(tab.id, tab.cwd()));
diff --git a/yazi-actor/src/mgr/create.rs b/yazi-actor/src/mgr/create.rs
index 094e8007..d79341aa 100644
--- a/yazi-actor/src/mgr/create.rs
+++ b/yazi-actor/src/mgr/create.rs
@@ -53,7 +53,7 @@ impl Create {
FilesOp::Deleting(parent.into(), [urn.into()].into()).emit();
provider::create(&new).await?;
} else if let Some(parent) = new.parent() {
- provider::create_dir_all(&parent).await.ok();
+ provider::create_dir_all(parent).await.ok();
ok_or_not_found(provider::remove_file(&new).await)?;
provider::create(&new).await?;
} else {
diff --git a/yazi-actor/src/mgr/reveal.rs b/yazi-actor/src/mgr/reveal.rs
index 4619532d..c95d414b 100644
--- a/yazi-actor/src/mgr/reveal.rs
+++ b/yazi-actor/src/mgr/reveal.rs
@@ -17,7 +17,7 @@ impl Actor for Reveal {
let Some((parent, child)) = opt.target.pair() else { succ!() };
// Cd to the parent directory
- act!(mgr:cd, cx, (parent.clone(), opt.source))?;
+ act!(mgr:cd, cx, (parent, opt.source))?;
// Try to hover on the child file
let tab = cx.tab_mut();
diff --git a/yazi-binding/src/url.rs b/yazi-binding/src/url.rs
index 207ab075..4af92936 100644
--- a/yazi-binding/src/url.rs
+++ b/yazi-binding/src/url.rs
@@ -38,7 +38,9 @@ impl<'a> From<&'a Url> for yazi_shared::url::Url<'a> {
}
impl<'a> From<&'a Url> for UrlCow<'a> {
- fn from(value: &'a Url) -> Self { UrlCow::Borrowed(value.as_url()) }
+ fn from(value: &'a Url) -> Self {
+ UrlCow::Borrowed { loc: value.loc.as_loc(), scheme: value.scheme.as_ref().into() }
+ }
}
impl From for yazi_shared::url::UrlBufCov {
diff --git a/yazi-config/src/pattern.rs b/yazi-config/src/pattern.rs
index 8d59c716..016b9f3e 100644
--- a/yazi-config/src/pattern.rs
+++ b/yazi-config/src/pattern.rs
@@ -3,7 +3,7 @@ use std::str::FromStr;
use anyhow::Result;
use globset::GlobBuilder;
use serde::Deserialize;
-use yazi_shared::url::{Scheme, UrlBuf};
+use yazi_shared::{scheme::{SchemeCow, SchemeRef}, url::UrlBuf};
#[derive(Debug, Deserialize)]
#[serde(try_from = "String")]
@@ -108,14 +108,16 @@ impl PatternScheme {
};
if protocol != "*" {
- me.0 = Some(Scheme::parse_kind(protocol.as_bytes())?);
+ me.0 = Some(SchemeCow::parse_kind(protocol.as_bytes())?);
}
Ok((me, protocol.len() + 3))
}
#[inline]
- fn matches(&self, scheme: &Scheme) -> bool { self.0.is_none_or(|s| s == scheme.kind()) }
+ fn matches<'a>(&self, scheme: impl Into>) -> bool {
+ self.0.is_none_or(|s| s == scheme.into().kind())
+ }
}
// --- Tests
diff --git a/yazi-core/src/tab/selected.rs b/yazi-core/src/tab/selected.rs
index acb273e7..284c30b8 100644
--- a/yazi-core/src/tab/selected.rs
+++ b/yazi-core/src/tab/selected.rs
@@ -59,7 +59,7 @@ impl Selected {
let mut parent = urls[0].parent();
let mut parents = vec![];
while let Some(u) = parent {
- if self.inner.contains_key(&UrlCov::new(&u)) {
+ if self.inner.contains_key(&UrlCov::new(u)) {
return 0;
}
@@ -117,11 +117,11 @@ impl Selected {
// FIXME: use UrlCov::parent() instead
let mut parent = first.parent();
while let Some(u) = parent {
- let n = self.parents.get_mut(&UrlCov::new(&u)).unwrap();
+ let n = self.parents.get_mut(&UrlCov::new(u)).unwrap();
*n -= count;
if *n == 0 {
- self.parents.remove(&UrlCov::new(&u));
+ self.parents.remove(&UrlCov::new(u));
}
parent = u.parent();
@@ -147,14 +147,14 @@ impl Selected {
#[cfg(test)]
mod tests {
- use yazi_shared::url::UrlCow;
+ use yazi_shared::{scheme::SchemeCow, url::UrlCow};
use super::*;
fn url(s: &str) -> Url<'_> {
match UrlCow::try_from(s).unwrap() {
- UrlCow::Borrowed(url) => url,
- UrlCow::Owned(_) => unreachable!(),
+ UrlCow::Borrowed { loc, scheme: SchemeCow::Borrowed(scheme) } => Url { loc, scheme },
+ _ => unreachable!(),
}
}
@@ -275,16 +275,16 @@ mod tests {
let child1 = url("/parent/child1");
let child2 = url("/parent/child2");
let child3 = url("/parent/child3");
- assert_eq!(3, s.add_same([&child1, &child2, &child3]));
+ assert_eq!(3, s.add_same([child1, child2, child3]));
- assert!(s.remove(&child1));
+ assert!(s.remove(child1));
assert_eq!(s.inner.len(), 2);
assert!(!s.parents.is_empty());
- assert!(s.remove(&child2));
+ assert!(s.remove(child2));
assert!(!s.parents.is_empty());
- assert!(s.remove(&child3));
+ assert!(s.remove(child3));
assert!(s.inner.is_empty());
assert!(s.parents.is_empty());
}
diff --git a/yazi-fs/src/fns.rs b/yazi-fs/src/fns.rs
index 0f0ae499..92b0b963 100644
--- a/yazi-fs/src/fns.rs
+++ b/yazi-fs/src/fns.rs
@@ -172,7 +172,7 @@ pub fn max_common_root(urls: &[UrlBuf]) -> usize {
.components()
.zip(parent.components())
.take_while(|(a, b)| match (a, b) {
- (Component::Scheme(a), Component::Scheme(b)) => a.covariant(b),
+ (Component::Scheme(a), Component::Scheme(b)) => a.covariant(*b),
(a, b) => a == b,
})
.count()
diff --git a/yazi-fs/src/path/clean.rs b/yazi-fs/src/path/clean.rs
index 51e6ee4d..3d893d78 100644
--- a/yazi-fs/src/path/clean.rs
+++ b/yazi-fs/src/path/clean.rs
@@ -8,10 +8,7 @@ pub fn clean_url<'a>(url: impl Into>) -> UrlBuf {
clean_path_impl(&cow.loc(), cow.loc().base().count(), cow.loc().trail().count());
let loc = LocBuf::with(path, uri, urn).expect("Failed to create Loc from cleaned path");
- match cow {
- UrlCow::Borrowed(u) => UrlBuf { loc, scheme: u.scheme.clone() },
- UrlCow::Owned(u) => UrlBuf { loc, scheme: u.scheme },
- }
+ UrlBuf { loc, scheme: cow.into_scheme().into() }
}
fn clean_path_impl(path: &Path, base: usize, trail: usize) -> (PathBuf, usize, usize) {
diff --git a/yazi-fs/src/path/expand.rs b/yazi-fs/src/path/expand.rs
index be0dbb4b..e39860c4 100644
--- a/yazi-fs/src/path/expand.rs
+++ b/yazi-fs/src/path/expand.rs
@@ -29,10 +29,10 @@ fn expand_url_impl<'a>(url: Url<'a>) -> UrlCow<'a> {
)
.expect("Failed to create Loc from expanded path");
- let url = UrlBuf { loc, scheme: url.scheme.clone() };
+ let url = UrlBuf { loc, scheme: url.scheme.into() };
match absolute_url(url.as_url()) {
- UrlCow::Borrowed(_) => url.into(),
- UrlCow::Owned(u) => u.into(),
+ UrlCow::Borrowed { .. } => url.into(),
+ c @ UrlCow::Owned { .. } => c.into_owned().into(),
}
}
@@ -73,7 +73,7 @@ fn absolute_url<'a>(url: Url<'a>) -> UrlCow<'a> {
if url.has_trail() { 0 } else { 2 },
)
.expect("Failed to create Loc from drive letter");
- UrlBuf { loc, scheme: url.scheme.clone() }.into()
+ UrlBuf { loc, scheme: url.scheme.into() }.into()
} else if local
&& let Ok(rest) = url.loc.strip_prefix("~/")
&& let Some(home) = dirs::home_dir()
@@ -86,7 +86,7 @@ fn absolute_url<'a>(url: Url<'a>) -> UrlCow<'a> {
url.urn().count() + if url.has_trail() { 0 } else { add },
)
.expect("Failed to create Loc from home directory");
- UrlBuf { loc, scheme: url.scheme.clone() }.into()
+ UrlBuf { loc, scheme: url.scheme.into() }.into()
} else if !url.is_absolute() {
let cwd = CWD.load();
let loc = LocBuf::with(cwd.loc.join(url.loc), url.uri().count(), url.urn().count())
diff --git a/yazi-fs/src/path/relative.rs b/yazi-fs/src/path/relative.rs
index b6daf65d..72eaba9b 100644
--- a/yazi-fs/src/path/relative.rs
+++ b/yazi-fs/src/path/relative.rs
@@ -8,8 +8,8 @@ pub fn path_relative_to<'a>(
to: &'a impl AsRef,
) -> Result> {
Ok(match url_relative_to(Url::regular(&from).into(), Url::regular(to).into())? {
- UrlCow::Borrowed(url) => Cow::Borrowed(url.loc.as_path()),
- UrlCow::Owned(url) => Cow::Owned(url.loc.into_path()),
+ UrlCow::Borrowed { loc, .. } => Cow::Borrowed(loc.as_path()),
+ UrlCow::Owned { loc, .. } => Cow::Owned(loc.into_path()),
})
}
@@ -25,7 +25,7 @@ pub(super) fn url_relative_to<'a>(from: UrlCow<'_>, to: UrlCow<'a>) -> Result(from: UrlCow<'_>, to: UrlCow<'a>) -> Result PartialEq for Symbol {
impl Eq for Symbol {}
+impl PartialEq for Symbol {
+ fn eq(&self, other: &str) -> bool { self.as_ref() == other }
+}
+
+impl PartialEq<[u8]> for Symbol<[u8]> {
+ fn eq(&self, other: &[u8]) -> bool { self.as_ref() == other }
+}
+
// --- Hash
impl Hash for Symbol {
fn hash(&self, state: &mut H) { self.ptr.as_ptr().hash(state); }
diff --git a/yazi-shared/src/url/scheme.rs b/yazi-shared/src/scheme/cow.rs
similarity index 60%
rename from yazi-shared/src/url/scheme.rs
rename to yazi-shared/src/scheme/cow.rs
index 0a952384..e8798934 100644
--- a/yazi-shared/src/url/scheme.rs
+++ b/yazi-shared/src/scheme/cow.rs
@@ -3,45 +3,75 @@ use std::{borrow::Cow, ops::Not, path::Path};
use anyhow::{Result, bail, ensure};
use percent_encoding::percent_decode;
-use crate::{BytesExt, pool::{InternStr, Symbol}};
+use crate::{BytesExt, pool::InternStr, scheme::{Scheme, SchemeRef}};
-#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub enum Scheme {
- #[default]
- Regular,
-
- Search(Symbol),
-
- Archive(Symbol),
-
- Sftp(Symbol),
+#[derive(Debug)]
+pub enum SchemeCow<'a> {
+ Borrowed(SchemeRef<'a>),
+ Owned(Scheme),
}
-impl Scheme {
- #[inline]
- pub const fn kind(&self) -> &'static str {
- match self {
- Self::Regular => "regular",
- Self::Search(_) => "search",
- Self::Archive(_) => "archive",
- Self::Sftp(_) => "sftp",
+impl Default for SchemeCow<'_> {
+ fn default() -> Self { Self::Borrowed(SchemeRef::Regular) }
+}
+
+impl From for SchemeCow<'_> {
+ fn from(value: Scheme) -> Self { Self::Owned(value) }
+}
+
+impl<'a> From<&'a Scheme> for SchemeCow<'a> {
+ fn from(value: &'a Scheme) -> Self { Self::Borrowed(value.as_ref()) }
+}
+
+impl<'a> From> for SchemeCow<'a> {
+ fn from(value: SchemeRef<'a>) -> Self { Self::Borrowed(value) }
+}
+
+impl From> for Scheme {
+ fn from(value: SchemeCow<'_>) -> Self {
+ match value {
+ SchemeCow::Borrowed(s) => s.into(),
+ SchemeCow::Owned(s) => s,
+ }
+ }
+}
+
+impl<'a> SchemeCow<'a> {
+ pub fn search(domain: impl Into>) -> Self {
+ match domain.into() {
+ Cow::Borrowed(s) => SchemeRef::Search(s).into(),
+ Cow::Owned(s) => Scheme::Search(s.intern()).into(),
+ }
+ }
+
+ pub fn archive(domain: impl Into>) -> Self {
+ match domain.into() {
+ Cow::Borrowed(s) => SchemeRef::Archive(s).into(),
+ Cow::Owned(s) => Scheme::Archive(s.intern()).into(),
+ }
+ }
+
+ pub fn sftp(domain: impl Into>) -> Self {
+ match domain.into() {
+ Cow::Borrowed(s) => SchemeRef::Sftp(s).into(),
+ Cow::Owned(s) => Scheme::Sftp(s.intern()).into(),
}
}
#[inline]
- pub fn domain(&self) -> Option<&str> {
+ pub fn as_ref(&self) -> SchemeRef<'_> {
match self {
- Self::Regular => None,
- Self::Search(s) | Self::Archive(s) | Self::Sftp(s) => Some(s),
+ Self::Borrowed(s) => *s,
+ Self::Owned(s) => s.into(),
}
}
- pub(super) fn parse(
- bytes: &[u8],
+ pub(crate) fn parse(
+ bytes: &'a [u8],
skip: &mut usize,
) -> Result<(Self, bool, Option, Option)> {
let Some((mut protocol, rest)) = bytes.split_by_seq(b"://") else {
- return Ok((Self::Regular, false, None, None));
+ return Ok((Self::default(), false, None, None));
};
// Advance to the beginning of the path
@@ -54,18 +84,18 @@ impl Scheme {
}
let (scheme, uri, urn) = match protocol {
- b"regular" => (Self::Regular, None, None),
+ b"regular" => (Self::default(), None, None),
b"search" => {
let (domain, uri, urn) = Self::decode_param(rest, skip)?;
- (Self::Search(domain), uri, urn)
+ (Self::search(domain), uri, urn)
}
b"archive" => {
let (domain, uri, urn) = Self::decode_param(rest, skip)?;
- (Self::Archive(domain), uri, urn)
+ (Self::archive(domain), uri, urn)
}
b"sftp" => {
let (domain, uri, urn) = Self::decode_param(rest, skip)?;
- (Self::Sftp(domain), uri, urn)
+ (Self::sftp(domain), uri, urn)
}
_ => bail!("Could not parse protocol from URL: {}", String::from_utf8_lossy(bytes)),
};
@@ -84,31 +114,18 @@ impl Scheme {
}
}
- #[inline]
- pub fn covariant(&self, other: &Self) -> bool {
- if self.is_virtual() || other.is_virtual() { self == other } else { true }
- }
-
- #[inline]
- pub fn is_virtual(&self) -> bool {
- match self {
- Self::Regular | Self::Search(_) => false,
- Self::Archive(_) | Self::Sftp(_) => true,
- }
- }
-
fn decode_param(
- bytes: &[u8],
+ bytes: &'a [u8],
skip: &mut usize,
- ) -> Result<(Symbol, Option, Option)> {
+ ) -> Result<(Cow<'a, str>, Option, Option)> {
let mut len = bytes.iter().copied().take_while(|&b| b != b'/').count();
let slash = bytes.get(len).is_some_and(|&b| b == b'/');
*skip += len + slash as usize;
let (uri, urn) = Self::decode_ports(&bytes[..len], &mut len)?;
let domain = match Cow::from(percent_decode(&bytes[..len])) {
- Cow::Borrowed(b) => str::from_utf8(b)?.intern(),
- Cow::Owned(b) => String::from_utf8(b)?.intern(),
+ Cow::Borrowed(b) => str::from_utf8(b)?.into(),
+ Cow::Owned(b) => String::from_utf8(b)?.into(),
};
Ok((domain, uri, urn))
@@ -131,24 +148,24 @@ impl Scheme {
Ok((b, a))
}
- pub(super) fn normalize_ports(
+ pub(crate) fn normalize_ports(
&self,
uri: Option,
urn: Option,
path: &Path,
) -> Result