Skip to content

Commit 1e08e09

Browse files
authored
feat: new search_do command to make it easier to achieve a flat view (#1431)
1 parent 5df6873 commit 1e08e09

File tree

12 files changed

+120
-69
lines changed

12 files changed

+120
-69
lines changed

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

yazi-config/preset/keymap.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ keymap = [
7575
{ on = ".", run = "hidden toggle", desc = "Toggle the visibility of hidden files" },
7676
{ on = "s", run = "search fd", desc = "Search files by name using fd" },
7777
{ on = "S", run = "search rg", desc = "Search files by content using ripgrep" },
78-
{ on = "<C-s>", run = "search none", desc = "Cancel the ongoing search" },
78+
{ on = "<C-s>", run = "escape --search", desc = "Cancel the ongoing search" },
7979
{ on = "z", run = "plugin zoxide", desc = "Jump to a directory using zoxide" },
8080
{ on = "Z", run = "plugin fzf", desc = "Jump to a directory or reveal a file using fzf" },
8181

yazi-core/src/tab/commands/escape.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,10 @@ impl Tab {
9292
}
9393

9494
pub fn escape_search(&mut self) -> bool {
95-
if !self.current.cwd.is_search() {
96-
return false;
97-
}
98-
95+
let b = self.current.cwd.is_search();
9996
self.search_stop();
100-
render_and!(true)
97+
98+
render_and!(b)
10199
}
102100

103101
pub fn try_escape_visual(&mut self) -> bool {

yazi-core/src/tab/commands/search.rs

Lines changed: 39 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,45 @@
1-
use std::{fmt::Display, mem, time::Duration};
1+
use std::{mem, time::Duration};
22

3-
use anyhow::bail;
43
use tokio::pin;
54
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
5+
use tracing::error;
66
use yazi_config::popup::InputCfg;
77
use yazi_plugin::external;
8-
use yazi_proxy::{AppProxy, InputProxy, ManagerProxy, TabProxy};
9-
use yazi_shared::{event::Cmd, fs::FilesOp, render};
8+
use yazi_proxy::{options::{SearchOpt, SearchOptVia}, AppProxy, InputProxy, ManagerProxy, TabProxy};
9+
use yazi_shared::fs::FilesOp;
1010

1111
use crate::tab::Tab;
1212

13-
#[derive(PartialEq, Eq)]
14-
pub enum OptType {
15-
None,
16-
Rg,
17-
Fd,
18-
}
13+
impl Tab {
14+
pub fn search(&mut self, opt: impl TryInto<SearchOpt>) {
15+
let Ok(mut opt) = opt.try_into() else {
16+
return AppProxy::notify_error("Invalid `search` option", "Failed to parse search option");
17+
};
1918

20-
impl From<String> for OptType {
21-
fn from(value: String) -> Self {
22-
match value.as_str() {
23-
"rg" => Self::Rg,
24-
"fd" => Self::Fd,
25-
_ => Self::None,
19+
if opt.via == SearchOptVia::None {
20+
return self.search_stop();
2621
}
27-
}
28-
}
29-
30-
impl Display for OptType {
31-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32-
f.write_str(match self {
33-
Self::Rg => "rg",
34-
Self::Fd => "fd",
35-
Self::None => "none",
36-
})
37-
}
38-
}
3922

40-
pub struct Opt {
41-
pub type_: OptType,
42-
pub args: Vec<String>,
43-
}
23+
if let Some(handle) = self.search.take() {
24+
handle.abort();
25+
}
4426

45-
impl TryFrom<Cmd> for Opt {
46-
type Error = ();
27+
tokio::spawn(async move {
28+
let mut input =
29+
InputProxy::show(InputCfg::search(&opt.via.to_string()).with_value(opt.subject));
4730

48-
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
49-
Ok(Self {
50-
type_: c.take_first_str().unwrap_or_default().into(),
51-
args: shell_words::split(c.str("args").unwrap_or_default()).map_err(|_| ())?,
52-
})
31+
if let Some(Ok(subject)) = input.recv().await {
32+
opt.subject = subject;
33+
TabProxy::search_do(opt);
34+
}
35+
});
5336
}
54-
}
5537

56-
impl Tab {
57-
pub fn search(&mut self, opt: impl TryInto<Opt>) {
38+
pub fn search_do(&mut self, opt: impl TryInto<SearchOpt>) {
5839
let Ok(opt) = opt.try_into() else {
59-
return AppProxy::notify_error("Invalid `search` option", "Failed to parse search option");
40+
return error!("Failed to parse search option for `search_do`");
6041
};
6142

62-
if opt.type_ == OptType::None {
63-
return self.search_stop();
64-
}
65-
6643
if let Some(handle) = self.search.take() {
6744
handle.abort();
6845
}
@@ -71,14 +48,21 @@ impl Tab {
7148
let hidden = self.conf.show_hidden;
7249

7350
self.search = Some(tokio::spawn(async move {
74-
let mut input = InputProxy::show(InputCfg::search(&opt.type_.to_string()));
75-
let Some(Ok(subject)) = input.recv().await else { bail!("") };
76-
77-
cwd = cwd.into_search(subject.clone());
78-
let rx = if opt.type_ == OptType::Rg {
79-
external::rg(external::RgOpt { cwd: cwd.clone(), hidden, subject, args: opt.args })
51+
cwd = cwd.into_search(opt.subject.clone());
52+
let rx = if opt.via == SearchOptVia::Rg {
53+
external::rg(external::RgOpt {
54+
cwd: cwd.clone(),
55+
hidden,
56+
subject: opt.subject,
57+
args: opt.args,
58+
})
8059
} else {
81-
external::fd(external::FdOpt { cwd: cwd.clone(), hidden, subject, args: opt.args })
60+
external::fd(external::FdOpt {
61+
cwd: cwd.clone(),
62+
hidden,
63+
subject: opt.subject,
64+
args: opt.args,
65+
})
8266
}?;
8367

8468
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(1000, Duration::from_millis(300));
@@ -89,10 +73,9 @@ impl Tab {
8973
FilesOp::Part(cwd.clone(), chunk, ticket).emit();
9074
}
9175
FilesOp::Done(cwd, None, ticket).emit();
76+
9277
Ok(())
9378
}));
94-
95-
render!();
9679
}
9780

9881
pub(super) fn search_stop(&mut self) {

yazi-dds/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ tracing = { workspace = true }
3131
vergen-gitcl = { version = "1.0.0", features = [ "build" ] }
3232

3333
[target."cfg(unix)".dependencies]
34-
uzers = "0.12.0"
34+
uzers = "0.12.1"

yazi-fm/src/executor.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ impl<'a> Executor<'a> {
110110
on!(ACTIVE, hidden);
111111
on!(ACTIVE, linemode);
112112
on!(ACTIVE, search);
113+
on!(ACTIVE, search_do);
113114

114115
// Filter
115116
on!(ACTIVE, filter);

yazi-plugin/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ unicode-width = { workspace = true }
4141
yazi-prebuild = "0.1.2"
4242

4343
[target."cfg(unix)".dependencies]
44-
uzers = "0.12.0"
44+
uzers = "0.12.1"
4545

4646
[target."cfg(windows)".dependencies]
4747
clipboard-win = "5.4.0"

yazi-proxy/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ yazi-config = { path = "../yazi-config", version = "0.3.0" }
1717
yazi-shared = { path = "../yazi-shared", version = "0.3.0" }
1818

1919
# External dependencies
20-
anyhow = { workspace = true }
21-
mlua = { workspace = true }
22-
tokio = { workspace = true }
20+
anyhow = { workspace = true }
21+
mlua = { workspace = true }
22+
shell-words = { workspace = true }
23+
tokio = { workspace = true }

yazi-proxy/src/options/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
mod notify;
22
mod open;
33
mod process;
4+
mod search;
45

56
pub use notify::*;
67
pub use open::*;
78
pub use process::*;
9+
pub use search::*;

yazi-proxy/src/options/search.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use std::fmt::Display;
2+
3+
use yazi_shared::event::Cmd;
4+
5+
pub struct SearchOpt {
6+
pub via: SearchOptVia,
7+
pub subject: String,
8+
pub args: Vec<String>,
9+
pub args_raw: String,
10+
}
11+
12+
impl TryFrom<Cmd> for SearchOpt {
13+
type Error = ();
14+
15+
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
16+
Ok(Self {
17+
// TODO: remove `c.take_first_str()` in the future
18+
via: c.take_str("via").or_else(|| c.take_first_str()).unwrap_or_default().into(),
19+
subject: c.take_first_str().unwrap_or_default(),
20+
args: shell_words::split(c.str("args").unwrap_or_default()).map_err(|_| ())?,
21+
args_raw: c.take_str("args").unwrap_or_default(),
22+
})
23+
}
24+
}
25+
26+
// Via
27+
#[derive(PartialEq, Eq)]
28+
pub enum SearchOptVia {
29+
// TODO: remove `None` in the future
30+
None,
31+
Rg,
32+
Fd,
33+
}
34+
35+
impl From<String> for SearchOptVia {
36+
fn from(value: String) -> Self {
37+
match value.as_str() {
38+
"rg" => Self::Rg,
39+
"fd" => Self::Fd,
40+
_ => Self::None,
41+
}
42+
}
43+
}
44+
45+
impl Display for SearchOptVia {
46+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47+
f.write_str(match self {
48+
Self::Rg => "rg",
49+
Self::Fd => "fd",
50+
Self::None => "none",
51+
})
52+
}
53+
}

0 commit comments

Comments
 (0)