//! Rhai wrappers for Process module functions //! //! This module provides Rhai wrappers for the functions in the Process module. use rhai::{Engine, EvalAltResult, Array, Dynamic, Map}; use crate::process::{self, CommandResult, ProcessInfo, RunError, ProcessError}; /// Register Process module functions with the Rhai engine /// /// # Arguments /// /// * `engine` - The Rhai engine to register the functions with /// /// # Returns /// /// * `Result<(), Box>` - Ok if registration was successful, Err otherwise pub fn register_process_module(engine: &mut Engine) -> Result<(), Box> { // Register types register_process_types(engine)?; // Register run functions engine.register_fn("run", run); engine.register_fn("run_silent", run_silent); engine.register_fn("run_with_options", run_with_options); engine.register_fn("new_run_options", new_run_options); // Register process management functions engine.register_fn("which", which); engine.register_fn("kill", kill); engine.register_fn("process_list", process_list); engine.register_fn("process_get", process_get); Ok(()) } /// Register Process module types with the Rhai engine fn register_process_types(engine: &mut Engine) -> Result<(), Box> { // Register CommandResult type and methods engine.register_type_with_name::("CommandResult"); // Register getters for CommandResult properties engine.register_get("stdout", |r: &mut CommandResult| r.stdout.clone()); engine.register_get("stderr", |r: &mut CommandResult| r.stderr.clone()); engine.register_get("success", |r: &mut CommandResult| r.success); engine.register_get("code", |r: &mut CommandResult| r.code); // Register ProcessInfo type and methods engine.register_type_with_name::("ProcessInfo"); // Register getters for ProcessInfo properties engine.register_get("pid", |p: &mut ProcessInfo| p.pid); engine.register_get("name", |p: &mut ProcessInfo| p.name.clone()); engine.register_get("memory", |p: &mut ProcessInfo| p.memory); engine.register_get("cpu", |p: &mut ProcessInfo| p.cpu); Ok(()) } // Helper functions for error conversion fn run_error_to_rhai_error(result: Result) -> Result> { result.map_err(|e| { Box::new(EvalAltResult::ErrorRuntime( format!("Run error: {}", e).into(), rhai::Position::NONE )) }) } fn process_error_to_rhai_error(result: Result) -> Result> { result.map_err(|e| { Box::new(EvalAltResult::ErrorRuntime( format!("Process error: {}", e).into(), rhai::Position::NONE )) }) } /// Create a new Map with default run options pub fn new_run_options() -> Map { let mut map = Map::new(); map.insert("die".into(), Dynamic::from(true)); map.insert("silent".into(), Dynamic::from(false)); map.insert("async_exec".into(), Dynamic::from(false)); map.insert("log".into(), Dynamic::from(false)); map } // // Run Function Wrappers // /// Wrapper for process::run_command /// /// Run a command or multiline script with arguments. pub fn run(command: &str) -> Result> { run_error_to_rhai_error(process::run_command(command)) } /// Wrapper for process::run_silent /// /// Run a command or multiline script with arguments silently. pub fn run_silent(command: &str) -> Result> { run_error_to_rhai_error(process::run_silent(command)) } /// Run a command with options specified in a Map /// /// This provides a builder-style interface for Rhai scripts. /// /// # Example /// /// ```rhai /// let options = new_run_options(); /// options.die = false; /// options.silent = true; /// let result = run("echo Hello", options); /// ``` pub fn run_with_options(command: &str, options: Map) -> Result> { let mut builder = process::run(command); // Apply options from the map if let Some(die) = options.get("die") { if let Ok(die_val) = die.clone().as_bool() { builder = builder.die(die_val); } } if let Some(silent) = options.get("silent") { if let Ok(silent_val) = silent.clone().as_bool() { builder = builder.silent(silent_val); } } if let Some(async_exec) = options.get("async_exec") { if let Ok(async_val) = async_exec.clone().as_bool() { builder = builder.async_exec(async_val); } } if let Some(log) = options.get("log") { if let Ok(log_val) = log.clone().as_bool() { builder = builder.log(log_val); } } // Execute the command run_error_to_rhai_error(builder.execute()) } // // Process Management Function Wrappers // /// Wrapper for process::which /// /// Check if a command exists in PATH. pub fn which(cmd: &str) -> Dynamic { match process::which(cmd) { Some(path) => path.into(), None => Dynamic::UNIT } } /// Wrapper for process::kill /// /// Kill processes matching a pattern. pub fn kill(pattern: &str) -> Result> { process_error_to_rhai_error(process::kill(pattern)) } /// Wrapper for process::process_list /// /// List processes matching a pattern (or all if pattern is empty). pub fn process_list(pattern: &str) -> Result> { let processes = process_error_to_rhai_error(process::process_list(pattern))?; // Convert Vec to Rhai Array let mut array = Array::new(); for process in processes { array.push(Dynamic::from(process)); } Ok(array) } /// Wrapper for process::process_get /// /// Get a single process matching the pattern (error if 0 or more than 1 match). pub fn process_get(pattern: &str) -> Result> { process_error_to_rhai_error(process::process_get(pattern)) }