forked from extern/nushell
try to use regular trim commands as much as possible (#3743)
This commit is contained in:
parent
a99a2ce7e8
commit
08c624576c
@ -98,37 +98,62 @@ fn trim(s: &str, char_: Option<char>, closure_flags: &ClosureFlags) -> String {
|
|||||||
both_flag,
|
both_flag,
|
||||||
format_flag,
|
format_flag,
|
||||||
} = closure_flags;
|
} = closure_flags;
|
||||||
let delimiter = char_.unwrap_or(' ');
|
let delimiters = match char_ {
|
||||||
let mut buf = vec![];
|
Some(c) => vec![c],
|
||||||
let mut is_delim = false;
|
// Trying to make this trim work like rust default trim()
|
||||||
let left_remove = left_trim | all_flag | both_flag | format_flag;
|
// which uses is_whitespace() as a default
|
||||||
let right_remove = right_trim | all_flag | both_flag | format_flag;
|
None => vec![
|
||||||
let middle_remove = all_flag | format_flag;
|
' ', // space
|
||||||
let middle_add = !all_flag && (*format_flag); // cases like -a -f
|
'\x09', // horizontal tab
|
||||||
for c in s.chars() {
|
'\x0A', // new line, line feed
|
||||||
match c {
|
'\x0B', // vertical tab
|
||||||
x if x == delimiter && buf.is_empty() && left_remove => continue,
|
'\x0C', // form feed, new page
|
||||||
x if x == delimiter => {
|
'\x0D', // carriage return
|
||||||
is_delim = true;
|
], //whitespace
|
||||||
if !middle_remove {
|
};
|
||||||
buf.push(delimiter);
|
|
||||||
|
if *left_trim {
|
||||||
|
s.trim_start_matches(&delimiters[..]).to_string()
|
||||||
|
} else if *right_trim {
|
||||||
|
s.trim_end_matches(&delimiters[..]).to_string()
|
||||||
|
} else if *all_flag {
|
||||||
|
s.split(&delimiters[..])
|
||||||
|
.filter(|s| !s.is_empty())
|
||||||
|
.collect::<String>()
|
||||||
|
} else if *both_flag {
|
||||||
|
s.trim_matches(&delimiters[..]).to_string()
|
||||||
|
} else if *format_flag {
|
||||||
|
// The idea here is to use regex to go through these delimiters and
|
||||||
|
// where there are multiple, replace them with singles
|
||||||
|
|
||||||
|
// create our return string which is a copy of the original string
|
||||||
|
let mut return_string = String::from(s);
|
||||||
|
// Iterate through the delimiters replacing them with regex friendly names
|
||||||
|
for r in &delimiters {
|
||||||
|
let reg = match r {
|
||||||
|
' ' => r"\s".to_string(),
|
||||||
|
'\x09' => r"\t".to_string(),
|
||||||
|
'\x0A' => r"\n".to_string(),
|
||||||
|
'\x0B' => r"\v".to_string(),
|
||||||
|
'\x0C' => r"\f".to_string(),
|
||||||
|
'\x0D' => r"\r".to_string(),
|
||||||
|
_ => format!(r"\{}", r),
|
||||||
|
};
|
||||||
|
// create a regex string that looks for 2 or more of each of these characters
|
||||||
|
let re_str = format!("{}{{2,}}", reg);
|
||||||
|
// create the regex
|
||||||
|
let re = regex::Regex::new(&re_str).expect("Error creating regular expression");
|
||||||
|
// replace all mutliple occurances with single occurences represented by r
|
||||||
|
let new_str = re.replace_all(&return_string, r.to_string());
|
||||||
|
// update the return string so the next loop has the latest changes
|
||||||
|
return_string = new_str.to_string();
|
||||||
}
|
}
|
||||||
|
// for good measure, trim_matches, which gets the start and end
|
||||||
|
// theoretically we shouldn't have to do this but from my testing, we do.
|
||||||
|
return_string.trim_matches(&delimiters[..]).to_string()
|
||||||
|
} else {
|
||||||
|
s.trim().to_string()
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
if is_delim && middle_add {
|
|
||||||
buf.push(delimiter);
|
|
||||||
is_delim = false;
|
|
||||||
}
|
|
||||||
buf.push(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if right_remove {
|
|
||||||
while buf.last() == Some(&delimiter) {
|
|
||||||
buf.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.into_iter().collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
Loading…
Reference in New Issue
Block a user