Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 37 additions & 28 deletions src/book/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,21 +187,23 @@ impl<'a> FunctionRef<'a> {
let command_line = self.function.execution.get_command_line()?;
let mut env = BTreeMap::new();

// interpolate the arguments
let command_line = {
let mut interpolated = Vec::new();
for arg in command_line {
interpolated.push(if let Some(caps) = ARG_VALUE_PARSER.captures(&arg) {
let var_name = caps
.get(1)
.ok_or(ARG_EXPRESSION_ERROR)
.map_err(|e| anyhow!(e))?
.as_str();
// interpolate the arguments
let command_line = {
let mut interpolated = Vec::new();
for arg in command_line {
if ARG_VALUE_PARSER.is_match(&arg) {
// Process args with placeholders by replacing only the matched patterns
let mut processed_arg = arg.clone();

// Find all matches and collect the replacements
let mut replacements = Vec::new();
for caps in ARG_VALUE_PARSER.captures_iter(&arg) {
let full_match = caps.get(0).unwrap().as_str();
let var_name = caps.get(1).ok_or(ARG_EXPRESSION_ERROR).map_err(| e| anyhow!(e))?.as_str();
let var_default = caps.get(3).map(|m| m.as_str());

// read variable from the environment if the name starts with env. or ENV.
if var_name.starts_with("env.") || var_name.starts_with("ENV.") {
let env_var_name = var_name.replace("env.", "").replace("ENV.", "");
let replacement = if var_name.starts_with("env.") || var_name. starts_with("ENV.") {
let env_var_name = var_name.replace("env.", "").replace ("ENV.", "");
let env_var = std::env::var(&env_var_name);
let env_var_value = if let Ok(value) = env_var {
value
Expand All @@ -214,39 +216,46 @@ impl<'a> FunctionRef<'a> {
));
};

// add the environment variable to the command line for later use
// add the environment variable to the command line for later use
env.insert(env_var_name, env_var_value.to_owned());

env_var_value
} else if let Some(value) = arguments.get(var_name) {
// if the value is empty and there's a default value, use the default value
if value.is_empty() {
if let Some(def) = var_default {
def.to_string()
} else {
value.to_string()
}
} else {
// otherwise, use the provided value
value.to_string()
}
} else if let Some(default_value) = var_default {
// if the value is not provided and there's a default value, use the default value
default_value.to_string()
} else {
return Err(anyhow::anyhow!("argument {} not provided", var_name));
}
} else {
arg
});
}
interpolated
};
return Err(anyhow::anyhow!("argument {} not provided", var_name));
};

// final parsing
CommandLine::from_vec_with_env(&command_line, env)
replacements.push((full_match, replacement));
}

// Apply all replacements to the arg string
for (pattern, replacement) in replacements {
processed_arg = processed_arg.replace(pattern, &replacement);
}

interpolated.push(processed_arg);
} else {
// For args without placeholders, use as-is
interpolated.push(arg);
}
}
interpolated
};
// final parsing
CommandLine::from_vec_with_env(&command_line, env)
}
}
}

#[cfg(test)]
mod tests {
Expand Down
Loading