mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-22 23:31:05 +00:00
feat: allow initializing input when opening it with commands like rename, create, find, filter, etc. (#2578)
This commit is contained in:
parent
fd007ab023
commit
be00881403
11 changed files with 52 additions and 60 deletions
|
|
@ -22,13 +22,12 @@ impl Mgr {
|
|||
#[yazi_codegen::command]
|
||||
pub fn create(&self, opt: Opt) {
|
||||
let cwd = self.cwd().to_owned();
|
||||
let mut input = InputProxy::show(InputCfg::create(opt.dir));
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut result = InputProxy::show(InputCfg::create(opt.dir));
|
||||
let Some(Ok(name)) = result.recv().await else {
|
||||
return Ok(());
|
||||
};
|
||||
let Some(Ok(name)) = input.recv().await else { return };
|
||||
if name.is_empty() {
|
||||
return Ok(());
|
||||
return;
|
||||
}
|
||||
|
||||
let new = cwd.join(&name);
|
||||
|
|
@ -36,10 +35,10 @@ impl Mgr {
|
|||
&& maybe_exists(&new).await
|
||||
&& !ConfirmProxy::show(ConfirmCfg::overwrite(&new)).await
|
||||
{
|
||||
return Ok(());
|
||||
return;
|
||||
}
|
||||
|
||||
Self::create_do(new, opt.dir || name.ends_with('/') || name.ends_with('\\')).await
|
||||
_ = Self::create_do(new, opt.dir || name.ends_with('/') || name.ends_with('\\')).await;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use yazi_config::{YAZI, popup::PickCfg};
|
|||
use yazi_fs::File;
|
||||
use yazi_macro::emit;
|
||||
use yazi_plugin::isolate;
|
||||
use yazi_proxy::{MgrProxy, TasksProxy, options::OpenDoOpt};
|
||||
use yazi_proxy::{MgrProxy, PickProxy, TasksProxy, options::OpenDoOpt};
|
||||
use yazi_shared::{MIME_DIR, event::{CmdCow, EventQuit}, url::Url};
|
||||
|
||||
use crate::{mgr::Mgr, tab::Folder, tasks::Tasks};
|
||||
|
|
@ -95,12 +95,10 @@ impl Mgr {
|
|||
return;
|
||||
}
|
||||
|
||||
let pick = PickProxy::show(PickCfg::open(openers.iter().map(|o| o.desc()).collect()));
|
||||
let urls = [opt.hovered].into_iter().chain(targets.into_iter().map(|(u, _)| u)).collect();
|
||||
tokio::spawn(async move {
|
||||
let result =
|
||||
yazi_proxy::PickProxy::show(PickCfg::open(openers.iter().map(|o| o.desc()).collect()));
|
||||
|
||||
if let Ok(choice) = result.await {
|
||||
if let Ok(choice) = pick.await {
|
||||
TasksProxy::open_with(Cow::Borrowed(openers[choice]), opt.cwd, urls);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -41,14 +41,14 @@ impl Mgr {
|
|||
return self.remove_do(opt, tasks);
|
||||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
let result = ConfirmProxy::show(if opt.permanently {
|
||||
ConfirmCfg::delete(&opt.targets)
|
||||
} else {
|
||||
ConfirmCfg::trash(&opt.targets)
|
||||
});
|
||||
let confirm = ConfirmProxy::show(if opt.permanently {
|
||||
ConfirmCfg::delete(&opt.targets)
|
||||
} else {
|
||||
ConfirmCfg::trash(&opt.targets)
|
||||
});
|
||||
|
||||
if result.await {
|
||||
tokio::spawn(async move {
|
||||
if confirm.await {
|
||||
MgrProxy::remove_do(opt.targets, opt.permanently);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -53,12 +53,10 @@ impl Mgr {
|
|||
|
||||
let old = hovered.url_owned();
|
||||
let tab = self.tabs.active().id;
|
||||
tokio::spawn(async move {
|
||||
let mut result = InputProxy::show(InputCfg::rename().with_value(name).with_cursor(cursor));
|
||||
let Some(Ok(name)) = result.recv().await else {
|
||||
return;
|
||||
};
|
||||
let mut input = InputProxy::show(InputCfg::rename().with_value(name).with_cursor(cursor));
|
||||
|
||||
tokio::spawn(async move {
|
||||
let Some(Ok(name)) = input.recv().await else { return };
|
||||
if name.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,10 +77,10 @@ impl Tab {
|
|||
}
|
||||
|
||||
fn cd_interactive(&mut self) {
|
||||
tokio::spawn(async move {
|
||||
let rx = InputProxy::show(InputCfg::cd());
|
||||
let input = InputProxy::show(InputCfg::cd());
|
||||
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||
tokio::spawn(async move {
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(input), Duration::from_millis(50));
|
||||
pin!(rx);
|
||||
|
||||
while let Some(result) = rx.next().await {
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ impl From<CmdCow> for Opt {
|
|||
impl Tab {
|
||||
#[yazi_codegen::command]
|
||||
pub fn filter(&mut self, opt: Opt) {
|
||||
tokio::spawn(async move {
|
||||
let rx = InputProxy::show(InputCfg::filter());
|
||||
let input = InputProxy::show(InputCfg::filter());
|
||||
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||
tokio::spawn(async move {
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(input), Duration::from_millis(50));
|
||||
pin!(rx);
|
||||
|
||||
while let Some(result) = rx.next().await {
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ impl From<CmdCow> for Opt {
|
|||
impl Tab {
|
||||
#[yazi_codegen::command]
|
||||
pub fn find(&mut self, opt: Opt) {
|
||||
tokio::spawn(async move {
|
||||
let rx = InputProxy::show(InputCfg::find(opt.prev));
|
||||
let input = InputProxy::show(InputCfg::find(opt.prev));
|
||||
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||
tokio::spawn(async move {
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(input), Duration::from_millis(50));
|
||||
pin!(rx);
|
||||
|
||||
while let Some(Ok(s)) | Some(Err(InputError::Typed(s))) = rx.next().await {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::{borrow::Cow, mem, time::Duration};
|
||||
|
||||
use anyhow::bail;
|
||||
use tokio::pin;
|
||||
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
|
||||
use tracing::error;
|
||||
|
|
@ -13,22 +12,18 @@ use crate::tab::Tab;
|
|||
|
||||
impl Tab {
|
||||
pub fn search(&mut self, opt: impl TryInto<SearchOpt>) {
|
||||
let Ok(mut opt) = opt.try_into() else {
|
||||
let Ok(mut opt): Result<SearchOpt, _> = opt.try_into() else {
|
||||
return AppProxy::notify_error("Invalid `search` option", "Failed to parse search option");
|
||||
};
|
||||
|
||||
if opt.via == SearchOptVia::None {
|
||||
return self.search_stop();
|
||||
}
|
||||
|
||||
if let Some(handle) = self.search.take() {
|
||||
handle.abort();
|
||||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut input =
|
||||
InputProxy::show(InputCfg::search(&opt.via.to_string()).with_value(opt.subject));
|
||||
let mut input =
|
||||
InputProxy::show(InputCfg::search(opt.via.as_ref()).with_value(opt.subject.to_owned()));
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Some(Ok(subject)) = input.recv().await {
|
||||
opt.subject = Cow::Owned(subject);
|
||||
TabProxy::search_do(opt);
|
||||
|
|
@ -68,7 +63,6 @@ impl Tab {
|
|||
subject: opt.subject.into_owned(),
|
||||
args: opt.args,
|
||||
}),
|
||||
SearchOptVia::None => bail!("Invalid `via` option for `search` command"),
|
||||
}?;
|
||||
|
||||
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(5000, Duration::from_millis(500));
|
||||
|
|
|
|||
|
|
@ -54,11 +54,16 @@ impl Tab {
|
|||
|
||||
let cwd = opt.cwd.take().unwrap_or_else(|| self.cwd().clone());
|
||||
let selected = self.hovered_and_selected().cloned().collect();
|
||||
|
||||
let input = opt.interactive.then(|| {
|
||||
InputProxy::show(
|
||||
InputCfg::shell(opt.block).with_value(opt.run.to_owned()).with_cursor(opt.cursor),
|
||||
)
|
||||
});
|
||||
|
||||
tokio::spawn(async move {
|
||||
if opt.interactive {
|
||||
let mut result =
|
||||
InputProxy::show(InputCfg::shell(opt.block).with_value(opt.run).with_cursor(opt.cursor));
|
||||
match result.recv().await {
|
||||
if let Some(mut rx) = input {
|
||||
match rx.recv().await {
|
||||
Some(Ok(e)) => opt.run = Cow::Owned(e),
|
||||
_ => return,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{borrow::Cow, fmt::Display};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use yazi_shared::event::CmdCow;
|
||||
|
||||
|
|
@ -35,31 +35,27 @@ impl TryFrom<CmdCow> for SearchOpt {
|
|||
// Via
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum SearchOptVia {
|
||||
// TODO: remove `None` in the future
|
||||
None,
|
||||
Rg,
|
||||
Fd,
|
||||
Rga,
|
||||
Fd,
|
||||
}
|
||||
|
||||
impl From<&str> for SearchOptVia {
|
||||
fn from(value: &str) -> Self {
|
||||
match value {
|
||||
"rg" => Self::Rg,
|
||||
"fd" => Self::Fd,
|
||||
"rga" => Self::Rga,
|
||||
_ => Self::None,
|
||||
_ => Self::Fd,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SearchOptVia {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(match self {
|
||||
impl AsRef<str> for SearchOptVia {
|
||||
fn as_ref(&self) -> &str {
|
||||
match self {
|
||||
Self::Rg => "rg",
|
||||
Self::Fd => "fd",
|
||||
Self::Rga => "rga",
|
||||
Self::None => "none",
|
||||
})
|
||||
Self::Fd => "fd",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ impl TabProxy {
|
|||
pub fn search_do(opt: SearchOpt) {
|
||||
emit!(Call(
|
||||
// TODO: use second positional argument instead of `args` parameter
|
||||
Cmd::args("mgr:search_do", &[opt.subject]).with("via", opt.via).with("args", opt.args_raw)
|
||||
Cmd::args("mgr:search_do", &[opt.subject])
|
||||
.with("via", opt.via.as_ref())
|
||||
.with("args", opt.args_raw)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue