mirror of
https://github.com/sxyazi/yazi.git
synced 2026-05-13 08:16:40 +00:00
feat: expose stash action and give it a new search source (#3872)
This commit is contained in:
parent
f6408656b4
commit
74d903a49a
55 changed files with 471 additions and 274 deletions
88
Cargo.lock
generated
88
Cargo.lock
generated
|
|
@ -588,9 +588,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.59"
|
||||
version = "1.2.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283"
|
||||
checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
|
|
@ -1365,9 +1365,9 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
|||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.14.0-rc.29"
|
||||
version = "0.14.0-rc.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e84043d573efd4ac9d2d125817979a379204bf7e328b25a4a30487e8d100e618"
|
||||
checksum = "7d7a0bfd012613a7bcfe02cbfccf2b846e9ef9e1bccb641c48d461253cfb034d"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"crypto-bigint",
|
||||
|
|
@ -1793,9 +1793,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.14.1"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e"
|
||||
checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159"
|
||||
dependencies = [
|
||||
"color_quant",
|
||||
"weezl",
|
||||
|
|
@ -1851,6 +1851,17 @@ name = "hashbrown"
|
|||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
"foldhash 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
|
|
@ -2010,12 +2021,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.13.1"
|
||||
version = "2.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff"
|
||||
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
|
@ -2279,9 +2290,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
|||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.15"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08"
|
||||
checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
@ -3176,7 +3187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"indexmap 2.13.1",
|
||||
"indexmap 2.14.0",
|
||||
"quick-xml",
|
||||
"serde",
|
||||
"time",
|
||||
|
|
@ -4103,7 +4114,7 @@ dependencies = [
|
|||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.13.1",
|
||||
"indexmap 2.14.0",
|
||||
"schemars 0.9.0",
|
||||
"schemars 1.2.1",
|
||||
"serde_core",
|
||||
|
|
@ -4667,9 +4678,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.51.0"
|
||||
version = "1.51.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd"
|
||||
checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
|
|
@ -4723,7 +4734,7 @@ version = "1.1.2+spec-1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
|
||||
dependencies = [
|
||||
"indexmap 2.13.1",
|
||||
"indexmap 2.14.0",
|
||||
"serde_core",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
|
|
@ -5153,7 +5164,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indexmap 2.13.1",
|
||||
"indexmap 2.14.0",
|
||||
"wasm-encoder",
|
||||
"wasmparser",
|
||||
]
|
||||
|
|
@ -5166,7 +5177,7 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
|||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"hashbrown 0.15.5",
|
||||
"indexmap 2.13.1",
|
||||
"indexmap 2.14.0",
|
||||
"semver",
|
||||
]
|
||||
|
||||
|
|
@ -5662,7 +5673,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"heck",
|
||||
"indexmap 2.13.1",
|
||||
"indexmap 2.14.0",
|
||||
"prettyplease",
|
||||
"syn 2.0.117",
|
||||
"wasm-metadata",
|
||||
|
|
@ -5693,7 +5704,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.11.0",
|
||||
"indexmap 2.13.1",
|
||||
"indexmap 2.14.0",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
|
@ -5712,7 +5723,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"id-arena",
|
||||
"indexmap 2.13.1",
|
||||
"indexmap 2.14.0",
|
||||
"log",
|
||||
"semver",
|
||||
"serde",
|
||||
|
|
@ -5745,7 +5756,7 @@ dependencies = [
|
|||
"crossterm 0.29.0",
|
||||
"either",
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"libc",
|
||||
"mlua",
|
||||
"paste",
|
||||
|
|
@ -5809,7 +5820,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"crossterm 0.29.0",
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"libc",
|
||||
"mlua",
|
||||
"paste",
|
||||
|
|
@ -5840,7 +5851,7 @@ dependencies = [
|
|||
"clap_complete_fig",
|
||||
"clap_complete_nushell",
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"regex",
|
||||
"vergen-gitcl",
|
||||
"yazi-adapter",
|
||||
|
|
@ -5869,7 +5880,7 @@ dependencies = [
|
|||
"clap_complete_fig",
|
||||
"clap_complete_nushell",
|
||||
"crossterm 0.29.0",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
|
|
@ -5900,8 +5911,8 @@ dependencies = [
|
|||
"bitflags 2.11.0",
|
||||
"crossterm 0.29.0",
|
||||
"globset",
|
||||
"hashbrown 0.16.1",
|
||||
"indexmap 2.13.1",
|
||||
"hashbrown 0.17.0",
|
||||
"indexmap 2.14.0",
|
||||
"ratatui",
|
||||
"regex",
|
||||
"serde",
|
||||
|
|
@ -5923,8 +5934,8 @@ dependencies = [
|
|||
"anyhow",
|
||||
"crossterm 0.29.0",
|
||||
"dyn-clone",
|
||||
"hashbrown 0.16.1",
|
||||
"indexmap 2.13.1",
|
||||
"hashbrown 0.17.0",
|
||||
"indexmap 2.14.0",
|
||||
"mlua",
|
||||
"parking_lot",
|
||||
"ratatui",
|
||||
|
|
@ -5959,8 +5970,8 @@ name = "yazi-dds"
|
|||
version = "26.2.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hashbrown 0.16.1",
|
||||
"indexmap 2.13.1",
|
||||
"hashbrown 0.17.0",
|
||||
"indexmap 2.14.0",
|
||||
"mlua",
|
||||
"ordered-float 5.3.0",
|
||||
"parking_lot",
|
||||
|
|
@ -6060,7 +6071,7 @@ dependencies = [
|
|||
"dirs",
|
||||
"either",
|
||||
"foldhash 0.2.0",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"libc",
|
||||
"objc2",
|
||||
"parking_lot",
|
||||
|
|
@ -6097,7 +6108,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"bitflags 2.11.0",
|
||||
"crossterm 0.29.0",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"mlua",
|
||||
"paste",
|
||||
"ratatui",
|
||||
|
|
@ -6172,6 +6183,7 @@ dependencies = [
|
|||
"yazi-macro",
|
||||
"yazi-scheduler",
|
||||
"yazi-shared",
|
||||
"yazi-shim",
|
||||
"yazi-widgets",
|
||||
]
|
||||
|
||||
|
|
@ -6180,7 +6192,7 @@ name = "yazi-runner"
|
|||
version = "26.2.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"mlua",
|
||||
"parking_lot",
|
||||
"thiserror 2.0.18",
|
||||
|
|
@ -6203,7 +6215,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"async-priority-channel",
|
||||
"foldhash 0.2.0",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"libc",
|
||||
"lru",
|
||||
"mlua",
|
||||
|
|
@ -6245,7 +6257,7 @@ dependencies = [
|
|||
"dyn-clone",
|
||||
"foldhash 0.2.0",
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"libc",
|
||||
"memchr",
|
||||
"ordered-float 5.3.0",
|
||||
|
|
@ -6311,7 +6323,7 @@ dependencies = [
|
|||
"deadpool",
|
||||
"either",
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"parking_lot",
|
||||
"russh",
|
||||
"tokio",
|
||||
|
|
@ -6329,7 +6341,7 @@ name = "yazi-watcher"
|
|||
version = "26.2.2"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"notify",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ either = { version = "1.15.0" }
|
|||
foldhash = "0.2.0"
|
||||
futures = "0.3.32"
|
||||
globset = "0.4.18"
|
||||
hashbrown = { version = "0.16.1", features = [ "serde" ] }
|
||||
indexmap = { version = "2.13.1", features = [ "serde" ] }
|
||||
hashbrown = { version = "0.17.0", features = [ "serde" ] }
|
||||
indexmap = { version = "2.14.0", features = [ "serde" ] }
|
||||
libc = "0.2.184"
|
||||
lru = "0.16.3"
|
||||
mlua = { version = "0.11.6", features = [ "anyhow", "async", "error-send", "lua55", "macros", "serde" ] }
|
||||
|
|
@ -71,7 +71,7 @@ serde_with = "3.18.0"
|
|||
strum = { version = "0.28.0", features = [ "derive" ] }
|
||||
syntect = { version = "5.3.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
||||
thiserror = "2.0.18"
|
||||
tokio = { version = "1.51.0", features = [ "full" ] }
|
||||
tokio = { version = "1.51.1", features = [ "full" ] }
|
||||
tokio-stream = "0.1.18"
|
||||
tokio-util = "0.7.18"
|
||||
toml = { version = "1.1.2" }
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use anyhow::Result;
|
||||
use yazi_actor::Ctx;
|
||||
use yazi_boot::BOOT;
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::{VoidForm, mgr::CdSource};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::{data::Data, strand::StrandLike, url::UrlLike};
|
||||
|
||||
use crate::Actor;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::{VoidForm, mgr::CdSource};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use anyhow::Result;
|
|||
use tokio::pin;
|
||||
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
|
||||
use yazi_config::popup::InputCfg;
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_fs::{File, FilesOp, path::{clean_url, expand_url}};
|
||||
use yazi_macro::{act, err, render, succ};
|
||||
|
|
@ -26,14 +27,15 @@ impl Actor for Cd {
|
|||
act!(mgr:escape_visual, cx)?;
|
||||
if form.interactive {
|
||||
return Self::cd_interactive(cx);
|
||||
}
|
||||
|
||||
let tab = cx.tab_mut();
|
||||
if form.target == *tab.cwd() {
|
||||
} else if form.target == *cx.cwd() {
|
||||
succ!();
|
||||
}
|
||||
|
||||
// Stash first so it's possible to access the original cwd in hooks
|
||||
act!(mgr:stash, cx, &form).ok();
|
||||
|
||||
// Take parent to history
|
||||
let tab = cx.tab_mut();
|
||||
if let Some(t) = tab.parent.take() {
|
||||
tab.history.insert(t.url.clone(), t);
|
||||
}
|
||||
|
|
@ -54,7 +56,6 @@ impl Actor for Cd {
|
|||
act!(mgr:sort, cx).ok();
|
||||
act!(mgr:hover, cx)?;
|
||||
act!(mgr:refresh, cx)?;
|
||||
act!(mgr:stash, cx, form).ok();
|
||||
act!(app:title, cx).ok();
|
||||
succ!(render!());
|
||||
}
|
||||
|
|
@ -77,7 +78,7 @@ impl Cd {
|
|||
|
||||
let Ok(file) = File::new(&url).await else { return };
|
||||
if file.is_dir() {
|
||||
return MgrProxy::cd(&url);
|
||||
return MgrProxy::cd(&url, CdSource::Cd);
|
||||
}
|
||||
|
||||
if let Some(p) = url.parent() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use anyhow::{Result, bail};
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_fs::FilesOp;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::mgr::{CdSource, DisplaceDoForm};
|
||||
use yazi_parser::mgr::DisplaceDoForm;
|
||||
use yazi_shared::{data::Data, url::UrlLike};
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::{VoidForm, mgr::CdSource};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::{data::Data, url::UrlLike};
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_fs::path::clean_url;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::{VoidForm, mgr::CdSource};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::{data::Data, url::UrlLike};
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::{VoidForm, mgr::CdSource};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::{VoidForm, mgr::CdSource};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::{data::Data, url::UrlLike};
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ use anyhow::Result;
|
|||
use tokio::pin;
|
||||
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
|
||||
use yazi_config::popup::InputCfg;
|
||||
use yazi_core::mgr::SearchVia;
|
||||
use yazi_core::mgr::{CdSource, SearchVia};
|
||||
use yazi_fs::{FilesOp, cha::Cha};
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::{VoidForm, mgr::{CdSource, SearchForm}};
|
||||
use yazi_parser::{VoidForm, mgr::SearchForm};
|
||||
use yazi_plugin::external;
|
||||
use yazi_proxy::{InputProxy, MgrProxy};
|
||||
use yazi_scheduler::NotifyProxy;
|
||||
|
|
@ -85,7 +85,7 @@ impl Actor for SearchDo {
|
|||
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(5000, Duration::from_millis(500));
|
||||
pin!(rx);
|
||||
|
||||
let ((), ticket) = (MgrProxy::cd(&cwd), FilesOp::prepare(&cwd));
|
||||
let ((), ticket) = (MgrProxy::cd(&cwd, CdSource::Search), FilesOp::prepare(&cwd));
|
||||
while let Some(chunk) = rx.next().await {
|
||||
FilesOp::Part(cwd.clone(), chunk, ticket).emit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::tab::Tab;
|
||||
use yazi_core::{mgr::CdSource, tab::Tab};
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::mgr::{CdSource, TabCreateForm};
|
||||
use yazi_parser::mgr::TabCreateForm;
|
||||
use yazi_scheduler::NotifyProxy;
|
||||
use yazi_shared::{data::Data, url::UrlLike};
|
||||
|
||||
|
|
@ -25,8 +25,8 @@ impl Actor for TabCreate {
|
|||
}
|
||||
|
||||
let mut tab = Tab::default();
|
||||
let (cd, url) = if let Some(wd) = form.url {
|
||||
(true, wd.into_owned())
|
||||
let (cd, url) = if let Some(target) = form.target {
|
||||
(true, target)
|
||||
} else if let Some(h) = cx.hovered() {
|
||||
tab.pref = cx.tab().pref.clone();
|
||||
(false, h.url.clone())
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use yazi_core::tab::Folder;
|
|||
use yazi_fs::FilesOp;
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::mgr::UpdateFilesForm;
|
||||
use yazi_shared::{data::Data, url::UrlLike};
|
||||
use yazi_shared::{data::Data, url::{UrlLike, UrlMapExt}};
|
||||
use yazi_watcher::local::LINKED;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
|
@ -87,7 +87,7 @@ impl UpdateFiles {
|
|||
|
||||
fn update_hovered(cx: &mut Ctx, op: FilesOp) -> Result<Data> {
|
||||
let (id, url) = (cx.tab().id, op.cwd());
|
||||
let folder = cx.tab_mut().history.entry_ref(url).or_insert_with(|| Folder::from(url));
|
||||
let folder = cx.tab_mut().history.get_or_insert_with(url, |u| Folder::from(u));
|
||||
|
||||
if folder.update_pub(id, op) {
|
||||
act!(mgr:peek, cx, true)?;
|
||||
|
|
@ -101,15 +101,11 @@ impl UpdateFiles {
|
|||
|(p, n)| matches!(op, FilesOp::Deleting(ref parent, ref urns) if *parent == p && urns.contains(&n)),
|
||||
);
|
||||
|
||||
tab
|
||||
.history
|
||||
.entry_ref(op.cwd())
|
||||
.or_insert_with(|| Folder::from(op.cwd()))
|
||||
.update_pub(tab.id, op);
|
||||
|
||||
tab.history.get_or_insert_with(op.cwd(), |u| Folder::from(u)).update_pub(tab.id, op);
|
||||
if leave {
|
||||
act!(mgr:leave, cx)?;
|
||||
}
|
||||
|
||||
succ!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{collections::VecDeque, mem};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use hashbrown::{HashMap, hash_map::EntryRef};
|
||||
use hashbrown::HashMap;
|
||||
use mlua::Function;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
|
@ -49,15 +49,9 @@ impl Runtime {
|
|||
|
||||
pub fn put_block(&mut self, f: &Function) -> Option<usize> {
|
||||
let cur = self.frames.back().filter(|f| f.id != "init")?;
|
||||
Some(match self.blocks.entry_ref(&cur.id) {
|
||||
EntryRef::Occupied(mut oe) => {
|
||||
oe.get_mut().push(f.clone());
|
||||
oe.get().len() - 1
|
||||
}
|
||||
EntryRef::Vacant(ve) => {
|
||||
ve.insert(vec![f.clone()]);
|
||||
0
|
||||
}
|
||||
})
|
||||
let blocks = self.blocks.entry_ref(&cur.id).or_default();
|
||||
|
||||
blocks.push(f.clone());
|
||||
Some(blocks.len() - 1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use serde::Deserialize;
|
|||
use yazi_shared::{Layer, Source, event::Action};
|
||||
|
||||
use super::Key;
|
||||
use crate::Platform;
|
||||
|
||||
static RE: OnceLock<Regex> = OnceLock::new();
|
||||
|
||||
|
|
@ -16,7 +17,8 @@ pub struct Chord {
|
|||
#[serde(deserialize_with = "super::deserialize_run")]
|
||||
pub run: Vec<Action>,
|
||||
pub desc: Option<String>,
|
||||
pub r#for: Option<String>,
|
||||
#[serde(default)]
|
||||
pub r#for: Platform,
|
||||
}
|
||||
|
||||
impl PartialEq for Chord {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::ops::Deref;
|
|||
use yazi_shared::event::ActionCow;
|
||||
|
||||
use super::Chord;
|
||||
use crate::Platform;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ChordCow {
|
||||
|
|
@ -31,7 +32,7 @@ impl Deref for ChordCow {
|
|||
|
||||
impl Default for ChordCow {
|
||||
fn default() -> Self {
|
||||
const C: &Chord = &Chord { on: vec![], run: vec![], desc: None, r#for: None };
|
||||
const C: &Chord = &Chord { on: vec![], run: vec![], desc: None, r#for: Platform::All };
|
||||
Self::Borrowed(C)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use yazi_codegen::DeserializeOver2;
|
|||
use yazi_shared::Layer;
|
||||
|
||||
use super::Chord;
|
||||
use crate::{Preset, check_for, keymap::Key};
|
||||
use crate::{Preset, keymap::Key};
|
||||
|
||||
#[derive(Default, Deserialize, DeserializeOver2)]
|
||||
pub struct KeymapRules {
|
||||
|
|
@ -39,9 +39,8 @@ impl KeymapRules {
|
|||
self.keymap.into_iter().filter(|v| !a_seen.contains(&on(v))),
|
||||
self.append_keymap.into_iter().filter(|v| !b_seen.contains(&on(v))),
|
||||
)
|
||||
.map(|mut chord| (chord.r#for.take(), chord))
|
||||
.filter(|(r#for, chord)| !chord.noop() && check_for(r#for.as_deref()))
|
||||
.map(|(_, chord)| chord.reshape(layer))
|
||||
.filter(|chord| !chord.noop() && chord.r#for.matches())
|
||||
.map(|chord| chord.reshape(layer))
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
Ok(Self { keymap, ..Default::default() })
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use toml::{Spanned, de::DeTable};
|
|||
use yazi_codegen::DeserializeOver;
|
||||
|
||||
use super::OpenerRule;
|
||||
use crate::check_for;
|
||||
|
||||
#[derive(Debug, Deserialize, DeserializeOver)]
|
||||
pub struct Opener(HashMap<String, Vec<OpenerRule>>);
|
||||
|
|
@ -47,9 +46,8 @@ impl Opener {
|
|||
for rules in self.0.values_mut() {
|
||||
*rules = mem::take(rules)
|
||||
.into_iter()
|
||||
.map(|mut r| (r.r#for.take(), r))
|
||||
.filter(|(r#for, _)| check_for(r#for.as_deref()))
|
||||
.map(|(_, r)| r.reshape())
|
||||
.filter(|r| r.r#for.matches())
|
||||
.map(|r| r.reshape())
|
||||
.collect::<Result<IndexSet<_>>>()?
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ use anyhow::{Result, bail};
|
|||
use serde::Deserialize;
|
||||
use yazi_fs::Splatter;
|
||||
|
||||
use crate::Platform;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct OpenerRule {
|
||||
pub run: String,
|
||||
|
|
@ -11,7 +13,8 @@ pub struct OpenerRule {
|
|||
pub orphan: bool,
|
||||
#[serde(default)]
|
||||
pub desc: String,
|
||||
pub r#for: Option<String>,
|
||||
#[serde(default)]
|
||||
pub r#for: Platform,
|
||||
#[serde(skip)]
|
||||
pub spread: bool,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,26 @@
|
|||
#[inline]
|
||||
pub(crate) fn check_for(r#for: Option<&str>) -> bool {
|
||||
match r#for.as_ref().map(|s| s.as_ref()) {
|
||||
Some("unix") if cfg!(unix) => true,
|
||||
Some(os) if os == std::env::consts::OS => true,
|
||||
Some(_) => false,
|
||||
None => true,
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum Platform {
|
||||
#[default]
|
||||
All,
|
||||
Linux,
|
||||
Macos,
|
||||
Windows,
|
||||
Android,
|
||||
Unix,
|
||||
}
|
||||
|
||||
impl Platform {
|
||||
pub(crate) fn matches(self) -> bool {
|
||||
match self {
|
||||
Self::All => true,
|
||||
Self::Linux => cfg!(target_os = "linux"),
|
||||
Self::Macos => cfg!(target_os = "macos"),
|
||||
Self::Windows => cfg!(windows),
|
||||
Self::Android => cfg!(target_os = "android"),
|
||||
Self::Unix => cfg!(unix),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
24
yazi-core/src/mgr/cd.rs
Normal file
24
yazi-core/src/mgr/cd.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use strum::IntoStaticStr;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, IntoStaticStr, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[strum(serialize_all = "kebab-case")]
|
||||
pub enum CdSource {
|
||||
#[default]
|
||||
Cd,
|
||||
Reveal,
|
||||
|
||||
Enter,
|
||||
Leave,
|
||||
|
||||
Follow,
|
||||
Search,
|
||||
Escape,
|
||||
|
||||
Forward,
|
||||
Back,
|
||||
|
||||
Tab,
|
||||
Displace,
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(batcher displace filter find mgr mimetype open search tabs yanked);
|
||||
yazi_macro::mod_flat!(batcher cd displace filter find mgr mimetype open search tabs yanked);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::ops::Deref;
|
|||
use hashbrown::HashMap;
|
||||
use indexmap::IndexMap;
|
||||
use yazi_fs::FilesOp;
|
||||
use yazi_shared::{timestamp_us, url::{Url, UrlBuf, UrlBufCov, UrlCov}};
|
||||
use yazi_shared::{timestamp_us, url::{Url, UrlBuf, UrlBufCov, UrlCov, UrlCovMapExt}};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Selected {
|
||||
|
|
@ -66,7 +66,7 @@ impl Selected {
|
|||
self.inner.extend(urls.iter().enumerate().map(|(i, u)| (u.into(), now + i as u64)));
|
||||
|
||||
for u in parents {
|
||||
*self.parents.entry_ref(&UrlCov::new(u)).or_default() += self.inner.len() - len;
|
||||
*self.parents.get_or_insert_default(UrlCov::new(u)) += self.inner.len() - len;
|
||||
}
|
||||
urls.len()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,39 @@
|
|||
use yazi_scheduler::plugin::PluginInEntry;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use yazi_scheduler::{TaskIn, plugin::PluginInEntry};
|
||||
use yazi_shared::{Id, SStr};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum TaskOpt {
|
||||
Plugin(PluginInEntry),
|
||||
}
|
||||
|
||||
impl TaskIn for TaskOpt {
|
||||
type Prog = ();
|
||||
|
||||
fn id(&self) -> Id {
|
||||
match self {
|
||||
Self::Plugin(r#in) => r#in.id(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: Id) -> &mut Self {
|
||||
match self {
|
||||
Self::Plugin(r#in) => _ = r#in.set_id(id),
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn title(&self) -> Cow<'_, str> {
|
||||
match self {
|
||||
Self::Plugin(r#in) => r#in.title(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_title(&mut self, title: impl Into<SStr>) -> &mut Self {
|
||||
match self {
|
||||
Self::Plugin(r#in) => _ = r#in.set_title(title),
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ impl<'a> Executor<'a> {
|
|||
on!(forward);
|
||||
on!(reveal);
|
||||
on!(follow);
|
||||
on!(stash);
|
||||
|
||||
// Toggle
|
||||
on!(toggle);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::path::Path;
|
|||
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use yazi_macro::relay;
|
||||
use yazi_shared::{Id, Ids, path::PathBufDyn, url::{UrlBuf, UrlLike}};
|
||||
use yazi_shared::{Id, Ids, path::PathBufDyn, url::{UrlBuf, UrlLike, UrlMapExt}};
|
||||
|
||||
use super::File;
|
||||
use crate::{cha::Cha, error::Error};
|
||||
|
|
@ -52,15 +52,15 @@ impl FilesOp {
|
|||
}
|
||||
|
||||
pub fn rename(map: HashMap<UrlBuf, File>) {
|
||||
let mut parents: HashMap<_, (HashSet<_>, HashMap<_, _>)> = Default::default();
|
||||
let mut parents: HashMap<UrlBuf, (HashSet<_>, HashMap<_, _>)> = Default::default();
|
||||
for (o, n) in map {
|
||||
let Some(o_p) = o.parent() else { continue };
|
||||
let Some(n_p) = n.url.parent() else { continue };
|
||||
if o_p == n_p {
|
||||
parents.entry_ref(&o_p).or_default().1.insert(o.urn().into(), n);
|
||||
parents.get_or_insert_default(o_p).1.insert(o.urn().into(), n);
|
||||
} else {
|
||||
parents.entry_ref(&o_p).or_default().0.insert(o.urn().into());
|
||||
parents.entry_ref(&n_p).or_default().1.insert(n.urn().into(), n);
|
||||
parents.get_or_insert_default(o_p).0.insert(o.urn().into());
|
||||
parents.get_or_insert_default(n_p).1.insert(n.urn().into(), n);
|
||||
}
|
||||
}
|
||||
for (p, (o, n)) in parents {
|
||||
|
|
|
|||
|
|
@ -1,41 +1,46 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::Deserialize;
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_fs::path::{clean_url, expand_url};
|
||||
use yazi_shared::{event::ActionCow, url::{Url, UrlBuf}};
|
||||
use yazi_vfs::provider;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct CdForm {
|
||||
#[serde(alias = "0")]
|
||||
pub target: UrlBuf,
|
||||
#[serde(default)]
|
||||
pub interactive: bool,
|
||||
#[serde(default)]
|
||||
pub raw: bool,
|
||||
#[serde(default)]
|
||||
pub source: CdSource,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for CdForm {
|
||||
fn from(mut a: ActionCow) -> Self {
|
||||
let mut target = a.take_first().unwrap_or_default();
|
||||
impl TryFrom<ActionCow> for CdForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
if !a.bool("raw") {
|
||||
target = expand_url(target);
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> {
|
||||
let mut me: Self = a.deserialize()?;
|
||||
|
||||
if !me.raw {
|
||||
me.target = expand_url(me.target).into_owned();
|
||||
}
|
||||
|
||||
if let Some(u) = provider::try_absolute(&target)
|
||||
if let Some(u) = provider::try_absolute(&me.target)
|
||||
&& u.is_owned()
|
||||
{
|
||||
target = u.into_static();
|
||||
me.target = u.into_owned();
|
||||
}
|
||||
|
||||
Self {
|
||||
target: clean_url(target),
|
||||
interactive: a.bool("interactive"),
|
||||
source: CdSource::Cd,
|
||||
}
|
||||
me.target = clean_url(me.target);
|
||||
Ok(me)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(UrlBuf, CdSource)> for CdForm {
|
||||
fn from((target, source): (UrlBuf, CdSource)) -> Self {
|
||||
Self { target, interactive: false, source }
|
||||
Self { target, interactive: false, raw: false, source }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,19 +55,3 @@ impl FromLua for CdForm {
|
|||
impl IntoLua for CdForm {
|
||||
fn into_lua(self, _: &Lua) -> mlua::Result<Value> { Err("unsupported".into_lua_err()) }
|
||||
}
|
||||
|
||||
// --- Source
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum CdSource {
|
||||
Tab,
|
||||
Cd,
|
||||
Reveal,
|
||||
Enter,
|
||||
Leave,
|
||||
Follow,
|
||||
Forward,
|
||||
Back,
|
||||
Escape,
|
||||
Displace,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,21 +5,20 @@ use serde::Deserialize;
|
|||
use strum::EnumString;
|
||||
use yazi_shared::{SStr, event::ActionCow, strand::AsStrand};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct CopyForm {
|
||||
#[serde(alias = "0")]
|
||||
pub r#type: SStr,
|
||||
#[serde(default)]
|
||||
pub separator: CopySeparator,
|
||||
#[serde(default)]
|
||||
pub hovered: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for CopyForm {
|
||||
fn from(mut a: ActionCow) -> Self {
|
||||
Self {
|
||||
r#type: a.take_first().unwrap_or_default(),
|
||||
separator: a.str("separator").parse().unwrap_or_default(),
|
||||
hovered: a.bool("hovered"),
|
||||
}
|
||||
}
|
||||
impl TryFrom<ActionCow> for CopyForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl FromLua for CopyForm {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct CreateForm {
|
||||
#[serde(default)]
|
||||
pub dir: bool,
|
||||
#[serde(default)]
|
||||
pub force: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for CreateForm {
|
||||
fn from(a: ActionCow) -> Self { Self { dir: a.bool("dir"), force: a.bool("force") } }
|
||||
impl TryFrom<ActionCow> for CreateForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl FromLua for CreateForm {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct HardlinkForm {
|
||||
#[serde(default)]
|
||||
pub force: bool,
|
||||
#[serde(default)]
|
||||
pub follow: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for HardlinkForm {
|
||||
fn from(a: ActionCow) -> Self { Self { force: a.bool("force"), follow: a.bool("follow") } }
|
||||
impl TryFrom<ActionCow> for HardlinkForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl FromLua for HardlinkForm {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct LinkForm {
|
||||
#[serde(default)]
|
||||
pub relative: bool,
|
||||
#[serde(default)]
|
||||
pub force: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for LinkForm {
|
||||
fn from(a: ActionCow) -> Self { Self { relative: a.bool("relative"), force: a.bool("force") } }
|
||||
impl TryFrom<ActionCow> for LinkForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl FromLua for LinkForm {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct PasteForm {
|
||||
#[serde(default)]
|
||||
pub force: bool,
|
||||
#[serde(default)]
|
||||
pub follow: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for PasteForm {
|
||||
fn from(a: ActionCow) -> Self { Self { force: a.bool("force"), follow: a.bool("follow") } }
|
||||
impl TryFrom<ActionCow> for PasteForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl FromLua for PasteForm {
|
||||
|
|
|
|||
|
|
@ -1,41 +1,53 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_fs::path::{clean_url, expand_url};
|
||||
use yazi_shared::{event::ActionCow, url::UrlBuf};
|
||||
use yazi_vfs::provider;
|
||||
|
||||
use crate::mgr::CdSource;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct RevealForm {
|
||||
#[serde(alias = "0")]
|
||||
pub target: UrlBuf,
|
||||
#[serde(default)]
|
||||
pub raw: bool,
|
||||
#[serde(default = "default_source")]
|
||||
pub source: CdSource,
|
||||
#[serde(alias = "no-dummy", default)]
|
||||
pub no_dummy: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for RevealForm {
|
||||
fn from(mut a: ActionCow) -> Self {
|
||||
let mut target = a.take_first().unwrap_or_default();
|
||||
impl TryFrom<ActionCow> for RevealForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
if !a.bool("raw") {
|
||||
target = expand_url(target);
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> {
|
||||
let mut me: Self = a.deserialize()?;
|
||||
|
||||
if !me.raw {
|
||||
me.target = expand_url(me.target).into_owned();
|
||||
}
|
||||
|
||||
if let Some(u) = provider::try_absolute(&target)
|
||||
if let Some(u) = provider::try_absolute(&me.target)
|
||||
&& u.is_owned()
|
||||
{
|
||||
target = u.into_static();
|
||||
me.target = u.into_owned();
|
||||
}
|
||||
|
||||
Self { target: clean_url(target), source: CdSource::Reveal, no_dummy: a.bool("no-dummy") }
|
||||
me.target = clean_url(me.target);
|
||||
Ok(me)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UrlBuf> for RevealForm {
|
||||
fn from(target: UrlBuf) -> Self { Self { target, source: CdSource::Reveal, no_dummy: false } }
|
||||
fn from(target: UrlBuf) -> Self {
|
||||
Self { target, raw: false, source: CdSource::Reveal, no_dummy: false }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(UrlBuf, CdSource)> for RevealForm {
|
||||
fn from((target, source): (UrlBuf, CdSource)) -> Self { Self { target, source, no_dummy: false } }
|
||||
fn from((target, source): (UrlBuf, CdSource)) -> Self {
|
||||
Self { target, raw: false, source, no_dummy: false }
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for RevealForm {
|
||||
|
|
@ -45,3 +57,5 @@ impl FromLua for RevealForm {
|
|||
impl IntoLua for RevealForm {
|
||||
fn into_lua(self, _: &Lua) -> mlua::Result<Value> { Err("unsupported".into_lua_err()) }
|
||||
}
|
||||
|
||||
fn default_source() -> CdSource { CdSource::Reveal }
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct SeekForm {
|
||||
#[serde(alias = "0")]
|
||||
pub units: i16,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for SeekForm {
|
||||
fn from(a: ActionCow) -> Self { Self { units: a.first().unwrap_or(0) } }
|
||||
impl TryFrom<ActionCow> for SeekForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl FromLua for SeekForm {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct SpotOpt {
|
||||
pub skip: Option<usize>,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for SpotOpt {
|
||||
fn from(a: ActionCow) -> Self { Self { skip: a.get("skip").ok() } }
|
||||
impl TryFrom<ActionCow> for SpotOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl From<usize> for SpotOpt {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
use anyhow::bail;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, LuaSerdeExt, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_binding::{SER_OPT, Url};
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_shared::{event::ActionCow, url::UrlBuf};
|
||||
|
||||
use crate::mgr::{CdForm, CdSource};
|
||||
use crate::mgr::CdForm;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct StashForm {
|
||||
#[serde(alias = "0")]
|
||||
pub target: UrlBuf,
|
||||
pub source: CdSource,
|
||||
}
|
||||
|
|
@ -15,11 +16,11 @@ pub struct StashForm {
|
|||
impl TryFrom<ActionCow> for StashForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(_: ActionCow) -> Result<Self, Self::Error> { bail!("unsupported") }
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl From<CdForm> for StashForm {
|
||||
fn from(form: CdForm) -> Self { Self { target: form.target, source: form.source } }
|
||||
impl From<&CdForm> for StashForm {
|
||||
fn from(form: &CdForm) -> Self { Self { target: form.target.clone(), source: form.source } }
|
||||
}
|
||||
|
||||
impl FromLua for StashForm {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct TabCloseForm {
|
||||
#[serde(alias = "0", default)]
|
||||
pub idx: usize,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for TabCloseForm {
|
||||
fn from(a: ActionCow) -> Self { Self { idx: a.first().unwrap_or(0) } }
|
||||
impl TryFrom<ActionCow> for TabCloseForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl From<usize> for TabCloseForm {
|
||||
|
|
|
|||
|
|
@ -1,35 +1,45 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_boot::BOOT;
|
||||
use yazi_fs::path::{clean_url, expand_url};
|
||||
use yazi_shared::{event::ActionCow, url::UrlCow};
|
||||
use yazi_shared::{event::ActionCow, url::UrlBuf};
|
||||
use yazi_vfs::provider;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct TabCreateForm {
|
||||
pub url: Option<UrlCow<'static>>,
|
||||
#[serde(alias = "0")]
|
||||
pub target: Option<UrlBuf>,
|
||||
#[serde(default)]
|
||||
pub current: bool,
|
||||
#[serde(default)]
|
||||
pub raw: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for TabCreateForm {
|
||||
fn from(mut a: ActionCow) -> Self {
|
||||
if a.bool("current") {
|
||||
return Self { url: None };
|
||||
impl TryFrom<ActionCow> for TabCreateForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> {
|
||||
let mut me: Self = a.deserialize()?;
|
||||
|
||||
if me.current {
|
||||
me.target = None;
|
||||
} else if me.target.is_none() {
|
||||
me.target = Some(BOOT.cwds[0].clone());
|
||||
} else if let Some(mut target) = me.target {
|
||||
if !me.raw {
|
||||
target = expand_url(target).into_owned();
|
||||
}
|
||||
|
||||
if let Some(u) = provider::try_absolute(&target)
|
||||
&& u.is_owned()
|
||||
{
|
||||
target = u.into_owned();
|
||||
}
|
||||
|
||||
me.target = Some(clean_url(target));
|
||||
}
|
||||
|
||||
let Ok(mut url) = a.take_first() else {
|
||||
return Self { url: Some(UrlCow::from(&BOOT.cwds[0])) };
|
||||
};
|
||||
|
||||
if !a.bool("raw") {
|
||||
url = expand_url(url);
|
||||
}
|
||||
|
||||
if let Some(u) = provider::try_absolute(&url)
|
||||
&& u.is_owned()
|
||||
{
|
||||
url = u.into_static();
|
||||
}
|
||||
|
||||
Self { url: Some(clean_url(url).into()) }
|
||||
Ok(me)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct TabSwitchForm {
|
||||
#[serde(alias = "0")]
|
||||
pub step: isize,
|
||||
#[serde(default)]
|
||||
pub relative: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for TabSwitchForm {
|
||||
fn from(a: ActionCow) -> Self {
|
||||
Self { step: a.first().unwrap_or(0), relative: a.bool("relative") }
|
||||
}
|
||||
impl TryFrom<ActionCow> for TabSwitchForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl FromLua for TabSwitchForm {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::bail;
|
||||
use anyhow::anyhow;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use yazi_core::tab::PreviewLock;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
|
@ -12,15 +12,9 @@ impl TryFrom<ActionCow> for UpdatePeekedForm {
|
|||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(mut a: ActionCow) -> Result<Self, Self::Error> {
|
||||
if let Some(opt) = a.take_any2("opt") {
|
||||
return opt;
|
||||
}
|
||||
|
||||
let Some(lock) = a.take_any("lock") else {
|
||||
bail!("Invalid 'lock' in UpdatePeekedForm");
|
||||
};
|
||||
|
||||
Ok(Self { lock })
|
||||
Ok(Self {
|
||||
lock: a.take_any("lock").ok_or_else(|| anyhow!("Invalid 'lock' in UpdatePeekedForm"))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::bail;
|
||||
use anyhow::anyhow;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use yazi_core::spot::SpotLock;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
|
@ -12,11 +12,9 @@ impl TryFrom<ActionCow> for UpdateSpottedForm {
|
|||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(mut a: ActionCow) -> Result<Self, Self::Error> {
|
||||
let Some(lock) = a.take_any("lock") else {
|
||||
bail!("Invalid 'lock' in UpdateSpottedForm");
|
||||
};
|
||||
|
||||
Ok(Self { lock })
|
||||
Ok(Self {
|
||||
lock: a.take_any("lock").ok_or_else(|| anyhow!("Invalid 'lock' in UpdateSpottedForm"))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use anyhow::bail;
|
||||
use anyhow::anyhow;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
|
@ -18,11 +18,7 @@ impl TryFrom<ActionCow> for UpdateYankedForm<'_> {
|
|||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(mut a: ActionCow) -> Result<Self, Self::Error> {
|
||||
let Some(state) = a.take_any("state") else {
|
||||
bail!("Invalid 'state' in UpdateYankedForm");
|
||||
};
|
||||
|
||||
Ok(Self(state))
|
||||
a.take_any(0).map(Self).ok_or_else(|| anyhow!("Invalid payload in UpdateYankedForm"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct VisualModeForm {
|
||||
#[serde(default)]
|
||||
pub unset: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for VisualModeForm {
|
||||
fn from(a: ActionCow) -> Self { Self { unset: a.bool("unset") } }
|
||||
impl TryFrom<ActionCow> for VisualModeForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl FromLua for VisualModeForm {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct YankForm {
|
||||
#[serde(default)]
|
||||
pub cut: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for YankForm {
|
||||
fn from(a: ActionCow) -> Self { Self { cut: a.bool("cut") } }
|
||||
impl TryFrom<ActionCow> for YankForm {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> { Ok(a.deserialize()?) }
|
||||
}
|
||||
|
||||
impl FromLua for YankForm {
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ function M:setup()
|
|||
ps.sub_remote("extract", function(args)
|
||||
ya.async(function()
|
||||
for i, arg in ipairs(args) do
|
||||
ya.task("plugin", {
|
||||
local in_ = {
|
||||
self._id,
|
||||
args = { arg, "", noisy = #args == 1 },
|
||||
title = "Extract " .. arg,
|
||||
track = i == 1,
|
||||
}):spawn()
|
||||
}
|
||||
ya.task("plugin", in_):name("Extract " .. arg):spawn()
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
local function setup(_, opts)
|
||||
if opts.sync_yanked then
|
||||
ps.sub_remote("@yank", function(state) ya.emit("update_yanked", { state = state }) end)
|
||||
ps.sub_remote("@yank", function(state) ya.emit("update_yanked", { state }) end)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use mlua::{UserData, UserDataMethods};
|
||||
use mlua::{AnyUserData, UserData, UserDataMethods};
|
||||
use yazi_proxy::TasksProxy;
|
||||
use yazi_scheduler::TaskIn;
|
||||
|
||||
use crate::tasks::Task;
|
||||
|
||||
|
|
@ -8,6 +9,10 @@ pub(crate) struct TaskOpt(pub(crate) yazi_core::tasks::TaskOpt);
|
|||
|
||||
impl UserData for TaskOpt {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_function_mut("name", |_, (ud, name): (AnyUserData, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?.0.set_title(name.to_string_lossy());
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_async_method_once("spawn", |_, me, ()| async move {
|
||||
Ok(Task { id: TasksProxy::spawn(me.0).await? })
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::{str::FromStr, time::Duration};
|
|||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, Table, Value};
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
use yazi_binding::{InputRx, elements::{Line, Pos, Text}, runtime};
|
||||
use yazi_config::{keymap::{Chord, ChordCow, Key}, popup::{ConfirmCfg, InputCfg}};
|
||||
use yazi_config::{Platform, keymap::{Chord, ChordCow, Key}, popup::{ConfirmCfg, InputCfg}};
|
||||
use yazi_core::notify::MessageOpt;
|
||||
use yazi_macro::relay;
|
||||
use yazi_proxy::{ConfirmProxy, InputProxy, NotifyProxy, WhichProxy};
|
||||
|
|
@ -28,7 +28,7 @@ impl Utils {
|
|||
on: Self::parse_keys(cand.raw_get("on")?)?,
|
||||
run: vec![relay!(which:callback, [i + 1])],
|
||||
desc: cand.raw_get("desc").ok(),
|
||||
r#for: None,
|
||||
r#for: Platform::All,
|
||||
}))
|
||||
})
|
||||
.collect::<mlua::Result<_>>()?;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ yazi-core = { path = "../yazi-core", version = "26.2.2" }
|
|||
yazi-macro = { path = "../yazi-macro", version = "26.2.2" }
|
||||
yazi-scheduler = { path = "../yazi-scheduler", version = "26.2.2" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "26.2.2" }
|
||||
yazi-shim = { path = "../yazi-shim", version = "26.2.2" }
|
||||
yazi-widgets = { path = "../yazi-widgets", version = "26.2.2" }
|
||||
|
||||
# External dependencies
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use yazi_core::{mgr::{DisplaceOpt, FilterOpt, FindDoOpt, OpenDoOpt, OpenOpt, SearchOpt}, spot::SpotLock};
|
||||
use yazi_core::{mgr::{CdSource, DisplaceOpt, FilterOpt, FindDoOpt, OpenDoOpt, OpenOpt, SearchOpt}, spot::SpotLock};
|
||||
use yazi_macro::{emit, relay};
|
||||
use yazi_shared::{Id, SStr, url::UrlBuf};
|
||||
use yazi_shim::strum::IntoStr;
|
||||
|
||||
pub struct MgrProxy;
|
||||
|
||||
|
|
@ -9,8 +10,10 @@ impl MgrProxy {
|
|||
emit!(Call(relay!(mgr:arrow, [step.into()])));
|
||||
}
|
||||
|
||||
pub fn cd(target: impl Into<UrlBuf>) {
|
||||
emit!(Call(relay!(mgr:cd, [target.into()]).with("raw", true)));
|
||||
pub fn cd(target: impl Into<UrlBuf>, source: CdSource) {
|
||||
emit!(Call(
|
||||
relay!(mgr:cd, [target.into()]).with("raw", true).with("source", source.into_str())
|
||||
));
|
||||
}
|
||||
|
||||
pub fn displace_do(tab: Id, opt: DisplaceOpt) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use yazi_shared::Id;
|
||||
use yazi_shared::{Id, SStr};
|
||||
|
||||
pub(crate) trait TaskIn {
|
||||
pub trait TaskIn {
|
||||
type Prog;
|
||||
|
||||
fn id(&self) -> Id;
|
||||
|
|
@ -10,4 +10,6 @@ pub(crate) trait TaskIn {
|
|||
fn set_id(&mut self, id: Id) -> &mut Self;
|
||||
|
||||
fn title(&self) -> Cow<'_, str>;
|
||||
|
||||
fn set_title(&mut self, _title: impl Into<SStr>) -> &mut Self { self }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@ impl TaskIn for PluginInEntry {
|
|||
Cow::Borrowed(&self.title)
|
||||
}
|
||||
}
|
||||
|
||||
fn set_title(&mut self, title: impl Into<SStr>) -> &mut Self {
|
||||
self.title = title.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl PluginInEntry {
|
||||
|
|
@ -80,11 +85,10 @@ impl FromLua for PluginInEntry {
|
|||
};
|
||||
|
||||
Ok(Self {
|
||||
id: Id::ZERO,
|
||||
plugin: t.raw_get::<String>(1)?.into(),
|
||||
args: Sendable::table_to_args(lua, t.raw_get("args")?)?,
|
||||
title: t.raw_get::<Option<String>>("title")?.unwrap_or_default().into(),
|
||||
track: t.raw_get("track")?,
|
||||
args: Sendable::table_to_args(lua, t.raw_get("args")?)?,
|
||||
track: t.raw_get("track")?,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,10 @@ impl From<Url<'_>> for UrlBufCov {
|
|||
fn from(value: Url<'_>) -> Self { Self(value.to_owned()) }
|
||||
}
|
||||
|
||||
impl From<UrlCov<'_>> for UrlBufCov {
|
||||
fn from(value: UrlCov<'_>) -> Self { Self(UrlBuf::from(&value.0)) }
|
||||
}
|
||||
|
||||
impl From<&UrlCov<'_>> for UrlBufCov {
|
||||
fn from(value: &UrlCov<'_>) -> Self { Self(UrlBuf::from(&value.0)) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -261,21 +261,6 @@ impl<'a> UrlCow<'a> {
|
|||
|
||||
pub fn into_path(self) -> PathCow<'a> { self.into_pair().1 }
|
||||
|
||||
pub fn into_static(self) -> UrlCow<'static> {
|
||||
match self {
|
||||
UrlCow::Regular(loc) => UrlCow::Regular(loc.into_owned().into()),
|
||||
UrlCow::Search { loc, domain } => {
|
||||
UrlCow::Search { loc: loc.into_owned().into(), domain: domain.into_owned().into() }
|
||||
}
|
||||
UrlCow::Archive { loc, domain } => {
|
||||
UrlCow::Archive { loc: loc.into_owned().into(), domain: domain.into_owned().into() }
|
||||
}
|
||||
UrlCow::Sftp { loc, domain } => {
|
||||
UrlCow::Sftp { loc: loc.into_owned().into(), domain: domain.into_owned().into() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_owned(&self) -> UrlBuf { self.as_url().into() }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::{hash::BuildHasher, path::{Path, PathBuf}};
|
||||
|
||||
use crate::{loc::Loc, url::{Url, UrlBuf, UrlCow}};
|
||||
use hashbrown::{HashMap, hash_map::EntryRef};
|
||||
|
||||
use crate::{loc::Loc, url::{Url, UrlBuf, UrlBufCov, UrlCov, UrlCow}};
|
||||
|
||||
// --- AsUrl
|
||||
pub trait AsUrl {
|
||||
|
|
@ -86,3 +88,63 @@ where
|
|||
{
|
||||
fn from(value: &'a mut T) -> Self { value.as_url() }
|
||||
}
|
||||
|
||||
// --- UrlMapExt
|
||||
pub trait UrlMapExt<V> {
|
||||
fn get_or_insert_default<U>(&mut self, url: U) -> &mut V
|
||||
where
|
||||
U: AsUrl,
|
||||
V: Default;
|
||||
|
||||
fn get_or_insert_with<U, F>(&mut self, url: U, default: F) -> &mut V
|
||||
where
|
||||
U: AsUrl,
|
||||
F: FnOnce(Url<'_>) -> V;
|
||||
}
|
||||
|
||||
impl<V, S> UrlMapExt<V> for HashMap<UrlBuf, V, S>
|
||||
where
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn get_or_insert_default<U>(&mut self, url: U) -> &mut V
|
||||
where
|
||||
U: AsUrl,
|
||||
V: Default,
|
||||
{
|
||||
self.get_or_insert_with(url, |_| Default::default())
|
||||
}
|
||||
|
||||
fn get_or_insert_with<U, F>(&mut self, url: U, default: F) -> &mut V
|
||||
where
|
||||
U: AsUrl,
|
||||
F: FnOnce(Url<'_>) -> V,
|
||||
{
|
||||
let url = url.as_url();
|
||||
match self.entry_ref(&url) {
|
||||
EntryRef::Occupied(oe) => oe.into_mut(),
|
||||
EntryRef::Vacant(ve) => ve.insert_with_key(url.into(), default(url)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- UrlCovMapExt
|
||||
pub trait UrlCovMapExt<V> {
|
||||
fn get_or_insert_default(&mut self, url: UrlCov<'_>) -> &mut V
|
||||
where
|
||||
V: Default;
|
||||
}
|
||||
|
||||
impl<V, S> UrlCovMapExt<V> for HashMap<UrlBufCov, V, S>
|
||||
where
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn get_or_insert_default(&mut self, url: UrlCov<'_>) -> &mut V
|
||||
where
|
||||
V: Default,
|
||||
{
|
||||
match self.entry_ref(&url) {
|
||||
EntryRef::Occupied(oe) => oe.into_mut(),
|
||||
EntryRef::Vacant(ve) => ve.insert_with_key(url.into(), Default::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue