yazi/yazi-actor/src/mgr/search.rs
三咲雅 misaki masa 58f1013348
Some checks failed
Cachix / Publish Flake (push) Has been cancelled
Check / clippy (push) Has been cancelled
Check / rustfmt (push) Has been cancelled
Check / stylua (push) Has been cancelled
Draft / build-unix (gcc-aarch64-linux-gnu, ubuntu-latest, aarch64-unknown-linux-gnu) (push) Has been cancelled
Draft / build-unix (gcc-i686-linux-gnu, ubuntu-latest, i686-unknown-linux-gnu) (push) Has been cancelled
Draft / build-unix (gcc-riscv64-linux-gnu, ubuntu-latest, riscv64gc-unknown-linux-gnu) (push) Has been cancelled
Draft / build-unix (gcc-sparc64-linux-gnu, ubuntu-latest, sparc64-unknown-linux-gnu) (push) Has been cancelled
Draft / build-unix (macos-latest, aarch64-apple-darwin) (push) Has been cancelled
Draft / build-unix (macos-latest, x86_64-apple-darwin) (push) Has been cancelled
Draft / build-unix (ubuntu-latest, x86_64-unknown-linux-gnu) (push) Has been cancelled
Draft / build-windows (windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
Draft / build-windows (windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
Draft / build-musl (aarch64-unknown-linux-musl) (push) Has been cancelled
Draft / build-musl (x86_64-unknown-linux-musl) (push) Has been cancelled
Draft / build-snap (amd64, ubuntu-latest) (push) Has been cancelled
Draft / build-snap (arm64, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (macos-latest) (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
Test / test (windows-latest) (push) Has been cancelled
Draft / snap (push) Has been cancelled
Draft / draft (push) Has been cancelled
Draft / nightly (push) Has been cancelled
feat: trash bin (#4144)
2026-07-23 01:59:39 +08:00

125 lines
3 KiB
Rust

use std::{borrow::Cow, time::Duration};
use anyhow::Result;
use tokio::pin;
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
use yazi_config::YAZI;
use yazi_core::mgr::{CdSource, SearchVia};
use yazi_fs::{FilesOp, cha::ChaType, file::File};
use yazi_macro::{act, input, succ};
use yazi_parser::{VoidForm, mgr::SearchForm};
use yazi_plugin::external;
use yazi_proxy::MgrProxy;
use yazi_scheduler::NotifyProxy;
use yazi_shared::{data::Data, url::{AsUrl, UrlLike}};
use yazi_widgets::input::InputEvent;
use crate::{Actor, Ctx};
pub struct Search;
impl Actor for Search {
type Form = SearchForm;
const NAME: &str = "search";
fn act(cx: &mut Ctx, Self::Form { mut opt }: Self::Form) -> Result<Data> {
if let Some(handle) = cx.tab_mut().search.take() {
handle.abort();
}
let mut input = input!(cx, YAZI.input.search(opt.via.into()).with_value(&*opt.subject))?;
tokio::spawn(async move {
if let Some(InputEvent::Submit(subject)) = input.recv().await {
opt.subject = Cow::Owned(subject);
MgrProxy::search_do(opt);
}
});
succ!();
}
}
// --- Do
pub struct SearchDo;
impl Actor for SearchDo {
type Form = SearchForm;
const NAME: &str = "search_do";
fn act(cx: &mut Ctx, Self::Form { opt }: Self::Form) -> Result<Data> {
let tab = cx.tab_mut();
if let Some(handle) = tab.search.take() {
handle.abort();
}
let hidden = tab.pref.show_hidden;
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"));
};
tab.search = Some(tokio::spawn(async move {
let rx = match opt.via {
SearchVia::Rg => external::rg(external::RgOpt {
cwd: cwd.clone(),
hidden,
subject: opt.subject.into_owned(),
args: opt.args,
}),
SearchVia::Rga => external::rga(external::RgaOpt {
cwd: cwd.clone(),
hidden,
subject: opt.subject.into_owned(),
args: opt.args,
}),
SearchVia::Fd => external::fd(external::FdOpt {
cwd: cwd.clone(),
hidden,
subject: opt.subject.into_owned(),
args: opt.args,
}),
}?;
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(5000, Duration::from_millis(500));
pin!(rx);
let ((), ticket) = (MgrProxy::cd(&cwd, CdSource::Search), FilesOp::prepare(&cwd));
while let Some(chunk) = rx.next().await {
FilesOp::Part(cwd.clone(), chunk, ticket).emit();
}
FilesOp::Done(File::from_dummy(cwd, Some(ChaType::Dir)), ticket).emit();
Ok(())
}));
succ!();
}
}
// --- Stop
pub struct SearchStop;
impl Actor for SearchStop {
type Form = VoidForm;
const NAME: &str = "search_stop";
fn act(cx: &mut Ctx, _: Self::Form) -> Result<Data> {
let tab = cx.tab_mut();
if let Some(handle) = tab.search.take() {
handle.abort();
}
if !tab.cwd().is_search() {
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))
}
}
}