From be00881403922f8dfd34840252649978fc75b5d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Sun, 6 Apr 2025 16:59:48 +0800 Subject: [PATCH] feat: allow initializing input when opening it with commands like `rename`, `create`, `find`, `filter`, etc. (#2578) --- yazi-core/src/mgr/commands/create.rs | 13 ++++++------- yazi-core/src/mgr/commands/open.rs | 8 +++----- yazi-core/src/mgr/commands/remove.rs | 14 +++++++------- yazi-core/src/mgr/commands/rename.rs | 8 +++----- yazi-core/src/tab/commands/cd.rs | 6 +++--- yazi-core/src/tab/commands/filter.rs | 6 +++--- yazi-core/src/tab/commands/find.rs | 6 +++--- yazi-core/src/tab/commands/search.rs | 14 ++++---------- yazi-core/src/tab/commands/shell.rs | 13 +++++++++---- yazi-proxy/src/options/search.rs | 20 ++++++++------------ yazi-proxy/src/tab.rs | 4 +++- 11 files changed, 52 insertions(+), 60 deletions(-) diff --git a/yazi-core/src/mgr/commands/create.rs b/yazi-core/src/mgr/commands/create.rs index 7058892c..38541db3 100644 --- a/yazi-core/src/mgr/commands/create.rs +++ b/yazi-core/src/mgr/commands/create.rs @@ -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; }); } diff --git a/yazi-core/src/mgr/commands/open.rs b/yazi-core/src/mgr/commands/open.rs index 71bcbbd1..232c7fb4 100644 --- a/yazi-core/src/mgr/commands/open.rs +++ b/yazi-core/src/mgr/commands/open.rs @@ -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); } }); diff --git a/yazi-core/src/mgr/commands/remove.rs b/yazi-core/src/mgr/commands/remove.rs index 9f9ce19b..19a27289 100644 --- a/yazi-core/src/mgr/commands/remove.rs +++ b/yazi-core/src/mgr/commands/remove.rs @@ -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); } }); diff --git a/yazi-core/src/mgr/commands/rename.rs b/yazi-core/src/mgr/commands/rename.rs index 4a9bb4ba..bf6e809d 100644 --- a/yazi-core/src/mgr/commands/rename.rs +++ b/yazi-core/src/mgr/commands/rename.rs @@ -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; } diff --git a/yazi-core/src/tab/commands/cd.rs b/yazi-core/src/tab/commands/cd.rs index ffb36330..6ee5b27d 100644 --- a/yazi-core/src/tab/commands/cd.rs +++ b/yazi-core/src/tab/commands/cd.rs @@ -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 { diff --git a/yazi-core/src/tab/commands/filter.rs b/yazi-core/src/tab/commands/filter.rs index e0b93078..8682b14a 100644 --- a/yazi-core/src/tab/commands/filter.rs +++ b/yazi-core/src/tab/commands/filter.rs @@ -30,10 +30,10 @@ impl From 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 { diff --git a/yazi-core/src/tab/commands/find.rs b/yazi-core/src/tab/commands/find.rs index d301d554..5fc235bb 100644 --- a/yazi-core/src/tab/commands/find.rs +++ b/yazi-core/src/tab/commands/find.rs @@ -25,10 +25,10 @@ impl From 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 { diff --git a/yazi-core/src/tab/commands/search.rs b/yazi-core/src/tab/commands/search.rs index 09ac84fd..a30e9216 100644 --- a/yazi-core/src/tab/commands/search.rs +++ b/yazi-core/src/tab/commands/search.rs @@ -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) { - let Ok(mut opt) = opt.try_into() else { + let Ok(mut opt): Result = 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)); diff --git a/yazi-core/src/tab/commands/shell.rs b/yazi-core/src/tab/commands/shell.rs index 87d083da..ee0d3dc3 100644 --- a/yazi-core/src/tab/commands/shell.rs +++ b/yazi-core/src/tab/commands/shell.rs @@ -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, } diff --git a/yazi-proxy/src/options/search.rs b/yazi-proxy/src/options/search.rs index 7c829109..abbaf1a0 100644 --- a/yazi-proxy/src/options/search.rs +++ b/yazi-proxy/src/options/search.rs @@ -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 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 for SearchOptVia { + fn as_ref(&self) -> &str { + match self { Self::Rg => "rg", - Self::Fd => "fd", Self::Rga => "rga", - Self::None => "none", - }) + Self::Fd => "fd", + } } } diff --git a/yazi-proxy/src/tab.rs b/yazi-proxy/src/tab.rs index 7c3c2dc4..cf7fee1c 100644 --- a/yazi-proxy/src/tab.rs +++ b/yazi-proxy/src/tab.rs @@ -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) )); } }