use crate::error::AndaxRes;
use rhai::{plugin::*, EvalAltResult};
use std::process::Command;
use tracing::{debug, instrument};
macro_rules! _sh_out {
($ctx:expr, $o:expr) => {
Ok((
$o.status.code().ok_or::<Box<EvalAltResult>>("No exit code".into())?,
String::from_utf8($o.stdout).ehdl($ctx)?,
String::from_utf8($o.stderr).ehdl($ctx)?,
))
};
}
macro_rules! _cmd {
($cmd:expr) => {{
let mut x;
if cfg!(target_os = "windows") {
x = Command::new("cmd");
x.args(["/C", $cmd]);
} else {
x = Command::new("sh");
x.args(["-c", $cmd]);
}
x
}};
}
type T = Result<(i32, String, String), Box<EvalAltResult>>;
#[export_module]
pub mod ar {
#[instrument(skip(ctx))]
#[rhai_fn(return_raw, name = "sh")]
pub(crate) fn shell(ctx: NativeCallContext, cmd: &str) -> T {
debug!("Running in shell");
_sh_out!(&ctx, _cmd!(cmd).output().ehdl(&ctx)?)
}
#[instrument(skip(ctx))]
#[rhai_fn(return_raw, name = "sh")]
pub(crate) fn shell_cwd(ctx: NativeCallContext, cmd: &str, cwd: &str) -> T {
debug!("Running in shell");
_sh_out!(&ctx, _cmd!(cmd).current_dir(cwd).output().ehdl(&ctx)?)
}
#[instrument(skip(ctx))]
#[rhai_fn(return_raw, name = "sh")]
pub(crate) fn sh(ctx: NativeCallContext, cmd: Vec<&str>) -> T {
debug!("Running executable");
_sh_out!(&ctx, Command::new(cmd[0]).args(&cmd[1..]).output().ehdl(&ctx)?)
}
#[instrument(skip(ctx))]
#[rhai_fn(return_raw, name = "sh")]
pub(crate) fn sh_cwd(ctx: NativeCallContext, cmd: Vec<&str>, cwd: &str) -> T {
debug!("Running executable");
_sh_out!(&ctx, Command::new(cmd[0]).args(&cmd[1..]).current_dir(cwd).output().ehdl(&ctx)?)
}
#[rhai_fn(return_raw)]
pub(crate) fn ls(
ctx: NativeCallContext,
dir: Option<&str>,
) -> Result<Vec<String>, Box<EvalAltResult>> {
let mut res = vec![];
for dir in std::fs::read_dir(dir.unwrap_or(".")).ehdl(&ctx)? {
res.push(dir.ehdl(&ctx)?.path().to_string_lossy().to_string());
}
Ok(res)
}
}