hen 0.8.0

Run API collections from the command line.
use std::collections::HashMap;

use pest::Parser;
use pest_derive::Parser;

#[derive(Parser)]
#[grammar = "src/parser/context.pest"]
struct VarPlaceholderParser;

pub fn inject_from_prompt(input: &str) -> String {
    let mut output = String::new();

    let mut pairs = VarPlaceholderParser::parse(Rule::text, input).unwrap();

    let pair = pairs.next().unwrap();

    for inner_pair in pair.into_inner() {
        match inner_pair.as_rule() {
            Rule::word => {
                output.push_str(inner_pair.as_str());
            }
            Rule::input => {
                let prompt = format!("Provide a value for \"{}\"", inner_pair.as_str());
                // get the input from the user
                let input: String = dialoguer::Input::new()
                    .with_prompt(prompt)
                    .interact()
                    .unwrap();
                output.push_str(input.as_str());
            }
            Rule::var => {
                // retain the variable placeholder
                // unresolved variables may be encountered in the context of a preamble.
                output.push_str(format!("{{{{{}}}}}", inner_pair.as_str()).as_str());
            }
            _ => {
                unreachable!("unexpected rule: {:?}", inner_pair.as_rule());
            }
        }
    }
    output
}

pub fn inject_from_variable(input: &str, context: &HashMap<String, String>) -> String {
    let mut output = String::new();

    let mut pairs = VarPlaceholderParser::parse(Rule::text, input).unwrap();

    let pair = pairs.next().unwrap();

    for inner_pair in pair.into_inner() {
        match inner_pair.as_rule() {
            Rule::word => {
                output.push_str(inner_pair.as_str());
            }
            Rule::var => {
                let key = inner_pair.as_str().to_string();
                let value = context
                    .get(&key)
                    .expect(&format!("No value found for variable: {}", key));
                output.push_str(value);
            }
            Rule::input => {
                // retain the input placeholder
                output.push_str(format!("[[{}]]", inner_pair.as_str()).as_str());
            }
            _ => {
                unreachable!("unexpected rule: {:?}", inner_pair.as_rule());
            }
        }
    }
    output
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn should_replace_variables() {
        let input = "this is a test with a {{variable}}";
        let mut context = HashMap::new();
        context.insert("variable".to_string(), "value".to_string());

        let output = inject_from_variable(input, &context);

        assert_eq!(output, "this is a test with a value");
    }
}