Skip to content

Commit

Permalink
feat(clap_complete): Add support for -fbar and -f=bar completion
Browse files Browse the repository at this point in the history
  • Loading branch information
shannmu committed Jul 25, 2024
1 parent 48a23f5 commit fc479ba
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 27 deletions.
82 changes: 81 additions & 1 deletion clap_complete/src/dynamic/completer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ fn complete_arg(
completions.extend(hidden_longs_aliases(cmd));
}

if arg.is_empty() || arg.is_stdio() || arg.is_short() {
if arg.is_empty() || arg.is_stdio() {
let dash_or_arg = if arg.is_empty() {
"-".into()
} else {
Expand All @@ -263,6 +263,86 @@ fn complete_arg(
.visible(true)
}),
);
} else if let Some(mut short) = arg.to_short() {
if !short.is_negative_number() {
let takes_value_opt;
let mut leading_flags = OsString::new();
// Find the first takes_value option.
loop {
match short.next_flag() {
Some(Ok(opt)) => {
leading_flags.push(opt.to_string());
let opt = cmd.get_arguments().find(|a| {
let shorts = a.get_short_and_visible_aliases();
let is_find = shorts.map(|v| {
let mut iter = v.into_iter();
let c = iter.find(|c| *c == opt);
c.is_some()
});
is_find.unwrap_or(false)
});
match opt.map(|o| o.get_action()) {
Some(clap::ArgAction::Set) | Some(clap::ArgAction::Append) => {
takes_value_opt = opt;
break;
}
Some(clap::ArgAction::SetTrue)
| Some(clap::ArgAction::SetFalse)
| Some(clap::ArgAction::Count)
| Some(clap::ArgAction::Version)
| Some(clap::ArgAction::Help)
| Some(clap::ArgAction::HelpShort)
| Some(clap::ArgAction::HelpLong) => (),
Some(_) => (),
None => (),
}
}
Some(Err(_)) | None => {
takes_value_opt = None;
break;
}
}
}

// Clone `short` to `peek_short` to peek whether the next flag is a `=`.
if let Some(opt) = takes_value_opt {
let mut peek_short = short.clone();
let has_equal = if let Some(Ok('=')) = peek_short.next_flag() {
short.next_flag();
true
} else {
false
};

let value = short.next_value_os().unwrap_or(OsStr::new(""));
completions.extend(
complete_arg_value(value.to_str().ok_or(value), opt, current_dir)
.into_iter()
.map(|comp| {
CompletionCandidate::new(format!(
"-{}{}{}",
leading_flags.to_string_lossy(),
if has_equal { "=" } else { "" },
comp.get_content().to_string_lossy()
))
.help(comp.get_help().cloned())
.visible(comp.is_visible())
}),
);
} else {
completions.extend(shorts_and_visible_aliases(cmd).into_iter().map(
|comp| {
CompletionCandidate::new(format!(
"-{}{}",
leading_flags.to_string_lossy(),
comp.get_content().to_string_lossy()
))
.help(comp.get_help().cloned())
.visible(comp.is_visible())
},
));
}
}
}

if let Some(positional) = cmd
Expand Down
37 changes: 11 additions & 26 deletions clap_complete/tests/testsuite/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,51 +406,36 @@ pos_c"
assert_data_eq!(
complete!(cmd, "-ci[TAB]", current_dir = Some(testdir_path)),
snapbox::str![
"-cii
-ciF
-cic
-cih Print help"
"-cia_file
-cib_file
-cic_dir/
-cid_dir/"
]
);

assert_data_eq!(
complete!(cmd, "-ci=[TAB]", current_dir = Some(testdir_path)),
snapbox::str![
"-ci=i
-ci=F
-ci=c
-ci=h Print help"
"-ci=a_file
-ci=b_file
-ci=c_dir/
-ci=d_dir/"
]
);

assert_data_eq!(
complete!(cmd, "-ci=a[TAB]", current_dir = Some(testdir_path)),
snapbox::str![
"-ci=ai
-ci=aF
-ci=ac
-ci=ah Print help"
]
snapbox::str!["-ci=a_file"]
);

assert_data_eq!(
complete!(cmd, "-ciF[TAB]", current_dir = Some(testdir_path)),
snapbox::str![
"-ciFi
-ciFF
-ciFc
-ciFh\tPrint help"
]
snapbox::str![""]
);

assert_data_eq!(
complete!(cmd, "-ciF=[TAB]", current_dir = Some(testdir_path)),
snapbox::str![
"-ciF=i
-ciF=F
-ciF=c
-ciF=h\tPrint help"
]
snapbox::str![""]
)
}

Expand Down

0 comments on commit fc479ba

Please sign in to comment.