Skip to content

Commit

Permalink
Merge pull request #5739 from epage/snap
Browse files Browse the repository at this point in the history
fix(complete): Prioritize subcommands, positionals over flags
  • Loading branch information
epage authored Sep 20, 2024
2 parents 75efece + 2bd2c12 commit 3bcc7f8
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 169 deletions.
30 changes: 17 additions & 13 deletions clap_complete/src/engine/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub fn complete(
arg_index: usize,
current_dir: Option<&std::path::Path>,
) -> Result<Vec<CompletionCandidate>, std::io::Error> {
debug!("complete: args={args:?}, arg_index={arg_index:?}, current_dir={current_dir:?}");
cmd.build();

let raw_args = clap_lex::RawArgs::new(args);
Expand All @@ -26,6 +27,7 @@ pub fn complete(
);
// As we loop, `cursor` will always be pointing to the next item
raw_args.next_os(&mut target_cursor);
debug!("complete: target_cursor={target_cursor:?}");

// TODO: Multicall support
if !cmd.is_no_binary_name_set() {
Expand All @@ -39,12 +41,14 @@ pub fn complete(
while let Some(arg) = raw_args.next(&mut cursor) {
let current_state = next_state;
next_state = ParseState::ValueDone;
debug!(
"complete::next: arg={:?}, current_state={current_state:?}, cursor={cursor:?}",
arg.to_value_os(),
);
if cursor == target_cursor {
return complete_arg(&arg, current_cmd, current_dir, pos_index, current_state);
}

debug!("complete::next: Begin parsing '{:?}'", arg.to_value_os(),);

if let Ok(value) = arg.to_value() {
if let Some(next_cmd) = current_cmd.find_subcommand(value) {
current_cmd = next_cmd;
Expand Down Expand Up @@ -142,6 +146,17 @@ fn complete_arg(

match state {
ParseState::ValueDone => {
if let Ok(value) = arg.to_value() {
completions.extend(complete_subcommand(value, cmd));
}

if let Some(positional) = cmd
.get_positionals()
.find(|p| p.get_index() == Some(pos_index))
{
completions.extend(complete_arg_value(arg.to_value(), positional, current_dir));
}

if let Some((flag, value)) = arg.to_long() {
if let Ok(flag) = flag {
if let Some(value) = value {
Expand Down Expand Up @@ -215,17 +230,6 @@ fn complete_arg(
}
}
}

if let Some(positional) = cmd
.get_positionals()
.find(|p| p.get_index() == Some(pos_index))
{
completions.extend(complete_arg_value(arg.to_value(), positional, current_dir));
}

if let Ok(value) = arg.to_value() {
completions.extend(complete_subcommand(value, cmd));
}
}
ParseState::Pos(..) => {
if let Some(positional) = cmd
Expand Down
12 changes: 6 additions & 6 deletions clap_complete/tests/testsuite/bash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ fn complete_dynamic_env_toplevel() {
let input = "exhaustive \t\t";
let expected = snapbox::str![[r#"
%
--global --help -h action help last quote
--generate --version -V alias hint pacman value
action help last quote --global --help -h
alias hint pacman value --generate --version -V
"#]];
let actual = runtime.complete(input, &term).unwrap();
assert_data_eq!(actual, expected);
Expand All @@ -275,10 +275,10 @@ fn complete_dynamic_env_quoted_help() {
let input = "exhaustive quote \t\t";
let expected = snapbox::str![[r#"
%
--single-quotes --brackets --help cmd-backslash cmd-expansions
--double-quotes --expansions --version cmd-backticks cmd-single-quotes
--backticks --choice -h cmd-brackets escape-help
--backslash --global -V cmd-double-quotes help
cmd-backslash cmd-expansions --single-quotes --brackets --help
cmd-backticks cmd-single-quotes --double-quotes --expansions --version
cmd-brackets escape-help --backticks --choice -h
cmd-double-quotes help --backslash --global -V
"#]];
let actual = runtime.complete(input, &term).unwrap();
assert_data_eq!(actual, expected);
Expand Down
Loading

0 comments on commit 3bcc7f8

Please sign in to comment.