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 std::process::Stdio;
|
||||||
|
|
||||||
use mlua::{AnyUserData, ExternalError, IntoLuaMulti, Lua, Table, UserData, Value};
|
use mlua::{AnyUserData, ExternalError, IntoLuaMulti, Lua, Table, UserData, Value};
|
||||||
use tokio::process::{ChildStderr, ChildStdin, ChildStdout};
|
use tokio::process::{ChildStderr, ChildStdin, ChildStdout};
|
||||||
|
|
||||||
use super::{Child, output::Output};
|
use super::{Child, output::Output};
|
||||||
use crate::process::Status;
|
use crate::process::Status;
|
||||||
|
|
||||||
pub struct Command {
|
pub struct Command {
|
||||||
inner: tokio::process::Command,
|
inner: tokio::process::Command,
|
||||||
}
|
}
|
||||||
|
|
||||||
const NULL: u8 = 0;
|
const NULL: u8 = 0;
|
||||||
|
|
@ -15,109 +13,115 @@ const PIPED: u8 = 1;
|
||||||
const INHERIT: u8 = 2;
|
const INHERIT: u8 = 2;
|
||||||
|
|
||||||
impl Command {
|
impl Command {
|
||||||
pub fn install(lua: &Lua) -> mlua::Result<()> {
|
pub fn install(lua: &Lua) -> mlua::Result<()> {
|
||||||
let new = lua.create_function(|_, (_, program): (Table, String)| {
|
let new = lua.create_function(|lua, (table, program): (Table, String)| {
|
||||||
let mut inner = tokio::process::Command::new(program);
|
let mut inner = tokio::process::Command::new(program);
|
||||||
inner.kill_on_drop(true).stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null());
|
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),
|
||||||
let command = lua.create_table_from([
|
("INHERIT", INHERIT),
|
||||||
// Stdio
|
])?;
|
||||||
("NULL", NULL),
|
|
||||||
("PIPED", PIPED),
|
command.set_metatable(Some(lua.create_table_from([("__call", new)])?));
|
||||||
("INHERIT", INHERIT),
|
lua.globals().set("Command", command)
|
||||||
])?;
|
}
|
||||||
|
|
||||||
command.set_metatable(Some(lua.create_table_from([("__call", new)])?));
|
|
||||||
|
|
||||||
lua.globals().raw_set("Command", command)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for Command {
|
impl UserData for Command {
|
||||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
#[inline]
|
fn make_stdio(v: Value) -> mlua::Result<Stdio> {
|
||||||
fn make_stdio(v: Value) -> mlua::Result<Stdio> {
|
match v {
|
||||||
match v {
|
Value::Integer(n) => {
|
||||||
Value::Integer(n) => {
|
Ok(match n as u8 {
|
||||||
return Ok(match n as u8 {
|
PIPED => Stdio::piped(),
|
||||||
PIPED => Stdio::piped(),
|
INHERIT => Stdio::inherit(),
|
||||||
INHERIT => Stdio::inherit(),
|
_ => Stdio::null(),
|
||||||
_ => Stdio::null(),
|
})
|
||||||
});
|
}
|
||||||
}
|
Value::UserData(ud) => {
|
||||||
Value::UserData(ud) => {
|
if let Ok(stdin) = ud.take::<ChildStdin>() {
|
||||||
if let Ok(stdin) = ud.take::<ChildStdin>() {
|
Ok(stdin.try_into()?)
|
||||||
return Ok(stdin.try_into()?);
|
} else if let Ok(stdout) = ud.take::<ChildStdout>() {
|
||||||
} else if let Ok(stdout) = ud.take::<ChildStdout>() {
|
Ok(stdout.try_into()?)
|
||||||
return Ok(stdout.try_into()?);
|
} else if let Ok(stderr) = ud.take::<ChildStderr>() {
|
||||||
} else if let Ok(stderr) = ud.take::<ChildStderr>() {
|
Ok(stderr.try_into()?)
|
||||||
return 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(
|
methods.add_function_mut("arg", |_, (ud, arg): (AnyUserData, mlua::String)| {
|
||||||
"must be one of Command.NULL, Command.PIPED, Command.INHERIT, or a ChildStdin, ChildStdout, or ChildStderr".into_lua_err(),
|
ud.borrow_mut::<Self>()?.inner.arg(arg.to_str()?);
|
||||||
)
|
Ok(ud)
|
||||||
}
|
});
|
||||||
|
|
||||||
methods.add_function_mut("arg", |_, (ud, arg): (AnyUserData, mlua::String)| {
|
methods.add_function_mut("args", |_, (ud, args): (AnyUserData, Vec<mlua::String>)| {
|
||||||
ud.borrow_mut::<Self>()?.inner.arg(arg.to_string_lossy().as_ref());
|
let mut me = ud.borrow_mut::<Self>()?;
|
||||||
Ok(ud)
|
for arg in args {
|
||||||
});
|
me.inner.arg(arg.to_str()?);
|
||||||
methods.add_function_mut("args", |_, (ud, args): (AnyUserData, Vec<mlua::String>)| {
|
}
|
||||||
{
|
Ok(ud)
|
||||||
let mut me = ud.borrow_mut::<Self>()?;
|
});
|
||||||
for arg in args {
|
|
||||||
me.inner.arg(arg.to_string_lossy().as_ref());
|
methods.add_function_mut("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| {
|
||||||
}
|
ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?);
|
||||||
}
|
Ok(ud)
|
||||||
Ok(ud)
|
});
|
||||||
});
|
|
||||||
methods.add_function_mut("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| {
|
methods.add_function_mut(
|
||||||
ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?);
|
"env",
|
||||||
Ok(ud)
|
|_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| {
|
||||||
});
|
ud.borrow_mut::<Self>()?
|
||||||
methods.add_function_mut(
|
.inner
|
||||||
"env",
|
.env(key.to_str()?, value.to_str()?);
|
||||||
|_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| {
|
Ok(ud)
|
||||||
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("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)?);
|
||||||
methods.add_function_mut("stdout", |_, (ud, stdio): (AnyUserData, Value)| {
|
Ok(ud)
|
||||||
ud.borrow_mut::<Self>()?.inner.stdout(make_stdio(stdio)?);
|
});
|
||||||
Ok(ud)
|
|
||||||
});
|
methods.add_function_mut("stderr", |_, (ud, stdio): (AnyUserData, Value)| {
|
||||||
methods.add_function_mut("stderr", |_, (ud, stdio): (AnyUserData, Value)| {
|
ud.borrow_mut::<Self>()?.inner.stderr(make_stdio(stdio)?);
|
||||||
ud.borrow_mut::<Self>()?.inner.stderr(make_stdio(stdio)?);
|
Ok(ud)
|
||||||
Ok(ud)
|
});
|
||||||
});
|
|
||||||
methods.add_method_mut("spawn", |lua, me, ()| match me.inner.spawn() {
|
methods.add_method_mut("spawn", |lua, me, ()| match me.inner.spawn() {
|
||||||
Ok(child) => (Child::new(child), Value::Nil).into_lua_multi(lua),
|
Ok(child) => (Child::new(child), Value::Nil).into_lua_multi(lua),
|
||||||
Err(e) => (Value::Nil, e.raw_os_error()).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 {
|
methods.add_async_method_mut("output", |lua, me, ()| async move {
|
||||||
Ok(output) => (Output::new(output), Value::Nil).into_lua_multi(lua),
|
match me.inner.output().await {
|
||||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
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),
|
methods.add_async_method_mut("status", |lua, me, ()| async move {
|
||||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
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