Skip to main content

rl_lang/interpreter/stdlib/process/
exec.rs

1use crate::{
2    ast::statements::TypeAnnotation,
3    interpreter::{evaluator::Evaluator, values::Value},
4    utils::{errors::Error, span::Span},
5};
6use std::process::Command;
7
8#[cfg(target_os = "windows")]
9fn shell_command(cmd: &str) -> Command {
10    let mut c = Command::new("cmd");
11    c.args(["/C", cmd]);
12    c
13}
14
15#[cfg(not(target_os = "windows"))]
16fn shell_command(cmd: &str) -> Command {
17    let mut c = Command::new("sh");
18    c.args(["-c", cmd]);
19    c
20}
21
22pub fn std_exec(eval: &mut Evaluator, cmd: String, span: Span) -> Result<Value, Error> {
23    let output = shell_command(&cmd)
24        .output()
25        .map_err(|e| eval.err(format!("exec(): failed to run \"{}\": {}", cmd, e), span))?;
26    let stdout = String::from_utf8_lossy(&output.stdout).to_string();
27    Ok(Value::String(stdout.trim_end_matches('\n').to_string()))
28}
29
30pub fn std_exec_code(eval: &mut Evaluator, cmd: String, span: Span) -> Result<Value, Error> {
31    let status = shell_command(&cmd).status().map_err(|e| {
32        eval.err(
33            format!("exec_code(): failed to run \"{}\": {}", cmd, e),
34            span,
35        )
36    })?;
37    Ok(Value::Integer(status.code().unwrap_or(-1) as i64))
38}
39
40pub fn std_exec_lines(eval: &mut Evaluator, cmd: String, span: Span) -> Result<Value, Error> {
41    let output = shell_command(&cmd).output().map_err(|e| {
42        eval.err(
43            format!("exec_lines(): failed to run \"{}\": {}", cmd, e),
44            span,
45        )
46    })?;
47    let stdout = String::from_utf8_lossy(&output.stdout).to_string();
48    let lines: Vec<Value> = stdout
49        .lines()
50        .map(|l| Value::String(l.to_string()))
51        .collect();
52    Ok(Value::Values {
53        items_type: TypeAnnotation::String,
54        items: lines,
55    })
56}