yazi/yazi-actor/src/mgr/open_do.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

81 lines
2.1 KiB
Rust

use anyhow::Result;
use hashbrown::HashMap;
use indexmap::IndexSet;
use yazi_config::{YAZI, opener::OpenerRule};
use yazi_fs::{Splatter, file::File};
use yazi_macro::succ;
use yazi_parser::mgr::OpenDoForm;
use yazi_proxy::{PickProxy, TasksProxy};
use yazi_scheduler::process::ShellOpt;
use yazi_shared::{data::Data, url::UrlBuf};
use crate::{Actor, Ctx};
pub struct OpenDo;
impl Actor for OpenDo {
type Form = OpenDoForm;
const NAME: &str = "open_do";
fn act(cx: &mut Ctx, Self::Form { opt }: Self::Form) -> Result<Data> {
let targets: Vec<_> = opt
.targets
.into_iter()
.map(|file| {
let mime = cx.mgr.mimetype.get(&file.url).unwrap_or_default();
(file, mime)
})
.filter(|(_, m)| !m.is_empty())
.collect();
if targets.is_empty() {
succ!();
} else if !opt.interactive {
succ!(Self::match_and_open(opt.cwd, targets));
}
let openers: IndexSet<_> =
YAZI.open.match_common(&targets).flat_map(|r| YAZI.opener.all(r)).collect();
if openers.is_empty() {
succ!();
}
let pick = PickProxy::show(YAZI.pick.open(openers.iter().map(|o| o.desc()).collect()));
let files: Vec<_> = targets.into_iter().map(|(file, _)| file).collect();
tokio::spawn(async move {
if let Some(choice) = pick.await {
Self::open_with(&openers[choice], &opt.cwd, &files);
}
});
succ!();
}
}
impl OpenDo {
fn match_and_open(cwd: UrlBuf, targets: Vec<(File, &str)>) {
let mut openers: HashMap<_, Vec<_>> = Default::default();
for (file, mime) in targets {
if let Some(open) = YAZI.open.matches(&file, mime)
&& let Some(opener) = YAZI.opener.first(&open)
{
openers.entry(opener).or_default().push(file);
}
}
for (opener, files) in openers {
Self::open_with(&opener, &cwd, &files);
}
}
fn open_with(opener: &OpenerRule, cwd: &UrlBuf, files: &[File]) {
let size = if opener.spread { files.len().max(1) } else { 1 };
for files in files.chunks(size) {
TasksProxy::process_open(ShellOpt {
cwd: cwd.clone(),
cmd: Splatter::new(files).splat(&opener.run),
block: opener.block,
orphan: opener.orphan,
});
}
}
}