mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: new --in for search action to set search directory (#3696)
This commit is contained in:
parent
578016e00f
commit
9af792ef69
14 changed files with 76 additions and 59 deletions
|
|
@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
### Added
|
||||
|
||||
- Custom tab name ([#3666])
|
||||
- New `--in` for `search` action to set search directory ([#3696])
|
||||
- Allow using `ps.sub()` in `init.lua` directly without a plugin ([#3638])
|
||||
- New `sort_fallback` option to control fallback sorting behavior ([#3077])
|
||||
- New `fs.access()` API to access the filesystem ([#3668])
|
||||
|
|
@ -1664,3 +1665,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
[#3684]: https://github.com/sxyazi/yazi/pull/3684
|
||||
[#3687]: https://github.com/sxyazi/yazi/pull/3687
|
||||
[#3689]: https://github.com/sxyazi/yazi/pull/3689
|
||||
[#3696]: https://github.com/sxyazi/yazi/pull/3696
|
||||
|
|
|
|||
25
Cargo.lock
generated
25
Cargo.lock
generated
|
|
@ -600,9 +600,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.58"
|
||||
version = "4.5.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806"
|
||||
checksum = "c5caf74d17c3aec5495110c34cc3f78644bfa89af6c8993ed4de2790e49b6499"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -610,9 +610,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.58"
|
||||
version = "4.5.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2"
|
||||
checksum = "370daa45065b80218950227371916a1633217ae42b2715b2287b606dcd618e24"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
|
@ -1105,21 +1105,20 @@ checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
|
|||
|
||||
[[package]]
|
||||
name = "deadpool"
|
||||
version = "0.12.3"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b"
|
||||
checksum = "883466cb8db62725aee5f4a6011e8a5d42912b42632df32aad57fc91127c6e04"
|
||||
dependencies = [
|
||||
"deadpool-runtime",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deadpool-runtime"
|
||||
version = "0.1.4"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b"
|
||||
checksum = "2657f61fb1dd8bf37a8d51093cc7cee4e77125b22f7753f49b289f831bec2bae"
|
||||
dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
|
@ -4676,9 +4675,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "1.0.1+spec-1.1.0"
|
||||
version = "1.0.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe30f93627849fa362d4a602212d41bb237dc2bd0f8ba0b2ce785012e124220"
|
||||
checksum = "d1dfefef6a142e93f346b64c160934eb13b5594b84ab378133ac6815cb2bd57f"
|
||||
dependencies = [
|
||||
"indexmap 2.13.0",
|
||||
"serde_core",
|
||||
|
|
@ -4700,9 +4699,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.8+spec-1.1.0"
|
||||
version = "1.0.9+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc"
|
||||
checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ ansi-to-tui = "8.0.1"
|
|||
anyhow = "1.0.101"
|
||||
base64 = "0.22.1"
|
||||
bitflags = { version = "2.11.0", features = [ "serde" ] }
|
||||
clap = { version = "4.5.58", features = [ "derive" ] }
|
||||
clap = { version = "4.5.59", features = [ "derive" ] }
|
||||
core-foundation-sys = "0.8.7"
|
||||
crossterm = { version = "0.29.0", features = [ "event-stream" ] }
|
||||
dirs = "6.0.0"
|
||||
|
|
@ -62,7 +62,7 @@ thiserror = "2.0.18"
|
|||
tokio = { version = "1.49.0", features = [ "full" ] }
|
||||
tokio-stream = "0.1.18"
|
||||
tokio-util = "0.7.18"
|
||||
toml = { version = "1.0.1" }
|
||||
toml = { version = "1.0.2" }
|
||||
tracing = { version = "0.1.44", features = [ "max_level_debug", "release_max_level_debug" ] }
|
||||
twox-hash = { version = "2.1.2", default-features = false, features = [ "std", "random", "xxhash3_128" ] }
|
||||
typed-path = "0.12.3"
|
||||
|
|
|
|||
|
|
@ -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, NotifyProxy};
|
||||
use yazi_shared::{data::Data, url::UrlLike};
|
||||
use yazi_shared::{data::Data, url::{AsUrl, UrlLike}};
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
|
|
@ -53,7 +53,8 @@ impl Actor for SearchDo {
|
|||
}
|
||||
|
||||
let hidden = tab.pref.show_hidden;
|
||||
let Ok(cwd) = tab.cwd().to_search(&opt.subject) else {
|
||||
let r#in = opt.r#in.as_ref().map_or_else(|| tab.cwd().as_url(), |u| u.as_url());
|
||||
let Ok(cwd) = r#in.to_search(&opt.subject) else {
|
||||
succ!(NotifyProxy::push_warn("Search", "Only local filesystem searches are supported"));
|
||||
};
|
||||
|
||||
|
|
@ -109,10 +110,14 @@ impl Actor for SearchStop {
|
|||
handle.abort();
|
||||
}
|
||||
|
||||
if tab.cwd().is_search() {
|
||||
act!(mgr:cd, cx, (tab.cwd().to_regular()?, CdSource::Escape))?;
|
||||
if !tab.cwd().is_search() {
|
||||
succ!();
|
||||
}
|
||||
|
||||
succ!();
|
||||
if let Some(u) = tab.backstack.current().cloned() {
|
||||
act!(mgr:cd, cx, (u, CdSource::Escape))
|
||||
} else {
|
||||
act!(mgr:cd, cx, (tab.cwd().to_regular()?, CdSource::Escape))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,12 +30,15 @@ impl Actor for TabCreate {
|
|||
} else if let Some(h) = cx.hovered() {
|
||||
tab.pref = cx.tab().pref.clone();
|
||||
(false, h.url.clone())
|
||||
} else if cx.cwd().is_search() {
|
||||
tab.pref = cx.tab().pref.clone();
|
||||
(true, cx.cwd().to_regular()?)
|
||||
} else {
|
||||
} else if !cx.cwd().is_search() {
|
||||
tab.pref = cx.tab().pref.clone();
|
||||
(true, cx.cwd().clone())
|
||||
} else if let Some(u) = tab.backstack.current().cloned() {
|
||||
tab.pref = cx.tab().pref.clone();
|
||||
(true, u)
|
||||
} else {
|
||||
tab.pref = cx.tab().pref.clone();
|
||||
(true, tab.cwd().to_regular()?)
|
||||
};
|
||||
|
||||
let tabs = &mut cx.mgr.tabs;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ impl Backstack {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn current(&self) -> Option<&UrlBuf> { self.stack.get(self.cursor) }
|
||||
|
||||
pub fn shift_backward(&mut self) -> Option<&UrlBuf> {
|
||||
if self.cursor > 0 {
|
||||
self.cursor -= 1;
|
||||
|
|
|
|||
|
|
@ -3,37 +3,42 @@ use std::str::FromStr;
|
|||
use anyhow::bail;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::{SStr, event::ActionCow};
|
||||
use yazi_shared::{SStr, event::ActionCow, url::{UrlCow, UrlLike}};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SearchOpt {
|
||||
pub via: SearchOptVia,
|
||||
pub subject: SStr,
|
||||
pub args: Vec<String>,
|
||||
pub args_raw: SStr,
|
||||
pub r#in: Option<UrlCow<'static>>,
|
||||
}
|
||||
|
||||
impl TryFrom<ActionCow> for SearchOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(mut a: ActionCow) -> Result<Self, Self::Error> {
|
||||
// TODO: remove this
|
||||
let (via, subject) = if let Ok(s) = a.get("via") {
|
||||
(str::parse(s)?, a.take_first().unwrap_or_default())
|
||||
} else {
|
||||
(a.str(0).parse()?, "".into())
|
||||
};
|
||||
if let Some(opt) = a.take_any2("opt") {
|
||||
return opt;
|
||||
}
|
||||
|
||||
let r#in = a.take::<UrlCow>("in").ok();
|
||||
if let Some(u) = &r#in
|
||||
&& (!u.is_absolute() || u.is_search())
|
||||
{
|
||||
bail!("invalid 'in' in SearchOpt");
|
||||
}
|
||||
|
||||
let Ok(args) = yazi_shared::shell::unix::split(a.str("args"), false) else {
|
||||
bail!("Invalid 'args' in SearchOpt");
|
||||
bail!("invalid 'args' in SearchOpt");
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
via,
|
||||
subject,
|
||||
// TODO: use second positional argument instead of `args` parameter
|
||||
via: a.str("via").parse()?,
|
||||
subject: a.take_first().unwrap_or_default(),
|
||||
args: args.0,
|
||||
args_raw: a.take("args").unwrap_or_default(),
|
||||
r#in,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
yazi-plugin/src/external/fd.rs
vendored
5
yazi-plugin/src/external/fd.rs
vendored
|
|
@ -1,4 +1,4 @@
|
|||
use std::process::Stdio;
|
||||
use std::{path::Path, process::Stdio};
|
||||
|
||||
use anyhow::Result;
|
||||
use tokio::{io::{AsyncBufReadExt, BufReader}, process::{Child, Command}, sync::mpsc::{self, UnboundedReceiver}};
|
||||
|
|
@ -21,6 +21,9 @@ pub fn fd(opt: FdOpt) -> Result<UnboundedReceiver<File>> {
|
|||
|
||||
tokio::spawn(async move {
|
||||
while let Ok(Some(line)) = it.next_line().await {
|
||||
if Path::new(&line).is_absolute() {
|
||||
continue;
|
||||
}
|
||||
let Ok(url) = opt.cwd.try_join(line) else {
|
||||
continue;
|
||||
};
|
||||
|
|
|
|||
7
yazi-plugin/src/external/rg.rs
vendored
7
yazi-plugin/src/external/rg.rs
vendored
|
|
@ -1,4 +1,4 @@
|
|||
use std::process::Stdio;
|
||||
use std::{path::Path, process::Stdio};
|
||||
|
||||
use anyhow::Result;
|
||||
use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}};
|
||||
|
|
@ -19,7 +19,7 @@ pub fn rg(opt: RgOpt) -> Result<UnboundedReceiver<File>> {
|
|||
.arg(if opt.hidden { "--hidden" } else { "--no-hidden" })
|
||||
.args(opt.args)
|
||||
.arg(opt.subject)
|
||||
.arg(&*opt.cwd.as_url().unified_path())
|
||||
.current_dir(&*opt.cwd.as_url().unified_path())
|
||||
.kill_on_drop(true)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::null())
|
||||
|
|
@ -30,6 +30,9 @@ pub fn rg(opt: RgOpt) -> Result<UnboundedReceiver<File>> {
|
|||
|
||||
tokio::spawn(async move {
|
||||
while let Ok(Some(line)) = it.next_line().await {
|
||||
if Path::new(&line).is_absolute() {
|
||||
continue;
|
||||
}
|
||||
let Ok(url) = opt.cwd.try_join(line) else {
|
||||
continue;
|
||||
};
|
||||
|
|
|
|||
7
yazi-plugin/src/external/rga.rs
vendored
7
yazi-plugin/src/external/rga.rs
vendored
|
|
@ -1,4 +1,4 @@
|
|||
use std::process::Stdio;
|
||||
use std::{path::Path, process::Stdio};
|
||||
|
||||
use anyhow::Result;
|
||||
use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}};
|
||||
|
|
@ -19,7 +19,7 @@ pub fn rga(opt: RgaOpt) -> Result<UnboundedReceiver<File>> {
|
|||
.arg(if opt.hidden { "--hidden" } else { "--no-hidden" })
|
||||
.args(opt.args)
|
||||
.arg(opt.subject)
|
||||
.arg(&*opt.cwd.as_url().unified_path())
|
||||
.current_dir(&*opt.cwd.as_url().unified_path())
|
||||
.kill_on_drop(true)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::null())
|
||||
|
|
@ -30,6 +30,9 @@ pub fn rga(opt: RgaOpt) -> Result<UnboundedReceiver<File>> {
|
|||
|
||||
tokio::spawn(async move {
|
||||
while let Ok(Some(line)) = it.next_line().await {
|
||||
if Path::new(&line).is_absolute() {
|
||||
continue;
|
||||
}
|
||||
let Ok(url) = opt.cwd.try_join(line) else {
|
||||
continue;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use yazi_macro::{emit, relay};
|
||||
use yazi_parser::mgr::{DisplaceDoOpt, FilterOpt, FindDoOpt, OpenDoOpt, OpenOpt, SearchOpt, UpdatePeekedOpt, UpdateSpottedOpt};
|
||||
use yazi_shared::{Id, SStr, url::UrlBuf};
|
||||
|
|
@ -50,12 +48,7 @@ impl MgrProxy {
|
|||
}
|
||||
|
||||
pub fn search_do(opt: SearchOpt) {
|
||||
emit!(Call(
|
||||
// TODO: use second positional argument instead of `args` parameter
|
||||
relay!(mgr:search_do, [opt.subject])
|
||||
.with("via", Cow::Borrowed(opt.via.into_str()))
|
||||
.with("args", opt.args_raw.into_owned())
|
||||
));
|
||||
emit!(Call(relay!(mgr:search_do).with_any("opt", opt)));
|
||||
}
|
||||
|
||||
pub fn tab_rename(tab: Id, name: impl Into<SStr>) {
|
||||
|
|
|
|||
|
|
@ -179,14 +179,6 @@ impl UrlBuf {
|
|||
Ok(Self::Regular(self.into_loc().into_os()?.into()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_search(&self, domain: impl AsRef<str>) -> Result<Self, PathDynError> {
|
||||
Ok(Self::Search {
|
||||
loc: LocBuf::<PathBuf>::zeroed(self.loc().to_os_owned()?),
|
||||
domain: Pool::<str>::intern(domain),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_search(self, domain: impl AsRef<str>) -> Result<Self, PathDynError> {
|
||||
Ok(Self::Search {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use hashbrown::Equivalent;
|
|||
use serde::Serialize;
|
||||
|
||||
use super::Encode as EncodeUrl;
|
||||
use crate::{loc::{Loc, LocBuf}, path::{AsPath, AsPathRef, EndsWithError, JoinError, PathBufDyn, PathDyn, PathDynError, PathLike, StartsWithError, StripPrefixError, StripSuffixError}, pool::InternStr, scheme::{Encode as EncodeScheme, SchemeCow, SchemeKind, SchemeRef}, strand::{AsStrand, Strand}, url::{AsUrl, Components, UrlBuf, UrlCow}};
|
||||
use crate::{loc::{Loc, LocBuf}, path::{AsPath, AsPathRef, EndsWithError, JoinError, PathBufDyn, PathDyn, PathDynError, PathLike, StartsWithError, StripPrefixError, StripSuffixError}, pool::{InternStr, Pool}, scheme::{Encode as EncodeScheme, SchemeCow, SchemeKind, SchemeRef}, strand::{AsStrand, Strand}, url::{AsUrl, Components, UrlBuf, UrlCow}};
|
||||
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub enum Url<'a> {
|
||||
|
|
@ -222,6 +222,13 @@ impl<'a> Url<'a> {
|
|||
#[inline]
|
||||
pub fn to_owned(self) -> UrlBuf { self.into() }
|
||||
|
||||
pub fn to_search(self, domain: impl AsRef<str>) -> Result<UrlBuf, PathDynError> {
|
||||
Ok(UrlBuf::Search {
|
||||
loc: LocBuf::<PathBuf>::zeroed(self.loc().to_os_owned()?),
|
||||
domain: Pool::<str>::intern(domain),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn trail(self) -> Self {
|
||||
let uri = self.uri();
|
||||
match self {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ yazi-shared = { path = "../yazi-shared", version = "26.2.2" }
|
|||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
deadpool = { version = "0.12.3", default-features = false, features = [ "managed", "rt_tokio_1" ] }
|
||||
deadpool = { version = "0.13.0", default-features = false, features = [ "managed", "rt_tokio_1" ] }
|
||||
either = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue