pub(super) struct WinPath {
pub(super) parts: Vec<String>,
}
impl WinPath {
pub(super) fn program(&self) -> String {
self.parts.last().map_or_else(String::new, |last| {
last.strip_suffix(".exe").unwrap_or(last).to_owned()
})
}
}
pub(super) fn read(word: &str) -> WinPath {
let unified = word.replace('\\', "/").to_ascii_lowercase();
let mut parts: Vec<String> = Vec::new();
for (index, raw) in unified.split('/').enumerate() {
let is_drive = index == 0 && raw.len() == 2 && raw.ends_with(':');
let name = if is_drive {
raw
} else {
raw.split(':').next().unwrap_or(raw)
};
match name {
"." => {}
".." => {
parts.pop();
}
name => {
let name = name.trim_end_matches(['.', ' ']);
if !name.is_empty() {
parts.push(name.to_owned());
}
}
}
}
WinPath { parts }
}
pub(super) fn program(word: &str) -> String {
read(word).program()
}