feat: new orphan option for opener rules, to keep the process running even when Yazi exited

This commit is contained in:
sxyazi 2023-09-23 22:19:35 +08:00
parent ec261a2708
commit 2174f3d536
No known key found for this signature in database
6 changed files with 23 additions and 12 deletions

View file

@ -4,6 +4,7 @@ use serde::{Deserialize, Deserializer};
pub struct Opener { pub struct Opener {
pub exec: String, pub exec: String,
pub block: bool, pub block: bool,
pub orphan: bool,
pub display_name: String, pub display_name: String,
pub spread: bool, pub spread: bool,
} }
@ -18,6 +19,8 @@ impl<'de> Deserialize<'de> for Opener {
pub exec: String, pub exec: String,
#[serde(default)] #[serde(default)]
pub block: bool, pub block: bool,
#[serde(default)]
pub orphan: bool,
pub display_name: Option<String>, 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()); .unwrap_or_else(|| shadow.exec.split_whitespace().next().unwrap().to_string());
let spread = shadow.exec.contains("$*") || shadow.exec.contains("$@"); 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 })
} }
} }

View file

@ -7,6 +7,7 @@ pub struct ShellOpt {
pub cmd: OsString, pub cmd: OsString,
pub args: Vec<OsString>, pub args: Vec<OsString>,
pub piped: bool, pub piped: bool,
pub orphan: bool,
} }
pub fn shell(opt: ShellOpt) -> Result<Child> { pub fn shell(opt: ShellOpt) -> Result<Child> {
@ -21,7 +22,7 @@ pub fn shell(opt: ShellOpt) -> Result<Child> {
.stdin(if opt.piped { Stdio::piped() } else { Stdio::inherit() }) .stdin(if opt.piped { Stdio::piped() } else { Stdio::inherit() })
.stdout(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() }) .stderr(if opt.piped { Stdio::piped() } else { Stdio::inherit() })
.kill_on_drop(true) .kill_on_drop(!opt.orphan)
.spawn()?, .spawn()?,
) )
} }

View file

@ -262,6 +262,7 @@ impl Manager {
cmd: (*opener.exec).into(), cmd: (*opener.exec).into(),
args: vec![tmp.to_owned().into()], args: vec![tmp.to_owned().into()],
piped: false, piped: false,
orphan: false,
})?; })?;
child.wait().await?; child.wait().await?;

View file

@ -379,7 +379,7 @@ impl Tab {
emit!(Open( emit!(Open(
selected, selected,
Some(Opener { exec, block, display_name: Default::default(), spread: true }) Some(Opener { exec, block, orphan: false, display_name: Default::default(), spread: true })
)); ));
}); });

View file

@ -310,6 +310,7 @@ impl Scheduler {
cmd: opener.exec.into(), cmd: opener.exec.into(),
args, args,
block: opener.block, block: opener.block,
orphan: opener.orphan,
cancel: cancel_tx, cancel: cancel_tx,
}) })
.await .await

View file

@ -16,6 +16,7 @@ pub(crate) struct ProcessOpOpen {
pub cmd: OsString, pub cmd: OsString,
pub args: Vec<OsString>, pub args: Vec<OsString>,
pub block: bool, pub block: bool,
pub orphan: bool,
pub cancel: oneshot::Sender<()>, pub cancel: oneshot::Sender<()>,
} }
@ -29,11 +30,12 @@ impl Process {
fn done(&self, id: usize) -> Result<()> { Ok(self.sch.send(TaskOp::Done(id))?) } fn done(&self, id: usize) -> Result<()> { Ok(self.sch.send(TaskOp::Done(id))?) }
pub(crate) async fn open(&self, mut task: ProcessOpOpen) -> Result<()> { pub(crate) async fn open(&self, mut task: ProcessOpOpen) -> Result<()> {
let opt = ShellOpt { cmd: task.cmd, args: task.args, piped: true, orphan: task.orphan };
if task.block { if task.block {
let _guard = BLOCKER.acquire().await.unwrap(); let _guard = BLOCKER.acquire().await.unwrap();
emit!(Stop(true)).await; emit!(Stop(true)).await;
match external::shell(ShellOpt { cmd: task.cmd, args: task.args, piped: false }) { match external::shell(ShellOpt { piped: false, ..opt }) {
Ok(mut child) => { Ok(mut child) => {
child.wait().await.ok(); child.wait().await.ok();
} }
@ -48,13 +50,16 @@ impl Process {
} }
self.sch.send(TaskOp::New(task.id, 0))?; 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(opt)?;
let mut stdout = BufReader::new(child.stdout.take().unwrap()).lines(); let mut stdout = BufReader::new(child.stdout.take().unwrap()).lines();
let mut stderr = BufReader::new(child.stderr.take().unwrap()).lines(); let mut stderr = BufReader::new(child.stderr.take().unwrap()).lines();
loop { loop {
select! { select! {
_ = task.cancel.closed() => break, _ = task.cancel.closed() => {
child.start_kill().ok();
break;
}
Ok(Some(line)) = stdout.next_line() => { Ok(Some(line)) = stdout.next_line() => {
self.log(task.id, line)?; self.log(task.id, line)?;
} }