forked from extern/nushell
53 lines
1.4 KiB
Rust
53 lines
1.4 KiB
Rust
|
use std::path::{Component, Path, PathBuf};
|
||
|
|
||
|
fn expand_ndots(path: &str) -> String {
|
||
|
let path = Path::new(path);
|
||
|
let mut expanded = PathBuf::new();
|
||
|
|
||
|
for component in path.components() {
|
||
|
match component {
|
||
|
Component::Normal(normal) => {
|
||
|
if let Some(normal) = normal.to_str() {
|
||
|
if normal.chars().all(|c| c == '.') {
|
||
|
for _ in 0..(normal.len() - 1) {
|
||
|
expanded.push("..");
|
||
|
}
|
||
|
} else {
|
||
|
expanded.push(normal);
|
||
|
}
|
||
|
} else {
|
||
|
expanded.push(normal);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
c => expanded.push(c.as_os_str()),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
expanded.to_string_lossy().to_string()
|
||
|
}
|
||
|
|
||
|
pub fn expand_path(path: &str) -> String {
|
||
|
let tilde_expansion = shellexpand::tilde(path);
|
||
|
expand_ndots(&tilde_expansion)
|
||
|
}
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use super::*;
|
||
|
|
||
|
#[test]
|
||
|
fn expand_in_relative_path() {
|
||
|
let expected = Path::new("../..");
|
||
|
let expanded = PathBuf::from(expand_path("..."));
|
||
|
assert_eq!(expected, &expanded);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn expand_in_absolute_path() {
|
||
|
let expected = Path::new("/foo/../..");
|
||
|
let expanded = PathBuf::from(expand_path("/foo/..."));
|
||
|
assert_eq!(expected, &expanded);
|
||
|
}
|
||
|
}
|