use std::path::{Path, PathBuf};
pub fn expand_tilde(path: &Path) -> PathBuf {
if let Some(path_str) = path.to_str() {
if path_str.starts_with("~/") {
if let Ok(home) = std::env::var("HOME") {
return PathBuf::from(path_str.replacen("~", &home, 1));
}
}
}
path.to_path_buf()
}
pub fn expand_env_vars(input: &str) -> String {
let mut result = input.to_string();
let mut processed = 0;
while processed < result.len() {
if let Some(start) = result[processed..].find("${") {
let abs_start = processed + start;
if let Some(end) = result[abs_start..].find('}') {
let var_name = &result[abs_start + 2..abs_start + end];
if !var_name.is_empty() && var_name.chars().all(|c| c.is_alphanumeric() || c == '_')
{
let replacement = std::env::var(var_name).unwrap_or_else(|_| {
tracing::debug!("Environment variable {} not found", var_name);
format!("${{{var_name}}}")
});
result.replace_range(abs_start..abs_start + end + 1, &replacement);
processed = abs_start + replacement.len();
} else {
processed = abs_start + end + 1;
}
} else {
break;
}
} else {
break;
}
}
let mut i = 0;
let bytes = result.as_bytes();
let mut new_result = String::new();
while i < bytes.len() {
if bytes[i] == b'$' && i + 1 < bytes.len() && bytes[i + 1] != b'{' {
let start = i;
i += 1;
while i < bytes.len() && (bytes[i].is_ascii_alphanumeric() || bytes[i] == b'_') {
i += 1;
}
if i > start + 1 {
let var_name = match std::str::from_utf8(&bytes[start + 1..i]) {
Ok(name) => name,
Err(_) => {
new_result.push('$');
continue;
}
};
let replacement = std::env::var(var_name).unwrap_or_else(|_| {
tracing::debug!("Environment variable {} not found", var_name);
match String::from_utf8(bytes[start..i].to_vec()) {
Ok(original) => original,
Err(_) => {
format!("$INVALID_UTF8_{start}")
}
}
});
new_result.push_str(&replacement);
} else {
new_result.push('$');
}
} else {
new_result.push(bytes[i] as char);
i += 1;
}
}
new_result
}
pub fn get_current_username() -> String {
std::env::var("USER")
.or_else(|_| std::env::var("USERNAME"))
.or_else(|_| std::env::var("LOGNAME"))
.unwrap_or_else(|_| {
whoami::username().unwrap_or_else(|_| "user".to_string())
})
}