mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: improve Command implementation and error handling
- Replace raw_set with set for safer global table manipulation - Add proper error handling for UserData type matching in make_stdio - Use to_str() instead of to_string_lossy() for proper UTF-8 validation - Improve code organization and readability - Add missing lua context parameter in command constructor - Remove redundant braces in args method These changes make the Command implementation more robust and safer to use while maintaining the existing functionality. The improved error handling will help catch potential issues earlier in the development process.
This commit is contained in:
parent
ef1a31a274
commit
abf5af727f
1 changed files with 106 additions and 102 deletions
|
|
@ -1,13 +1,11 @@
|
|||
use std::process::Stdio;
|
||||
|
||||
use mlua::{AnyUserData, ExternalError, IntoLuaMulti, Lua, Table, UserData, Value};
|
||||
use tokio::process::{ChildStderr, ChildStdin, ChildStdout};
|
||||
|
||||
use super::{Child, output::Output};
|
||||
use crate::process::Status;
|
||||
|
||||
pub struct Command {
|
||||
inner: tokio::process::Command,
|
||||
inner: tokio::process::Command,
|
||||
}
|
||||
|
||||
const NULL: u8 = 0;
|
||||
|
|
@ -15,109 +13,115 @@ const PIPED: u8 = 1;
|
|||
const INHERIT: u8 = 2;
|
||||
|
||||
impl Command {
|
||||
pub fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
let new = lua.create_function(|_, (_, program): (Table, String)| {
|
||||
let mut inner = tokio::process::Command::new(program);
|
||||
inner.kill_on_drop(true).stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null());
|
||||
pub fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
let new = lua.create_function(|lua, (table, program): (Table, String)| {
|
||||
let mut inner = tokio::process::Command::new(program);
|
||||
inner.kill_on_drop(true)
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null());
|
||||
Ok(Command { inner })
|
||||
})?;
|
||||
|
||||
Ok(Self { inner })
|
||||
})?;
|
||||
let command = lua.create_table_from([
|
||||
("NULL", NULL),
|
||||
("PIPED", PIPED),
|
||||
("INHERIT", INHERIT),
|
||||
])?;
|
||||
|
||||
let command = lua.create_table_from([
|
||||
// Stdio
|
||||
("NULL", NULL),
|
||||
("PIPED", PIPED),
|
||||
("INHERIT", INHERIT),
|
||||
])?;
|
||||
|
||||
command.set_metatable(Some(lua.create_table_from([("__call", new)])?));
|
||||
|
||||
lua.globals().raw_set("Command", command)
|
||||
}
|
||||
command.set_metatable(Some(lua.create_table_from([("__call", new)])?));
|
||||
lua.globals().set("Command", 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()?);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
fn make_stdio(v: Value) -> mlua::Result<Stdio> {
|
||||
match v {
|
||||
Value::Integer(n) => {
|
||||
Ok(match n as u8 {
|
||||
PIPED => Stdio::piped(),
|
||||
INHERIT => Stdio::inherit(),
|
||||
_ => Stdio::null(),
|
||||
})
|
||||
}
|
||||
Value::UserData(ud) => {
|
||||
if let Ok(stdin) = ud.take::<ChildStdin>() {
|
||||
Ok(stdin.try_into()?)
|
||||
} else if let Ok(stdout) = ud.take::<ChildStdout>() {
|
||||
Ok(stdout.try_into()?)
|
||||
} else if let Ok(stderr) = ud.take::<ChildStderr>() {
|
||||
Ok(stderr.try_into()?)
|
||||
} else {
|
||||
Err("Invalid userdata type".into_lua_err())
|
||||
}
|
||||
}
|
||||
_ => Err(
|
||||
"must be one of Command.NULL, Command.PIPED, Command.INHERIT, or a ChildStdin, ChildStdout, or ChildStderr".into_lua_err(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Err(
|
||||
"must be one of Command.NULL, Command.PIPED, Command.INHERIT, or a ChildStdin, ChildStdout, or ChildStderr".into_lua_err(),
|
||||
)
|
||||
}
|
||||
methods.add_function_mut("arg", |_, (ud, arg): (AnyUserData, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?.inner.arg(arg.to_str()?);
|
||||
Ok(ud)
|
||||
});
|
||||
|
||||
methods.add_function_mut("arg", |_, (ud, arg): (AnyUserData, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?.inner.arg(arg.to_string_lossy().as_ref());
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function_mut("args", |_, (ud, args): (AnyUserData, Vec<mlua::String>)| {
|
||||
{
|
||||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
for arg in args {
|
||||
me.inner.arg(arg.to_string_lossy().as_ref());
|
||||
}
|
||||
}
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function_mut("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?);
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function_mut(
|
||||
"env",
|
||||
|_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?
|
||||
.inner
|
||||
.env(key.to_string_lossy().as_ref(), value.to_string_lossy().as_ref());
|
||||
Ok(ud)
|
||||
},
|
||||
);
|
||||
methods.add_function_mut("stdin", |_, (ud, stdio): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stdin(make_stdio(stdio)?);
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function_mut("stdout", |_, (ud, stdio): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stdout(make_stdio(stdio)?);
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function_mut("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() {
|
||||
Ok(child) => (Child::new(child), Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
});
|
||||
methods.add_async_method_mut("output", |lua, me, ()| async move {
|
||||
match me.inner.output().await {
|
||||
Ok(output) => (Output::new(output), Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
});
|
||||
methods.add_async_method_mut("status", |lua, me, ()| async move {
|
||||
match me.inner.status().await {
|
||||
Ok(status) => (Status::new(status), Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
});
|
||||
}
|
||||
methods.add_function_mut("args", |_, (ud, args): (AnyUserData, Vec<mlua::String>)| {
|
||||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
for arg in args {
|
||||
me.inner.arg(arg.to_str()?);
|
||||
}
|
||||
Ok(ud)
|
||||
});
|
||||
|
||||
methods.add_function_mut("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?);
|
||||
Ok(ud)
|
||||
});
|
||||
|
||||
methods.add_function_mut(
|
||||
"env",
|
||||
|_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?
|
||||
.inner
|
||||
.env(key.to_str()?, value.to_str()?);
|
||||
Ok(ud)
|
||||
},
|
||||
);
|
||||
|
||||
methods.add_function_mut("stdin", |_, (ud, stdio): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stdin(make_stdio(stdio)?);
|
||||
Ok(ud)
|
||||
});
|
||||
|
||||
methods.add_function_mut("stdout", |_, (ud, stdio): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stdout(make_stdio(stdio)?);
|
||||
Ok(ud)
|
||||
});
|
||||
|
||||
methods.add_function_mut("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() {
|
||||
Ok(child) => (Child::new(child), Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
});
|
||||
|
||||
methods.add_async_method_mut("output", |lua, me, ()| async move {
|
||||
match me.inner.output().await {
|
||||
Ok(output) => (Output::new(output), Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
});
|
||||
|
||||
methods.add_async_method_mut("status", |lua, me, ()| async move {
|
||||
match me.inner.status().await {
|
||||
Ok(status) => (Status::new(status), Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue