mirror of
https://github.com/nushell/nushell.git
synced 2025-02-17 02:50:56 +01:00
Improve quoting for path completions. (#2464)
- Ensure quotes surround suggestion replacement when there are spaces. - Ensure an appropriate quote character is chosen based on other quoting characters being in the suggestions.
This commit is contained in:
parent
8d1cecf643
commit
889b67ca92
@ -47,6 +47,30 @@ impl NuCompleter {
|
|||||||
|
|
||||||
LocationType::Argument(cmd, _arg_name) => {
|
LocationType::Argument(cmd, _arg_name) => {
|
||||||
let path_completer = crate::completion::path::Completer;
|
let path_completer = crate::completion::path::Completer;
|
||||||
|
|
||||||
|
const QUOTE_CHARS: &[char] = &['\'', '"', '`'];
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// outer. The former is what we want to complete, the latter what
|
||||||
|
// we'd need to replace.
|
||||||
|
let (quote_char, partial) = if partial.starts_with(QUOTE_CHARS) {
|
||||||
|
let (head, tail) = partial.split_at(1);
|
||||||
|
(Some(head), tail)
|
||||||
|
} else {
|
||||||
|
(None, partial)
|
||||||
|
};
|
||||||
|
|
||||||
|
let partial = if let Some(quote_char) = quote_char {
|
||||||
|
if partial.ends_with(quote_char) {
|
||||||
|
&partial[..partial.len()]
|
||||||
|
} else {
|
||||||
|
partial
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
partial
|
||||||
|
};
|
||||||
|
|
||||||
let completed_paths = path_completer.complete(context, partial);
|
let completed_paths = path_completer.complete(context, partial);
|
||||||
match cmd.as_deref().unwrap_or("") {
|
match cmd.as_deref().unwrap_or("") {
|
||||||
"cd" => select_directory_suggestions(completed_paths),
|
"cd" => select_directory_suggestions(completed_paths),
|
||||||
@ -57,7 +81,10 @@ impl NuCompleter {
|
|||||||
LocationType::Variable => Vec::new(),
|
LocationType::Variable => Vec::new(),
|
||||||
}
|
}
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(requote)
|
})
|
||||||
|
.map(|suggestion| Suggestion {
|
||||||
|
replacement: requote(suggestion.replacement),
|
||||||
|
display: suggestion.display,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@ -77,14 +104,30 @@ fn select_directory_suggestions(completed_paths: Vec<Suggestion>) -> Vec<Suggest
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn requote(item: Suggestion) -> Suggestion {
|
fn requote(value: String) -> String {
|
||||||
let unescaped = rustyline::completion::unescape(&item.replacement, Some('\\'));
|
let value = rustyline::completion::unescape(&value, Some('\\'));
|
||||||
if unescaped != item.replacement {
|
|
||||||
Suggestion {
|
let mut quotes = vec!['"', '\'', '`'];
|
||||||
display: item.display,
|
let mut should_quote = false;
|
||||||
replacement: format!("\"{}\"", unescaped),
|
for c in value.chars() {
|
||||||
|
if c.is_whitespace() {
|
||||||
|
should_quote = true;
|
||||||
|
} else if let Some(index) = quotes.iter().position(|q| *q == c) {
|
||||||
|
should_quote = true;
|
||||||
|
quotes.swap_remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if should_quote {
|
||||||
|
if quotes.is_empty() {
|
||||||
|
// TODO we don't really have an escape character, so there isn't a great option right
|
||||||
|
// now. One possibility is `{{$(char backtick)}}`
|
||||||
|
value.to_string()
|
||||||
|
} else {
|
||||||
|
let quote = quotes[0];
|
||||||
|
format!("{}{}{}", quote, value, quote)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
item
|
value.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user