mirror of
https://github.com/nushell/nushell
synced 2025-01-06 10:19:03 +00:00
9ec2aca86f
* refactor: expand_path and expand_ndots now work for any string. * refactor: refactor test and add new ones. * refactor: convert expanded to owned string * feat: pub export of expand_ndots * feat: add completion for ndots in fs-shell
95 lines
2 KiB
Rust
95 lines
2 KiB
Rust
use std::borrow::Cow;
|
|
|
|
fn handle_dots_push(string: &mut String, count: u8) {
|
|
if count < 1 {
|
|
return;
|
|
}
|
|
|
|
if count == 1 {
|
|
string.push('.');
|
|
return;
|
|
}
|
|
|
|
for _ in 0..(count - 1) {
|
|
string.push_str("../");
|
|
}
|
|
|
|
string.pop(); // remove last '/'
|
|
}
|
|
|
|
pub fn expand_ndots(path: &str) -> Cow<'_, str> {
|
|
let mut dots_count = 0u8;
|
|
let ndots_present = {
|
|
for chr in path.chars() {
|
|
if chr == '.' {
|
|
dots_count += 1;
|
|
} else {
|
|
if dots_count > 2 {
|
|
break;
|
|
}
|
|
|
|
dots_count = 0;
|
|
}
|
|
}
|
|
|
|
dots_count > 2
|
|
};
|
|
|
|
if !ndots_present {
|
|
return path.into();
|
|
}
|
|
|
|
let mut dots_count = 0u8;
|
|
let mut expanded = String::new();
|
|
for chr in path.chars() {
|
|
if chr != '.' {
|
|
handle_dots_push(&mut expanded, dots_count);
|
|
dots_count = 0;
|
|
expanded.push(chr);
|
|
} else {
|
|
dots_count += 1;
|
|
}
|
|
}
|
|
|
|
handle_dots_push(&mut expanded, dots_count);
|
|
|
|
expanded.into()
|
|
}
|
|
|
|
pub fn expand_path<'a>(path: &'a str) -> Cow<'a, str> {
|
|
let tilde_expansion: Cow<'a, str> = shellexpand::tilde(path);
|
|
let ndots_expansion: Cow<'a, str> = match tilde_expansion {
|
|
Cow::Borrowed(b) => expand_ndots(b),
|
|
Cow::Owned(o) => expand_ndots(&o).to_string().into(),
|
|
};
|
|
|
|
ndots_expansion
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn string_without_ndots() {
|
|
assert_eq!("../hola", &expand_ndots("../hola").to_string());
|
|
}
|
|
|
|
#[test]
|
|
fn string_with_three_ndots() {
|
|
assert_eq!("../..", &expand_ndots("...").to_string());
|
|
}
|
|
|
|
#[test]
|
|
fn string_with_three_ndots_and_final_slash() {
|
|
assert_eq!("../../", &expand_ndots(".../").to_string());
|
|
}
|
|
|
|
#[test]
|
|
fn string_with_three_ndots_and_garbage() {
|
|
assert_eq!(
|
|
"ls ../../ garbage.*[",
|
|
&expand_ndots("ls .../ garbage.*[").to_string(),
|
|
);
|
|
}
|
|
}
|