diff --git a/yazi-plugin/src/external/shell.rs b/yazi-plugin/src/external/shell.rs index 2b85a757..cc7039b7 100644 --- a/yazi-plugin/src/external/shell.rs +++ b/yazi-plugin/src/external/shell.rs @@ -3,6 +3,7 @@ use std::{env, ffi::OsString, process::Stdio}; use anyhow::Result; use tokio::process::{Child, Command}; +#[derive(Default)] pub struct ShellOpt { pub cmd: OsString, pub args: Vec, diff --git a/yazi-scheduler/src/process/op.rs b/yazi-scheduler/src/process/op.rs index 8436f37a..5275b3fa 100644 --- a/yazi-scheduler/src/process/op.rs +++ b/yazi-scheduler/src/process/op.rs @@ -1,4 +1,4 @@ -use std::{ffi::OsString, mem}; +use std::ffi::OsString; use tokio::sync::oneshot; use yazi_plugin::external::ShellOpt; @@ -13,13 +13,8 @@ pub struct ProcessOpOpen { pub cancel: oneshot::Sender<()>, } -impl From<&mut ProcessOpOpen> for ShellOpt { - fn from(op: &mut ProcessOpOpen) -> Self { - Self { - cmd: mem::take(&mut op.cmd), - args: mem::take(&mut op.args), - piped: false, - orphan: op.orphan, - } +impl From for ShellOpt { + fn from(op: ProcessOpOpen) -> Self { + Self { cmd: op.cmd, args: op.args, piped: false, orphan: op.orphan } } } diff --git a/yazi-scheduler/src/process/process.rs b/yazi-scheduler/src/process/process.rs index 12582964..3d5bf253 100644 --- a/yazi-scheduler/src/process/process.rs +++ b/yazi-scheduler/src/process/process.rs @@ -2,6 +2,7 @@ use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, select, sync::mpsc}; use yazi_plugin::external::{self, ShellOpt}; use yazi_proxy::AppProxy; +use yazi_shared::Defer; use super::ProcessOpOpen; use crate::{TaskProg, BLOCKER}; @@ -14,37 +15,21 @@ impl Process { pub fn new(prog: mpsc::UnboundedSender) -> Self { Self { prog } } pub async fn open(&self, mut task: ProcessOpOpen) -> Result<()> { - let opt = ShellOpt::from(&mut task); if task.block { - let _guard = BLOCKER.acquire().await.unwrap(); - AppProxy::stop().await; - - match external::shell(opt) { - Ok(mut child) => { - child.wait().await.ok(); - self.succ(task.id)?; - } - Err(e) => { - self.prog.send(TaskProg::New(task.id, 0))?; - self.fail(task.id, format!("Failed to spawn process: {e}"))?; - } - } - return Ok(AppProxy::resume()); + return self.open_block(task).await; } if task.orphan { - match external::shell(opt) { - Ok(_) => self.succ(task.id)?, - Err(e) => { - self.prog.send(TaskProg::New(task.id, 0))?; - self.fail(task.id, format!("Failed to spawn process: {e}"))?; - } - } - return Ok(()); + return self.open_orphan(task).await; } self.prog.send(TaskProg::New(task.id, 0))?; - let mut child = external::shell(opt.with_piped())?; + let mut child = external::shell(ShellOpt { + cmd: task.cmd, + args: task.args, + piped: true, + ..Default::default() + })?; let mut stdout = BufReader::new(child.stdout.take().unwrap()).lines(); let mut stderr = BufReader::new(child.stderr.take().unwrap()).lines(); @@ -76,6 +61,43 @@ impl Process { self.prog.send(TaskProg::Adv(task.id, 1, 0))?; self.succ(task.id) } + + async fn open_block(&self, task: ProcessOpOpen) -> Result<()> { + let _guard = BLOCKER.acquire().await.unwrap(); + let _defer = Defer::new(AppProxy::resume); + AppProxy::stop().await; + + let (id, cmd) = (task.id, task.cmd.clone()); + let result = external::shell(task.into()); + if let Err(e) = result { + AppProxy::notify_warn(&cmd.to_string_lossy(), &format!("Failed to spawn process: {e}")); + return self.succ(id); + } + + let status = result.unwrap().wait().await?; + if !status.success() { + let content = match status.code() { + Some(code) => format!("Process exited with status code: {code}"), + None => "Process terminated by signal".to_string(), + }; + AppProxy::notify_warn(&cmd.to_string_lossy(), &content); + } + + self.succ(id) + } + + async fn open_orphan(&self, task: ProcessOpOpen) -> Result<()> { + let id = task.id; + match external::shell(task.into()) { + Ok(_) => self.succ(id)?, + Err(e) => { + self.prog.send(TaskProg::New(id, 0))?; + self.fail(id, format!("Failed to spawn process: {e}"))?; + } + } + + Ok(()) + } } impl Process {