Add argument handling in extensions
This commit is contained in:
parent
6378aa3bcc
commit
9e5a2a7c95
|
@ -34,7 +34,7 @@ impl super::Extension for RandomExtension {
|
|||
String::from("random")
|
||||
}
|
||||
|
||||
fn calculate(&self, params: &Mapping, _: &Vec<String>) -> Option<String> { // TODO: add argument handling
|
||||
fn calculate(&self, params: &Mapping, args: &Vec<String>) -> Option<String> {
|
||||
let choices = params.get(&Value::from("choices"));
|
||||
if choices.is_none() {
|
||||
warn!("No 'choices' parameter specified for random variable");
|
||||
|
@ -51,7 +51,10 @@ impl super::Extension for RandomExtension {
|
|||
|
||||
match choice {
|
||||
Some(output) => {
|
||||
return Some(output.clone())
|
||||
// Render arguments
|
||||
let output = crate::render::utils::render_args(output, args);
|
||||
|
||||
return Some(output)
|
||||
},
|
||||
None => {
|
||||
error!("Could not select a random choice.");
|
||||
|
@ -91,5 +94,29 @@ mod tests {
|
|||
assert!(choices.iter().any(|x| x == &output));
|
||||
}
|
||||
|
||||
// TODO: add test with arguments
|
||||
#[test]
|
||||
fn test_random_with_args() {
|
||||
let mut params = Mapping::new();
|
||||
let choices = vec!(
|
||||
"first $0$",
|
||||
"second $0$",
|
||||
"$0$ third",
|
||||
);
|
||||
params.insert(Value::from("choices"), Value::from(choices.clone()));
|
||||
|
||||
let extension = RandomExtension::new();
|
||||
let output = extension.calculate(¶ms, &vec!["test".to_owned()]);
|
||||
|
||||
assert!(output.is_some());
|
||||
|
||||
let output = output.unwrap();
|
||||
|
||||
let rendered_choices = vec!(
|
||||
"first test",
|
||||
"second test",
|
||||
"test third",
|
||||
);
|
||||
|
||||
assert!(rendered_choices.iter().any(|x| x == &output));
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ impl super::Extension for ScriptExtension {
|
|||
String::from("script")
|
||||
}
|
||||
|
||||
fn calculate(&self, params: &Mapping, _: &Vec<String>) -> Option<String> { // TODO: add argument handling
|
||||
fn calculate(&self, params: &Mapping, user_args: &Vec<String>) -> Option<String> {
|
||||
let args = params.get(&Value::from("args"));
|
||||
if args.is_none() {
|
||||
warn!("No 'args' parameter specified for script variable");
|
||||
|
@ -42,10 +42,17 @@ impl super::Extension for ScriptExtension {
|
|||
}
|
||||
let args = args.unwrap().as_sequence();
|
||||
if let Some(args) = args {
|
||||
let str_args = args.iter().map(|arg| {
|
||||
let mut str_args = args.iter().map(|arg| {
|
||||
arg.as_str().unwrap_or_default().to_string()
|
||||
}).collect::<Vec<String>>();
|
||||
|
||||
// The user has to enable argument concatenation explicitly
|
||||
let inject_args = params.get(&Value::from("inject_args"))
|
||||
.unwrap_or(&Value::from(false)).as_bool().unwrap_or(false);
|
||||
if inject_args {
|
||||
str_args.extend(user_args.clone());
|
||||
}
|
||||
|
||||
let output = if str_args.len() > 1 {
|
||||
Command::new(&str_args[0])
|
||||
.args(&str_args[1..])
|
||||
|
@ -71,4 +78,62 @@ impl super::Extension for ScriptExtension {
|
|||
error!("Could not execute script with args '{:?}'", args);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::extension::Extension;
|
||||
|
||||
#[test]
|
||||
fn test_script_basic() {
|
||||
let mut params = Mapping::new();
|
||||
params.insert(Value::from("args"), Value::from(vec!["echo", "hello world"]));
|
||||
|
||||
let extension = ScriptExtension::new();
|
||||
let output = extension.calculate(¶ms, &vec![]);
|
||||
|
||||
assert!(output.is_some());
|
||||
|
||||
if cfg!(target_os = "windows") {
|
||||
assert_eq!(output.unwrap(), "hello world\r\n");
|
||||
}else{
|
||||
assert_eq!(output.unwrap(), "hello world\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_script_inject_args_off() {
|
||||
let mut params = Mapping::new();
|
||||
params.insert(Value::from("args"), Value::from(vec!["echo", "hello world"]));
|
||||
|
||||
let extension = ScriptExtension::new();
|
||||
let output = extension.calculate(¶ms, &vec!["jon".to_owned()]);
|
||||
|
||||
assert!(output.is_some());
|
||||
|
||||
if cfg!(target_os = "windows") {
|
||||
assert_eq!(output.unwrap(), "hello world\r\n");
|
||||
}else{
|
||||
assert_eq!(output.unwrap(), "hello world\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_script_inject_args_on() {
|
||||
let mut params = Mapping::new();
|
||||
params.insert(Value::from("args"), Value::from(vec!["echo", "hello world"]));
|
||||
params.insert(Value::from("inject_args"), Value::from(true));
|
||||
|
||||
let extension = ScriptExtension::new();
|
||||
let output = extension.calculate(¶ms, &vec!["jon".to_owned()]);
|
||||
|
||||
assert!(output.is_some());
|
||||
|
||||
if cfg!(target_os = "windows") {
|
||||
assert_eq!(output.unwrap(), "hello world jon\r\n");
|
||||
}else{
|
||||
assert_eq!(output.unwrap(), "hello world jon\n");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,15 @@
|
|||
use serde_yaml::{Mapping, Value};
|
||||
use std::process::Command;
|
||||
use log::{warn, error};
|
||||
use regex::{Regex, Captures};
|
||||
|
||||
lazy_static! {
|
||||
static ref POS_ARG_REGEX: Regex = if cfg!(target_os = "windows") {
|
||||
Regex::new("\\%(?P<pos>\\d+)").unwrap()
|
||||
}else{
|
||||
Regex::new("\\$(?P<pos>\\d+)").unwrap()
|
||||
};
|
||||
}
|
||||
|
||||
pub struct ShellExtension {}
|
||||
|
||||
|
@ -34,7 +43,7 @@ impl super::Extension for ShellExtension {
|
|||
String::from("shell")
|
||||
}
|
||||
|
||||
fn calculate(&self, params: &Mapping, _: &Vec<String>) -> Option<String> { // TODO: add argument handling
|
||||
fn calculate(&self, params: &Mapping, args: &Vec<String>) -> Option<String> {
|
||||
let cmd = params.get(&Value::from("cmd"));
|
||||
if cmd.is_none() {
|
||||
warn!("No 'cmd' parameter specified for shell variable");
|
||||
|
@ -42,14 +51,25 @@ impl super::Extension for ShellExtension {
|
|||
}
|
||||
let cmd = cmd.unwrap().as_str().unwrap();
|
||||
|
||||
// Render positional parameters in args
|
||||
let cmd = POS_ARG_REGEX.replace_all(&cmd, |caps: &Captures| {
|
||||
let position_str = caps.name("pos").unwrap().as_str();
|
||||
let position = position_str.parse::<i32>().unwrap_or(-1);
|
||||
if position >= 0 && position < args.len() as i32 {
|
||||
args[position as usize].to_owned()
|
||||
}else{
|
||||
"".to_owned()
|
||||
}
|
||||
}).to_string();
|
||||
|
||||
let output = if cfg!(target_os = "windows") {
|
||||
Command::new("cmd")
|
||||
.args(&["/C", cmd])
|
||||
.args(&["/C", &cmd])
|
||||
.output()
|
||||
} else {
|
||||
Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(cmd)
|
||||
.arg(&cmd)
|
||||
.output()
|
||||
};
|
||||
|
||||
|
@ -163,5 +183,31 @@ mod tests {
|
|||
assert_eq!(output.unwrap(), "hello world");
|
||||
}
|
||||
|
||||
// TODO: add tests with arguments
|
||||
#[test]
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn test_shell_args_unix() {
|
||||
let mut params = Mapping::new();
|
||||
params.insert(Value::from("cmd"), Value::from("echo $0"));
|
||||
|
||||
let extension = ShellExtension::new();
|
||||
let output = extension.calculate(¶ms, &vec!["hello".to_owned()]);
|
||||
|
||||
assert!(output.is_some());
|
||||
|
||||
assert_eq!(output.unwrap(), "hello\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "windows")]
|
||||
fn test_shell_args_windows() {
|
||||
let mut params = Mapping::new();
|
||||
params.insert(Value::from("cmd"), Value::from("echo %0"));
|
||||
|
||||
let extension = ShellExtension::new();
|
||||
let output = extension.calculate(¶ms, &vec!["hello".to_owned()]);
|
||||
|
||||
assert!(output.is_some());
|
||||
|
||||
assert_eq!(output.unwrap(), "hello\r\n");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user