Improve quoted completions (#3577)

This commit is contained in:
JT 2021-06-09 06:47:29 +12:00 committed by GitHub
parent 2e968d2557
commit e9de4c08b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -65,23 +65,23 @@ impl NuCompleter {
let suggestions = locations let suggestions = locations
.into_iter() .into_iter()
.flat_map(|location| { .flat_map(|location| {
let partial = location.span.slice(line); let partial = location.span.slice(line).to_string();
match location.item { match location.item {
LocationType::Command => { LocationType::Command => {
let command_completer = CommandCompleter; let command_completer = CommandCompleter;
command_completer.complete(context, partial, matcher.to_owned()) command_completer.complete(context, &partial, matcher.to_owned())
} }
LocationType::Flag(cmd) => { LocationType::Flag(cmd) => {
let flag_completer = FlagCompleter { cmd }; let flag_completer = FlagCompleter { cmd };
flag_completer.complete(context, partial, matcher.to_owned()) flag_completer.complete(context, &partial, matcher.to_owned())
} }
LocationType::Argument(cmd, _arg_name) => { LocationType::Argument(cmd, _arg_name) => {
let path_completer = PathCompleter; let path_completer = PathCompleter;
let prepend = Span::new(pos, location.span.start()).slice(line); let prepend = Span::new(pos, location.span.start()).slice(line);
const QUOTE_CHARS: &[char] = &['\'', '"', '`']; const QUOTE_CHARS: &[char] = &['\'', '"'];
// TODO Find a better way to deal with quote chars. Can the completion // TODO Find a better way to deal with quote chars. Can the completion
// engine relay this back to us? Maybe have two spans: inner and // engine relay this back to us? Maybe have two spans: inner and
@ -89,22 +89,24 @@ impl NuCompleter {
// we'd need to replace. // we'd need to replace.
let (quote_char, partial) = if partial.starts_with(QUOTE_CHARS) { let (quote_char, partial) = if partial.starts_with(QUOTE_CHARS) {
let (head, tail) = partial.split_at(1); let (head, tail) = partial.split_at(1);
(Some(head), tail) (Some(head), tail.to_string())
} else { } else {
(None, partial) (None, partial)
}; };
let partial = if let Some(quote_char) = quote_char { let (mut partial, quoted) = if let Some(quote_char) = quote_char {
if partial.ends_with(quote_char) { if partial.ends_with(quote_char) {
&partial[..partial.len() - 1] (partial[..partial.len() - 1].to_string(), true)
} else { } else {
partial (partial, false)
} }
} else { } else {
partial (partial, false)
}; };
let completed_paths = path_completer.path_suggestions(partial, matcher); partial = partial.split('"').collect::<Vec<_>>().join("");
let completed_paths =
path_completer.path_suggestions(&partial, matcher);
match cmd.as_deref().unwrap_or("") { match cmd.as_deref().unwrap_or("") {
"cd" => select_directory_suggestions(completed_paths), "cd" => select_directory_suggestions(completed_paths),
_ => completed_paths, _ => completed_paths,
@ -114,7 +116,7 @@ impl NuCompleter {
replacement: format!( replacement: format!(
"{}{}", "{}{}",
prepend, prepend,
requote(s.suggestion.replacement) requote(s.suggestion.replacement, quoted)
), ),
display: s.suggestion.display, display: s.suggestion.display,
}) })
@ -144,10 +146,10 @@ fn select_directory_suggestions(completed_paths: Vec<PathSuggestion>) -> Vec<Pat
.collect() .collect()
} }
fn requote(orig_value: String) -> String { fn requote(orig_value: String, previously_quoted: bool) -> String {
let value: Cow<str> = rustyline::completion::unescape(&orig_value, Some('\\')); let value: Cow<str> = rustyline::completion::unescape(&orig_value, Some('\\'));
let mut quotes = vec!['"', '\'', '`']; let mut quotes = vec!['"', '\''];
let mut should_quote = false; let mut should_quote = false;
for c in value.chars() { for c in value.chars() {
if c.is_whitespace() || c == '#' { if c.is_whitespace() || c == '#' {
@ -165,7 +167,11 @@ fn requote(orig_value: String) -> String {
value.to_string() value.to_string()
} else { } else {
let quote = quotes[0]; let quote = quotes[0];
format!("{}{}{}", quote, value, quote) if previously_quoted {
format!("{}{}", quote, value)
} else {
format!("{}{}{}", quote, value, quote)
}
} }
} else { } else {
value.to_string() value.to_string()