mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-22 23:31:05 +00:00
feat: support stdin and pipe for Child API (#1033)
This commit is contained in:
parent
07342a29ef
commit
28dfe728ab
4 changed files with 77 additions and 26 deletions
|
|
@ -70,6 +70,7 @@ impl Input {
|
|||
let snap = self.snap_mut();
|
||||
|
||||
match opt.kind.as_str() {
|
||||
"all" => self.kill_range(..),
|
||||
"bol" => {
|
||||
let end = snap.idx(snap.cursor).unwrap_or(snap.len());
|
||||
self.kill_range(..end)
|
||||
|
|
|
|||
|
|
@ -87,16 +87,17 @@ impl Input {
|
|||
}
|
||||
|
||||
pub(super) fn flush_value(&mut self) {
|
||||
let Some(tx) = &self.callback else { return };
|
||||
self.ticket = self.ticket.wrapping_add(1);
|
||||
|
||||
if self.realtime {
|
||||
let value = self.snap().value.clone();
|
||||
self.callback.as_ref().unwrap().send(Err(InputError::Typed(value))).ok();
|
||||
tx.send(Err(InputError::Typed(value))).ok();
|
||||
}
|
||||
|
||||
if self.completion {
|
||||
let before = self.partition()[0].to_owned();
|
||||
self.callback.as_ref().unwrap().send(Err(InputError::Completed(before, self.ticket))).ok();
|
||||
tx.send(Err(InputError::Completed(before, self.ticket))).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use futures::future::try_join3;
|
||||
use mlua::{AnyUserData, IntoLuaMulti, Table, UserData, Value};
|
||||
use tokio::{io::{self, AsyncBufReadExt, AsyncReadExt, BufReader}, process::{ChildStderr, ChildStdin, ChildStdout}, select};
|
||||
use mlua::{AnyUserData, ExternalError, IntoLua, IntoLuaMulti, Table, UserData, Value};
|
||||
use tokio::{io::{self, AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader, BufWriter}, process::{ChildStderr, ChildStdin, ChildStdout}, select};
|
||||
|
||||
use super::Status;
|
||||
use crate::process::Output;
|
||||
|
||||
pub struct Child {
|
||||
inner: tokio::process::Child,
|
||||
_stdin: Option<ChildStdin>,
|
||||
stdin: Option<BufWriter<ChildStdin>>,
|
||||
stdout: Option<BufReader<ChildStdout>>,
|
||||
stderr: Option<BufReader<ChildStderr>>,
|
||||
}
|
||||
|
||||
impl Child {
|
||||
pub fn new(mut inner: tokio::process::Child) -> Self {
|
||||
let stdin = inner.stdin.take();
|
||||
let stdin = inner.stdin.take().map(BufWriter::new);
|
||||
let stdout = inner.stdout.take().map(BufReader::new);
|
||||
let stderr = inner.stderr.take().map(BufReader::new);
|
||||
Self { inner, _stdin: stdin, stdout, stderr }
|
||||
Self { inner, stdin, stdout, stderr }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,6 +69,26 @@ impl UserData for Child {
|
|||
Err(_) => Ok((String::new(), 3u8)),
|
||||
}
|
||||
});
|
||||
|
||||
methods.add_async_method_mut("write_all", |lua, me, src: mlua::String| async move {
|
||||
let Some(stdin) = &mut me.stdin else {
|
||||
return Err("stdin is not piped".into_lua_err());
|
||||
};
|
||||
match stdin.write_all(src.as_bytes()).await {
|
||||
Ok(()) => (true, Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
});
|
||||
methods.add_async_method_mut("flush", |lua, me, ()| async move {
|
||||
let Some(stdin) = &mut me.stdin else {
|
||||
return Err("stdin is not piped".into_lua_err());
|
||||
};
|
||||
match stdin.flush().await {
|
||||
Ok(()) => (true, Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
});
|
||||
|
||||
methods.add_async_method_mut("wait", |lua, me, ()| async move {
|
||||
match me.inner.wait().await {
|
||||
Ok(status) => (Status::new(status), Value::Nil).into_lua_multi(lua),
|
||||
|
|
@ -107,5 +127,18 @@ impl UserData for Child {
|
|||
Ok(_) => (true, Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
|
||||
});
|
||||
|
||||
methods.add_method_mut("take_stdin", |lua, me, ()| match me.stdin.take() {
|
||||
Some(stdin) => lua.create_any_userdata(stdin.into_inner())?.into_lua(lua),
|
||||
None => Ok(Value::Nil),
|
||||
});
|
||||
methods.add_method_mut("take_stdout", |lua, me, ()| match me.stdout.take() {
|
||||
Some(stdout) => lua.create_any_userdata(stdout.into_inner())?.into_lua(lua),
|
||||
None => Ok(Value::Nil),
|
||||
});
|
||||
methods.add_method_mut("take_stderr", |lua, me, ()| match me.stderr.take() {
|
||||
Some(stderr) => lua.create_any_userdata(stderr.into_inner())?.into_lua(lua),
|
||||
None => Ok(Value::Nil),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::process::Stdio;
|
||||
|
||||
use mlua::{AnyUserData, IntoLuaMulti, Lua, Table, UserData, Value};
|
||||
use mlua::{AnyUserData, ExternalError, IntoLuaMulti, Lua, Table, UserData, Value};
|
||||
use tokio::process::{ChildStderr, ChildStdin, ChildStdout};
|
||||
|
||||
use super::{output::Output, Child};
|
||||
|
||||
|
|
@ -36,6 +37,33 @@ impl Command {
|
|||
|
||||
impl UserData for Command {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
#[inline]
|
||||
fn make_stdio(v: Value) -> mlua::Result<Stdio> {
|
||||
match v {
|
||||
Value::Integer(n) => {
|
||||
return Ok(match n as u8 {
|
||||
PIPED => Stdio::piped(),
|
||||
INHERIT => Stdio::inherit(),
|
||||
_ => Stdio::null(),
|
||||
});
|
||||
}
|
||||
Value::UserData(ud) => {
|
||||
if let Ok(stdin) = ud.take::<ChildStdin>() {
|
||||
return Ok(stdin.try_into()?);
|
||||
} else if let Ok(stdout) = ud.take::<ChildStdout>() {
|
||||
return Ok(stdout.try_into()?);
|
||||
} else if let Ok(stderr) = ud.take::<ChildStderr>() {
|
||||
return Ok(stderr.try_into()?);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Err(
|
||||
"must be one of Command.NULL, Command.PIPED, Command.INHERIT, or a ChildStdin, ChildStdout, or ChildStderr".into_lua_err(),
|
||||
)
|
||||
}
|
||||
|
||||
methods.add_function("arg", |_, (ud, arg): (AnyUserData, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?.inner.arg(arg.to_string_lossy().as_ref());
|
||||
Ok(ud)
|
||||
|
|
@ -62,28 +90,16 @@ impl UserData for Command {
|
|||
Ok(ud)
|
||||
},
|
||||
);
|
||||
methods.add_function("stdin", |_, (ud, stdio): (AnyUserData, u8)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stdin(match stdio {
|
||||
PIPED => Stdio::piped(),
|
||||
INHERIT => Stdio::inherit(),
|
||||
_ => Stdio::null(),
|
||||
});
|
||||
methods.add_function("stdin", |_, (ud, stdio): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stdin(make_stdio(stdio)?);
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function("stdout", |_, (ud, stdio): (AnyUserData, u8)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stdout(match stdio {
|
||||
PIPED => Stdio::piped(),
|
||||
INHERIT => Stdio::inherit(),
|
||||
_ => Stdio::null(),
|
||||
});
|
||||
methods.add_function("stdout", |_, (ud, stdio): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stdout(make_stdio(stdio)?);
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function("stderr", |_, (ud, stdio): (AnyUserData, u8)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stderr(match stdio {
|
||||
PIPED => Stdio::piped(),
|
||||
INHERIT => Stdio::inherit(),
|
||||
_ => Stdio::null(),
|
||||
});
|
||||
methods.add_function("stderr", |_, (ud, stdio): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stderr(make_stdio(stdio)?);
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_method_mut("spawn", |lua, me, ()| match me.inner.spawn() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue