test(complete): Allow E2E dynamic completion tests

This commit is contained in:
Roland Fredenhagen 2023-07-28 18:10:04 +07:00 committed by Ed Page
parent dac33b686b
commit 9a6208c795
10 changed files with 150 additions and 27 deletions

View file

@ -1,3 +1,5 @@
#[cfg(feature = "unstable-dynamic")]
use clap::{FromArgMatches, Subcommand};
use clap_complete::{generate, Generator, Shell};
fn main() {
@ -6,9 +8,18 @@ fn main() {
let mut cmd = cli();
eprintln!("Generating completion file for {generator}...");
print_completions(*generator, &mut cmd);
} else {
println!("{:?}", matches);
return;
}
#[cfg(feature = "unstable-dynamic")]
if let Ok(completions) =
clap_complete::dynamic::shells::CompleteCommand::from_arg_matches(&matches)
{
completions.complete(&mut cli());
return;
};
println!("{:?}", matches);
}
fn print_completions<G: Generator>(gen: G, cmd: &mut clap::Command) {
@ -16,7 +27,7 @@ fn print_completions<G: Generator>(gen: G, cmd: &mut clap::Command) {
}
fn cli() -> clap::Command {
clap::Command::new("test")
let cli = clap::Command::new("test")
.version("3.0")
.propagate_version(true)
.args([
@ -27,6 +38,7 @@ fn cli() -> clap::Command {
.help("everywhere"),
clap::Arg::new("generate")
.long("generate")
.value_name("SHELL")
.value_parser(clap::value_parser!(Shell))
.help("generate"),
])
@ -173,5 +185,8 @@ fn cli() -> clap::Command {
.long("email")
.value_hint(clap::ValueHint::EmailAddress),
]),
])
]);
#[cfg(feature = "unstable-dynamic")]
let cli = clap_complete::dynamic::shells::CompleteCommand::augment_subcommands(cli);
cli
}

View file

@ -20,6 +20,9 @@ _test() {
test,alias)
cmd="test__alias"
;;
test,complete)
cmd="test__complete"
;;
test,help)
cmd="test__help"
;;
@ -44,6 +47,9 @@ _test() {
test__help,alias)
cmd="test__help__alias"
;;
test__help,complete)
cmd="test__help__complete"
;;
test__help,help)
cmd="test__help__help"
;;
@ -153,7 +159,7 @@ _test() {
case "${cmd}" in
test)
opts="-h -V --global --generate --help --version action quote value pacman last alias hint help"
opts="-h -V --global --generate --help --version action quote value pacman last alias hint complete help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@ -222,8 +228,30 @@ _test() {
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
test__complete)
opts="-h -V --shell --register --global --help --version [COMP_WORDS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--shell)
COMPREPLY=($(compgen -W "bash" -- "${cur}"))
return 0
;;
--register)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
test__help)
opts="action quote value pacman last alias hint help"
opts="action quote value pacman last alias hint complete help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@ -264,6 +292,20 @@ _test() {
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
test__help__complete)
opts=""
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
test__help__help)
opts=""
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then

View file

@ -33,6 +33,7 @@ set edit:completion:arg-completer[test] = {|@words|
cand last 'last'
cand alias 'alias'
cand hint 'hint'
cand complete 'Register shell completions for this program'
cand help 'Print this message or the help of the given subcommand(s)'
}
&'test;action'= {
@ -225,6 +226,15 @@ set edit:completion:arg-completer[test] = {|@words|
cand -V 'Print version'
cand --version 'Print version'
}
&'test;complete'= {
cand --shell 'Specify shell to complete for'
cand --register 'Path to write completion-registration to'
cand --global 'everywhere'
cand -h 'Print help (see more with ''--help'')'
cand --help 'Print help (see more with ''--help'')'
cand -V 'Print version'
cand --version 'Print version'
}
&'test;help'= {
cand action 'action'
cand quote 'quote'
@ -233,6 +243,7 @@ set edit:completion:arg-completer[test] = {|@words|
cand last 'last'
cand alias 'alias'
cand hint 'hint'
cand complete 'Register shell completions for this program'
cand help 'Print this message or the help of the given subcommand(s)'
}
&'test;help;action'= {
@ -273,6 +284,8 @@ set edit:completion:arg-completer[test] = {|@words|
}
&'test;help;hint'= {
}
&'test;help;complete'= {
}
&'test;help;help'= {
}
]

View file

@ -9,6 +9,7 @@ complete -c test -n "__fish_use_subcommand" -f -a "pacman"
complete -c test -n "__fish_use_subcommand" -f -a "last"
complete -c test -n "__fish_use_subcommand" -f -a "alias"
complete -c test -n "__fish_use_subcommand" -f -a "hint"
complete -c test -n "__fish_use_subcommand" -f -a "complete" -d 'Register shell completions for this program'
complete -c test -n "__fish_use_subcommand" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
complete -c test -n "__fish_seen_subcommand_from action" -l set -d 'value' -r
complete -c test -n "__fish_seen_subcommand_from action" -l choice -d 'enum' -r -f -a "{first ,second }"
@ -103,14 +104,20 @@ complete -c test -n "__fish_seen_subcommand_from hint" -l email -r -f
complete -c test -n "__fish_seen_subcommand_from hint" -l global -d 'everywhere'
complete -c test -n "__fish_seen_subcommand_from hint" -s h -l help -d 'Print help'
complete -c test -n "__fish_seen_subcommand_from hint" -s V -l version -d 'Print version'
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from help" -f -a "action"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from help" -f -a "quote"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from help" -f -a "value"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from help" -f -a "pacman"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from help" -f -a "last"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from help" -f -a "alias"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from help" -f -a "hint"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
complete -c test -n "__fish_seen_subcommand_from complete" -l shell -d 'Specify shell to complete for' -r -f -a "{bash }"
complete -c test -n "__fish_seen_subcommand_from complete" -l register -d 'Path to write completion-registration to' -r -F
complete -c test -n "__fish_seen_subcommand_from complete" -l global -d 'everywhere'
complete -c test -n "__fish_seen_subcommand_from complete" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c test -n "__fish_seen_subcommand_from complete" -s V -l version -d 'Print version'
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from complete; and not __fish_seen_subcommand_from help" -f -a "action"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from complete; and not __fish_seen_subcommand_from help" -f -a "quote"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from complete; and not __fish_seen_subcommand_from help" -f -a "value"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from complete; and not __fish_seen_subcommand_from help" -f -a "pacman"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from complete; and not __fish_seen_subcommand_from help" -f -a "last"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from complete; and not __fish_seen_subcommand_from help" -f -a "alias"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from complete; and not __fish_seen_subcommand_from help" -f -a "hint"
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from complete; and not __fish_seen_subcommand_from help" -f -a "complete" -d 'Register shell completions for this program'
complete -c test -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from action; and not __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from value; and not __fish_seen_subcommand_from pacman; and not __fish_seen_subcommand_from last; and not __fish_seen_subcommand_from alias; and not __fish_seen_subcommand_from hint; and not __fish_seen_subcommand_from complete; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
complete -c test -n "__fish_seen_subcommand_from help; and __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions" -f -a "cmd-single-quotes" -d 'Can be \'always\', \'auto\', or \'never\''
complete -c test -n "__fish_seen_subcommand_from help; and __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions" -f -a "cmd-double-quotes" -d 'Can be "always", "auto", or "never"'
complete -c test -n "__fish_seen_subcommand_from help; and __fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions" -f -a "cmd-backticks" -d 'For more information see `echo test`'

View file

@ -15,7 +15,7 @@ _test() {
local context curcontext="$curcontext" state line
_arguments "${_arguments_options[@]}" \
'--generate=[generate]: :(bash elvish fish powershell zsh)' \
'--generate=[generate]:SHELL:(bash elvish fish powershell zsh)' \
'--global[everywhere]' \
'-h[Print help]' \
'--help[Print help]' \
@ -307,6 +307,18 @@ _arguments "${_arguments_options[@]}" \
'*::command_with_args:_cmdambivalent' \
&& ret=0
;;
(complete)
_arguments "${_arguments_options[@]}" \
'--shell=[Specify shell to complete for]:SHELL:(bash)' \
'--register=[Path to write completion-registration to]:REGISTER:_files' \
'--global[everywhere]' \
'-h[Print help (see more with '\''--help'\'')]' \
'--help[Print help (see more with '\''--help'\'')]' \
'-V[Print version]' \
'--version[Print version]' \
'*::comp_words:' \
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" \
":: :_test__help_commands" \
@ -403,6 +415,10 @@ _arguments "${_arguments_options[@]}" \
_arguments "${_arguments_options[@]}" \
&& ret=0
;;
(complete)
_arguments "${_arguments_options[@]}" \
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" \
&& ret=0
@ -426,6 +442,7 @@ _test_commands() {
'last:' \
'alias:' \
'hint:' \
'complete:Register shell completions for this program' \
'help:Print this message or the help of the given subcommand(s)' \
)
_describe -t commands 'test commands' commands "$@"
@ -540,6 +557,16 @@ _test__quote__help__cmd-single-quotes_commands() {
local commands; commands=()
_describe -t commands 'test quote help cmd-single-quotes commands' commands "$@"
}
(( $+functions[_test__complete_commands] )) ||
_test__complete_commands() {
local commands; commands=()
_describe -t commands 'test complete commands' commands "$@"
}
(( $+functions[_test__help__complete_commands] )) ||
_test__help__complete_commands() {
local commands; commands=()
_describe -t commands 'test help complete commands' commands "$@"
}
(( $+functions[_test__help_commands] )) ||
_test__help_commands() {
local commands; commands=(
@ -550,6 +577,7 @@ _test__help_commands() {
'last:' \
'alias:' \
'hint:' \
'complete:Register shell completions for this program' \
'help:Print this message or the help of the given subcommand(s)' \
)
_describe -t commands 'test help commands' commands "$@"

View file

@ -156,8 +156,8 @@ fn complete() {
let input = "test \t\t";
let expected = r#"%
-h --global --help action value last hint
-V --generate --version quote pacman alias help"#;
-h --global --help action value last hint help
-V --generate --version quote pacman alias complete"#;
let actual = runtime.complete(input, &term).unwrap();
snapbox::assert_eq(expected, actual);
}

View file

@ -308,9 +308,17 @@ pub fn register_example(context: &str, name: &str, shell: completest::Shell) {
.join(shell_name);
println!("Compiling");
let manifest_path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml");
let bin_path =
snapbox::cmd::compile_example(name, ["--manifest-path", manifest_path.to_str().unwrap()])
.unwrap();
let bin_path = snapbox::cmd::compile_example(
name,
[
"--manifest-path",
manifest_path.to_str().unwrap(),
// Unconditionally include to avoid completion file tests failing based on the how
// `cargo test` is invoked
"--features=unstable-dynamic",
],
)
.unwrap();
println!("Compiled");
let bin_root = bin_path.parent().unwrap().to_owned();
@ -353,9 +361,17 @@ pub fn load_runtime(
let home = scratch.path().unwrap().to_owned();
println!("Compiling");
let manifest_path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml");
let bin_path =
snapbox::cmd::compile_example(name, ["--manifest-path", manifest_path.to_str().unwrap()])
.unwrap();
let bin_path = snapbox::cmd::compile_example(
name,
[
"--manifest-path",
manifest_path.to_str().unwrap(),
// Unconditionally include to avoid completion file tests failing based on the how
// `cargo test` is invoked
"--features=unstable-dynamic",
],
)
.unwrap();
println!("Compiled");
let bin_root = bin_path.parent().unwrap().to_owned();

View file

@ -146,6 +146,7 @@ fn complete() {
-h Print help
action action
alias alias
complete Register shell completions for this program
help Print this message or the help of the given subcommand(s)
hint hint
last last

View file

@ -138,8 +138,8 @@ fn complete() {
let input = "test \t";
let expected = r#"% test
action help (Print this message or the help of the given subcommand(s)) last quote
alias hint pacman value"#;
action complete (Register shell completions for this program) hint pacman value
alias help (Print this message or the help of the given subcommand(s)) last quote"#;
let actual = runtime.complete(input, &term).unwrap();
snapbox::assert_eq(expected, actual);
}

View file

@ -138,8 +138,9 @@ fn complete() {
let input = "test \t";
let expected = r#"% test
help -- Print this message or the help of the given subcommand(s)
pacman action alias value quote hint last --"#;
complete -- Register shell completions for this program
help -- Print this message or the help of the given subcommand(s)
pacman action alias value quote hint last --"#;
let actual = runtime.complete(input, &term).unwrap();
snapbox::assert_eq(expected, actual);
}