1use crate::{self as process, CommandResult, ProcessError, ProcessInfo, RunError};
6use rhai::{Array, Dynamic, Engine, EvalAltResult, Map};
7use std::clone::Clone;
8
9pub fn register_process_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
19 engine.register_type_with_name::<CommandResult>("CommandResult");
24 engine.register_get("stdout", |r: &mut CommandResult| r.stdout.clone());
25 engine.register_get("stderr", |r: &mut CommandResult| r.stderr.clone());
26 engine.register_get("success", |r: &mut CommandResult| r.success);
27 engine.register_get("code", |r: &mut CommandResult| r.code);
28
29 engine.register_type_with_name::<ProcessInfo>("ProcessInfo");
31 engine.register_get("pid", |p: &mut ProcessInfo| p.pid);
32 engine.register_get("name", |p: &mut ProcessInfo| p.name.clone());
33 engine.register_get("memory", |p: &mut ProcessInfo| p.memory);
34 engine.register_get("cpu", |p: &mut ProcessInfo| p.cpu);
35
36 engine.register_type_with_name::<RhaiCommandBuilder>("CommandBuilder");
38 engine.register_fn("run", RhaiCommandBuilder::new_rhai); engine.register_fn("silent", RhaiCommandBuilder::silent); engine.register_fn("ignore_error", RhaiCommandBuilder::ignore_error); engine.register_fn("log", RhaiCommandBuilder::log); engine.register_fn("execute", RhaiCommandBuilder::execute_command); engine.register_fn("which", which);
46 engine.register_fn("kill", kill);
47 engine.register_fn("process_list", process_list);
48 engine.register_fn("process_get", process_get);
49
50 engine.register_fn("run_command", run_command);
52 engine.register_fn("run_silent", run_silent);
53 engine.register_fn("run", run_with_options);
54
55 Ok(())
56}
57
58fn run_error_to_rhai_error<T>(result: Result<T, RunError>) -> Result<T, Box<EvalAltResult>> {
60 result.map_err(|e| {
61 Box::new(EvalAltResult::ErrorRuntime(
62 format!("Run error: {}", e).into(),
63 rhai::Position::NONE,
64 ))
65 })
66}
67
68#[derive(Clone)]
70struct RhaiCommandBuilder {
71 command: String,
72 die_on_error: bool,
73 is_silent: bool,
74 enable_log: bool,
75}
76
77impl RhaiCommandBuilder {
78 pub fn new_rhai(command: &str) -> Self {
80 Self {
81 command: command.to_string(),
82 die_on_error: true, is_silent: false,
84 enable_log: false,
85 }
86 }
87
88 pub fn silent(mut self) -> Self {
90 self.is_silent = true;
91 self
92 }
93
94 pub fn ignore_error(mut self) -> Self {
96 self.die_on_error = false;
97 self
98 }
99
100 pub fn log(mut self) -> Self {
102 self.enable_log = true;
103 self
104 }
105
106 pub fn execute_command(self) -> Result<CommandResult, Box<EvalAltResult>> {
108 let builder = process::run(&self.command)
109 .die(self.die_on_error)
110 .silent(self.is_silent)
111 .log(self.enable_log);
112
113 run_error_to_rhai_error(builder.execute())
115 }
116}
117
118fn process_error_to_rhai_error<T>(
119 result: Result<T, ProcessError>,
120) -> Result<T, Box<EvalAltResult>> {
121 result.map_err(|e| {
122 Box::new(EvalAltResult::ErrorRuntime(
123 format!("Process error: {}", e).into(),
124 rhai::Position::NONE,
125 ))
126 })
127}
128
129pub fn which(cmd: &str) -> Dynamic {
137 match process::which(cmd) {
138 Some(path) => path.into(),
139 None => Dynamic::UNIT,
140 }
141}
142
143pub fn kill(pattern: &str) -> Result<String, Box<EvalAltResult>> {
147 process_error_to_rhai_error(process::kill(pattern))
148}
149
150pub fn process_list(pattern: &str) -> Result<Array, Box<EvalAltResult>> {
154 let processes = process_error_to_rhai_error(process::process_list(pattern))?;
155
156 let mut array = Array::new();
158 for process in processes {
159 array.push(Dynamic::from(process));
160 }
161
162 Ok(array)
163}
164
165pub fn process_get(pattern: &str) -> Result<ProcessInfo, Box<EvalAltResult>> {
169 process_error_to_rhai_error(process::process_get(pattern))
170}
171
172pub fn run_command(cmd: &str) -> Result<CommandResult, Box<EvalAltResult>> {
176 run_error_to_rhai_error(process::run(cmd).execute())
177}
178
179pub fn run_silent(cmd: &str) -> Result<CommandResult, Box<EvalAltResult>> {
183 run_error_to_rhai_error(process::run(cmd).silent(true).execute())
184}
185
186pub fn run_with_options(cmd: &str, options: Map) -> Result<CommandResult, Box<EvalAltResult>> {
190 let mut builder = process::run(cmd);
191
192 if let Some(silent) = options.get("silent") {
194 if let Ok(silent_bool) = silent.as_bool() {
195 builder = builder.silent(silent_bool);
196 }
197 }
198
199 if let Some(die) = options.get("die") {
200 if let Ok(die_bool) = die.as_bool() {
201 builder = builder.die(die_bool);
202 }
203 }
204
205 if let Some(log) = options.get("log") {
206 if let Ok(log_bool) = log.as_bool() {
207 builder = builder.log(log_bool);
208 }
209 }
210
211 run_error_to_rhai_error(builder.execute())
212}