mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-24 00:01:03 +00:00
feat: new orphan option for opener rules, to keep the process running even when Yazi exited (#216)
This commit is contained in:
parent
e2ead7eecb
commit
d3ed8e7cf8
6 changed files with 41 additions and 13 deletions
|
|
@ -4,6 +4,7 @@ use serde::{Deserialize, Deserializer};
|
|||
pub struct Opener {
|
||||
pub exec: String,
|
||||
pub block: bool,
|
||||
pub orphan: bool,
|
||||
pub display_name: String,
|
||||
pub spread: bool,
|
||||
}
|
||||
|
|
@ -18,6 +19,8 @@ impl<'de> Deserialize<'de> for Opener {
|
|||
pub exec: String,
|
||||
#[serde(default)]
|
||||
pub block: bool,
|
||||
#[serde(default)]
|
||||
pub orphan: bool,
|
||||
pub display_name: Option<String>,
|
||||
}
|
||||
|
||||
|
|
@ -32,6 +35,6 @@ impl<'de> Deserialize<'de> for Opener {
|
|||
.unwrap_or_else(|| shadow.exec.split_whitespace().next().unwrap().to_string());
|
||||
|
||||
let spread = shadow.exec.contains("$*") || shadow.exec.contains("$@");
|
||||
Ok(Self { exec: shadow.exec, block: shadow.block, display_name, spread })
|
||||
Ok(Self { exec: shadow.exec, block: shadow.block, orphan: shadow.orphan, display_name, spread })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
core/src/external/shell.rs
vendored
16
core/src/external/shell.rs
vendored
|
|
@ -4,9 +4,17 @@ use anyhow::Result;
|
|||
use tokio::process::{Child, Command};
|
||||
|
||||
pub struct ShellOpt {
|
||||
pub cmd: OsString,
|
||||
pub args: Vec<OsString>,
|
||||
pub piped: bool,
|
||||
pub cmd: OsString,
|
||||
pub args: Vec<OsString>,
|
||||
pub piped: bool,
|
||||
pub orphan: bool,
|
||||
}
|
||||
|
||||
impl ShellOpt {
|
||||
pub fn with_piped(mut self) -> Self {
|
||||
self.piped = true;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shell(opt: ShellOpt) -> Result<Child> {
|
||||
|
|
@ -21,7 +29,7 @@ pub fn shell(opt: ShellOpt) -> Result<Child> {
|
|||
.stdin(if opt.piped { Stdio::piped() } else { Stdio::inherit() })
|
||||
.stdout(if opt.piped { Stdio::piped() } else { Stdio::inherit() })
|
||||
.stderr(if opt.piped { Stdio::piped() } else { Stdio::inherit() })
|
||||
.kill_on_drop(true)
|
||||
.kill_on_drop(!opt.orphan)
|
||||
.spawn()?,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,9 +259,10 @@ impl Manager {
|
|||
emit!(Stop(true)).await;
|
||||
|
||||
let mut child = external::shell(ShellOpt {
|
||||
cmd: (*opener.exec).into(),
|
||||
args: vec![tmp.to_owned().into()],
|
||||
piped: false,
|
||||
cmd: (*opener.exec).into(),
|
||||
args: vec![tmp.to_owned().into()],
|
||||
piped: false,
|
||||
orphan: false,
|
||||
})?;
|
||||
child.wait().await?;
|
||||
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ impl Tab {
|
|||
|
||||
emit!(Open(
|
||||
selected,
|
||||
Some(Opener { exec, block, display_name: Default::default(), spread: true })
|
||||
Some(Opener { exec, block, orphan: false, display_name: Default::default(), spread: true })
|
||||
));
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ impl Scheduler {
|
|||
cmd: opener.exec.into(),
|
||||
args,
|
||||
block: opener.block,
|
||||
orphan: opener.orphan,
|
||||
cancel: cancel_tx,
|
||||
})
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::ffi::OsString;
|
||||
use std::{ffi::OsString, mem};
|
||||
|
||||
use anyhow::Result;
|
||||
use tokio::{io::{AsyncBufReadExt, BufReader}, select, sync::{mpsc, oneshot}};
|
||||
|
|
@ -16,9 +16,21 @@ pub(crate) struct ProcessOpOpen {
|
|||
pub cmd: OsString,
|
||||
pub args: Vec<OsString>,
|
||||
pub block: bool,
|
||||
pub orphan: bool,
|
||||
pub cancel: oneshot::Sender<()>,
|
||||
}
|
||||
|
||||
impl From<&mut ProcessOpOpen> for ShellOpt {
|
||||
fn from(value: &mut ProcessOpOpen) -> Self {
|
||||
Self {
|
||||
cmd: mem::take(&mut value.cmd),
|
||||
args: mem::take(&mut value.args),
|
||||
piped: false,
|
||||
orphan: value.orphan,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Process {
|
||||
pub(crate) fn new(sch: mpsc::UnboundedSender<TaskOp>) -> Self { Self { sch } }
|
||||
|
||||
|
|
@ -33,7 +45,7 @@ impl Process {
|
|||
let _guard = BLOCKER.acquire().await.unwrap();
|
||||
emit!(Stop(true)).await;
|
||||
|
||||
match external::shell(ShellOpt { cmd: task.cmd, args: task.args, piped: false }) {
|
||||
match external::shell(ShellOpt::from(&mut task)) {
|
||||
Ok(mut child) => {
|
||||
child.wait().await.ok();
|
||||
}
|
||||
|
|
@ -48,13 +60,16 @@ impl Process {
|
|||
}
|
||||
|
||||
self.sch.send(TaskOp::New(task.id, 0))?;
|
||||
let mut child = external::shell(ShellOpt { cmd: task.cmd, args: task.args, piped: true })?;
|
||||
let mut child = external::shell(ShellOpt::from(&mut task).with_piped())?;
|
||||
|
||||
let mut stdout = BufReader::new(child.stdout.take().unwrap()).lines();
|
||||
let mut stderr = BufReader::new(child.stderr.take().unwrap()).lines();
|
||||
loop {
|
||||
select! {
|
||||
_ = task.cancel.closed() => break,
|
||||
_ = task.cancel.closed() => {
|
||||
child.start_kill().ok();
|
||||
break;
|
||||
}
|
||||
Ok(Some(line)) = stdout.next_line() => {
|
||||
self.log(task.id, line)?;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue