use std::borrow::Cow;
pub(super) fn expand_home(target: &str) -> Option<Cow<'_, str>> {
let rest = match target {
"~" => "",
t => match t.strip_prefix("~/") {
Some(r) => r,
None => return Some(Cow::Borrowed(target)),
},
};
let home = std::env::var("HOME").ok().filter(|h| h.starts_with('/'))?;
Some(Cow::Owned(if rest.is_empty() { home } else { format!("{home}/{rest}") }))
}
pub(super) fn express_relative_to_root(abs: &str, root: &str) -> String {
let root = root.trim_end_matches('/');
if crate::engine::resolve::regions::keeps_absolute(abs, root) {
return abs.to_string();
}
if abs == root {
return ".".to_string(); }
match abs.strip_prefix(root) {
Some(inside) if inside.starts_with('/') => inside.trim_start_matches('/').to_string(),
_ => abs.to_string(),
}
}
pub(super) fn lexical_join(base: &str, rel: &str) -> String {
let mut parts: Vec<&str> = base.split('/').filter(|s| !s.is_empty()).collect();
for seg in rel.split('/') {
match seg {
"" | "." => {}
".." => {
parts.pop();
}
s => parts.push(s),
}
}
format!("/{}", parts.join("/"))
}