mirror of
https://github.com/nushell/nushell
synced 2024-12-30 15:03:25 +00:00
Add support for subcommand completions (#3571)
* Add support for subcommand completions * Update test * WIP * Fix prepend for completions * Fix test
This commit is contained in:
parent
31a5de973d
commit
7eadbd938d
2 changed files with 50 additions and 10 deletions
|
@ -203,7 +203,8 @@ pub fn completion_location(line: &str, block: &Block, pos: usize) -> Vec<Complet
|
||||||
} else {
|
} else {
|
||||||
let mut command = None;
|
let mut command = None;
|
||||||
let mut prev = None;
|
let mut prev = None;
|
||||||
for loc in locations {
|
|
||||||
|
for loc in &locations {
|
||||||
// We don't use span.contains because we want to include the end. This handles the case
|
// We don't use span.contains because we want to include the end. This handles the case
|
||||||
// where the cursor is just after the text (i.e., no space between cursor and text)
|
// where the cursor is just after the text (i.e., no space between cursor and text)
|
||||||
if loc.span.start() <= pos && pos <= loc.span.end() {
|
if loc.span.start() <= pos && pos <= loc.span.end() {
|
||||||
|
@ -215,14 +216,31 @@ pub fn completion_location(line: &str, block: &Block, pos: usize) -> Vec<Complet
|
||||||
let cmd = cmd.clone();
|
let cmd = cmd.clone();
|
||||||
let span = loc.span;
|
let span = loc.span;
|
||||||
vec![
|
vec![
|
||||||
loc,
|
loc.clone(),
|
||||||
LocationType::Flag(cmd.unwrap_or_default()).spanned(span),
|
LocationType::Flag(cmd.unwrap_or_default()).spanned(span),
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
vec![loc]
|
let mut output = vec![];
|
||||||
|
|
||||||
|
for rloc in locations.iter().rev() {
|
||||||
|
if let Spanned {
|
||||||
|
span,
|
||||||
|
item: LocationType::Command,
|
||||||
|
} = &rloc
|
||||||
|
{
|
||||||
|
output.push(LocationType::Command.spanned(Span::new(
|
||||||
|
span.start(),
|
||||||
|
locations[locations.len() - 1].span.end(),
|
||||||
|
)));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => vec![loc],
|
|
||||||
|
output.push(loc.clone());
|
||||||
|
output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => vec![loc.clone()],
|
||||||
};
|
};
|
||||||
} else if pos < loc.span.start() {
|
} else if pos < loc.span.start() {
|
||||||
break;
|
break;
|
||||||
|
@ -236,14 +254,25 @@ pub fn completion_location(line: &str, block: &Block, pos: usize) -> Vec<Complet
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(prev) = prev {
|
if let Some(prev) = prev {
|
||||||
|
let mut locations = vec![];
|
||||||
// Cursor is between locations (or at the end). Look at the line to see if the cursor
|
// Cursor is between locations (or at the end). Look at the line to see if the cursor
|
||||||
// is after some character that would imply we're in the command position.
|
// is after some character that would imply we're in the command position.
|
||||||
let start = prev.span.end();
|
let start = prev.span.end();
|
||||||
|
|
||||||
|
if let Spanned {
|
||||||
|
item: LocationType::Command,
|
||||||
|
span,
|
||||||
|
} = &prev
|
||||||
|
{
|
||||||
|
locations.push(LocationType::Command.spanned(Span::new(span.start(), pos)));
|
||||||
|
}
|
||||||
if line[start..pos].contains(BEFORE_COMMAND_CHARS) {
|
if line[start..pos].contains(BEFORE_COMMAND_CHARS) {
|
||||||
vec![LocationType::Command.spanned(Span::new(pos, pos))]
|
locations.push(LocationType::Command.spanned(Span::new(pos, pos)));
|
||||||
|
locations
|
||||||
} else {
|
} else {
|
||||||
// TODO this should be able to be mapped to a command
|
// TODO this should be able to be mapped to a command
|
||||||
vec![LocationType::Argument(command, None).spanned(Span::new(pos, pos))]
|
locations.push(LocationType::Argument(command, None).spanned(Span::new(pos, pos)));
|
||||||
|
locations
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Cursor is before any possible completion location, so must be a command
|
// Cursor is before any possible completion location, so must be a command
|
||||||
|
@ -399,7 +428,10 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
completion_location(line, ®istry, 3),
|
completion_location(line, ®istry, 3),
|
||||||
vec![LocationType::Argument(Some("cd".to_string()), None)],
|
vec![
|
||||||
|
LocationType::Command,
|
||||||
|
LocationType::Argument(Some("cd".to_string()), None)
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +461,10 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
completion_location(line, ®istry, 6),
|
completion_location(line, ®istry, 6),
|
||||||
vec![LocationType::Argument(Some("echo".to_string()), None)],
|
vec![
|
||||||
|
LocationType::Command,
|
||||||
|
LocationType::Argument(Some("echo".to_string()), None)
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::completion::path::{PathCompleter, PathSuggestion};
|
||||||
use crate::completion::{self, Completer, Suggestion};
|
use crate::completion::{self, Completer, Suggestion};
|
||||||
use nu_engine::EvaluationContext;
|
use nu_engine::EvaluationContext;
|
||||||
use nu_parser::ParserScope;
|
use nu_parser::ParserScope;
|
||||||
use nu_source::Tag;
|
use nu_source::{Span, Tag};
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ impl NuCompleter {
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
const QUOTE_CHARS: &[char] = &['\'', '"', '`'];
|
const QUOTE_CHARS: &[char] = &['\'', '"', '`'];
|
||||||
|
|
||||||
|
@ -103,7 +104,11 @@ impl NuCompleter {
|
||||||
}
|
}
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| Suggestion {
|
.map(|s| Suggestion {
|
||||||
replacement: requote(s.suggestion.replacement),
|
replacement: format!(
|
||||||
|
"{}{}",
|
||||||
|
prepend,
|
||||||
|
requote(s.suggestion.replacement)
|
||||||
|
),
|
||||||
display: s.suggestion.display,
|
display: s.suggestion.display,
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|
Loading…
Reference in a new issue