use crate::config_clap::error::{ConfigClapError, Result};
use ggen_core::config_lib::GgenConfig;
use std::path::Path;
pub trait LoadConfigFromGgenToml: Sized {
fn from_ggen_toml<P: AsRef<Path>>(path: P) -> Result<Self>;
fn merge_with_cli(self, cli_args: Self) -> Self;
}
pub fn load_ggen_config<P: AsRef<Path>>(path: P) -> Result<GgenConfig> {
let config_str = std::fs::read_to_string(path.as_ref())
.map_err(|e| ConfigClapError::LoadError(format!("Failed to read ggen.toml: {e}")))?;
let config: GgenConfig = toml::from_str(&config_str)
.map_err(|e| ConfigClapError::ParseError(format!("Failed to parse ggen.toml: {e}")))?;
Ok(config)
}
#[must_use]
pub fn expand_env_vars(input: &str) -> String {
let mut result = input.to_string();
let mut last_pos = 0;
while let Some(start) = result[last_pos..].find("${") {
let start = last_pos + start;
if let Some(end) = result[start..].find('}') {
let var_name = &result[start + 2..start + end];
if let Ok(value) = std::env::var(var_name) {
result.replace_range(start..start + end + 1, &value);
last_pos = start + value.len();
} else {
last_pos = start + end + 1;
}
} else {
break;
}
}
let mut chars: Vec<char> = result.chars().collect();
let mut i = 0;
while i < chars.len() {
if chars[i] == '$' && i + 1 < chars.len() && chars[i + 1].is_alphabetic() {
let start = i;
i += 1;
while i < chars.len() && (chars[i].is_alphanumeric() || chars[i] == '_') {
i += 1;
}
let var_name: String = chars[start + 1..i].iter().collect();
if let Ok(value) = std::env::var(&var_name) {
result.replace_range(start..start + var_name.len() + 1, &value);
chars = result.chars().collect();
i = start + value.len();
} else {
i = start + var_name.len() + 1;
}
} else {
i += 1;
}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
#[test]
fn test_expand_env_vars_dollar_brace() {
env::set_var("TEST_VAR", "test_value");
let input = "Path: ${TEST_VAR}/output";
let result = expand_env_vars(input);
assert_eq!(result, "Path: test_value/output");
env::remove_var("TEST_VAR");
}
#[test]
fn test_expand_env_vars_dollar() {
env::set_var("USER", "testuser");
let input = "Home: /home/$USER";
let result = expand_env_vars(input);
assert_eq!(result, "Home: /home/testuser");
}
#[test]
fn test_expand_env_vars_missing() {
let input = "Path: ${NONEXISTENT_VAR}/output";
let result = expand_env_vars(input);
assert!(result.contains("${NONEXISTENT_VAR}") || result == input);
}
#[test]
fn test_load_missing_config() {
let result = load_ggen_config("/nonexistent/ggen.toml");
assert!(result.is_err());
assert!(matches!(result, Err(ConfigClapError::LoadError(_))));
}
}