Support completion when cursor inside an argument (#4023)

* Support completion when cursor inside an argument

Bash supports completion even when cursor is in an argument, this is very useful for some fixup after the initial completion.
Let add this feature as well.

Signed-off-by: Tw <wei.tan@intel.com>

* Add test for when cursor inside an argument

To support test this case, let's also take the position into account.

Signed-off-by: Tw <wei.tan@intel.com>
This commit is contained in:
Tw 2021-09-19 13:23:05 +08:00 committed by GitHub
parent f7043bf690
commit 4f7b423f36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -238,11 +238,19 @@ pub fn completion_location(line: &str, block: &Block, pos: usize) -> Vec<Complet
}
}
output.push(loc.clone());
output.push({
let mut partial_loc = loc.clone();
partial_loc.span = Span::new(loc.span.start(), pos);
partial_loc
});
output
}
}
_ => vec![loc.clone()],
_ => vec![{
let mut partial_loc = loc.clone();
partial_loc.span = Span::new(loc.span.start(), pos);
partial_loc
}],
};
} else if pos < loc.span.start() {
break;
@ -339,7 +347,7 @@ mod tests {
line: &str,
scope: &dyn ParserScope,
pos: usize,
) -> Vec<LocationType> {
) -> Vec<CompletionLocation> {
let (tokens, _) = lex(line, 0, nu_parser::NewlineMode::Normal);
let (lite_block, _) = parse_block(tokens);
@ -348,9 +356,6 @@ mod tests {
scope.exit_scope();
super::completion_location(line, &block, pos)
.into_iter()
.map(|v| v.item)
.collect()
}
#[test]
@ -362,7 +367,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 10),
vec![LocationType::Command],
vec![LocationType::Command.spanned(Span::new(9, 10)),],
);
}
@ -373,7 +378,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 10),
vec![LocationType::Command],
vec![LocationType::Command.spanned(Span::new(9, 10)),],
);
}
@ -384,7 +389,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 4),
vec![LocationType::Command],
vec![LocationType::Command.spanned(Span::new(0, 4)),],
);
}
@ -395,7 +400,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 13),
vec![LocationType::Variable],
vec![LocationType::Variable.spanned(Span::new(5, 13)),],
);
}
@ -410,7 +415,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 7),
vec![LocationType::Flag("du".to_string())],
vec![LocationType::Flag("du".to_string()).spanned(Span::new(3, 7)),],
);
}
@ -421,7 +426,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 8),
vec![LocationType::Command],
vec![LocationType::Command.spanned(Span::new(6, 8)),],
);
}
@ -433,8 +438,8 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 3),
vec![
LocationType::Command,
LocationType::Argument(Some("cd".to_string()), None)
LocationType::Command.spanned(Span::new(0, 3)),
LocationType::Argument(Some("cd".to_string()), None).spanned(Span::new(3, 3)),
],
);
}
@ -451,8 +456,8 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 3),
vec![
LocationType::Argument(Some("du".to_string()), None),
LocationType::Flag("du".to_string()),
LocationType::Argument(Some("du".to_string()), None).spanned(Span::new(3, 4)),
LocationType::Flag("du".to_string()).spanned(Span::new(3, 4)),
],
);
}
@ -467,8 +472,24 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 6),
vec![
LocationType::Command,
LocationType::Argument(Some("echo".to_string()), None)
LocationType::Command.spanned(Span::new(0, 6)),
LocationType::Argument(Some("echo".to_string()), None).spanned(Span::new(5, 6)),
],
);
}
#[test]
fn completes_argument_when_cursor_inside_argument() {
let registry: VecRegistry =
vec![Signature::build("echo").rest("rest", SyntaxShape::Any, "the values to echo")]
.into();
let line = "echo 123";
assert_eq!(
completion_location(line, &registry, 6),
vec![
LocationType::Command.spanned(Span::new(0, 6)),
LocationType::Argument(Some("echo".to_string()), None).spanned(Span::new(5, 6)),
],
);
}