extern crate regex;
use regex::Regex;
pub fn expand_env<T: AsRef<str>>(p: T) -> String {
let mut p = String::from(p.as_ref());
p = p.replace("~", "${HOME}");
let start = '{';
let end = '}';
let re = Regex::new(r"\$(\w+|\{[^}]*\})").unwrap();
let mut global_start_pos = 0;
#[warn(unused_variables, unused_mut)]
let mut result = String::new();
for cap in re.find_iter(&p) {
let mut name = cap.as_str();
name = &name[1..name.chars().count()];
let name_len = name.chars().count();
if name.chars().nth(0).unwrap() == start && name.chars().nth(name_len - 1).unwrap() == end {
name = &name[1..name_len - 1];
}
let local_start_pos = cap.start();
if global_start_pos < local_start_pos {
let inner: String = p
.chars()
.skip(global_start_pos)
.take(local_start_pos - global_start_pos)
.collect();
result.push_str(inner.as_str());
}
for (ref key, ref value) in std::env::vars().into_iter() {
if key == name {
result.push_str(value);
break;
}
}
global_start_pos = cap.end();
}
let end_pos = p.chars().count();
if global_start_pos < end_pos {
let inner: String = p
.chars()
.skip(global_start_pos)
.take(end_pos - global_start_pos)
.collect();
result.push_str(inner.as_str());
}
println!("result: {}", result);
return result;
}
#[cfg(test)]
mod tests {
use super::expand_env;
#[test]
fn test_expand_env() {
let s = expand_env("${PWD}/a/$HOME/c.txt");
let pwd = std::env::current_dir().unwrap();
let home = std::env::home_dir().unwrap();
let s2 = format!(
"{}/a/{}/c.txt",
pwd.to_str().unwrap(),
home.to_str().unwrap()
);
assert_eq!(s, s2);
}
}