mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 06:12:40 +00:00
test(complete): Helper for asserting dynamic completions
This commit is contained in:
parent
5b10a9d83c
commit
65b9c2b37d
1 changed files with 82 additions and 70 deletions
|
@ -1,34 +1,38 @@
|
||||||
#![cfg(feature = "unstable-dynamic")]
|
#![cfg(feature = "unstable-dynamic")]
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use clap::Command;
|
||||||
|
|
||||||
|
macro_rules! complete {
|
||||||
|
($cmd:expr, $input:expr$(, current_dir = $current_dir:expr)? $(,)?) => {
|
||||||
|
{
|
||||||
|
#[allow(unused)]
|
||||||
|
let current_dir = None;
|
||||||
|
$(let current_dir = $current_dir;)?
|
||||||
|
complete(&mut $cmd, $input, current_dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn suggest_subcommand_subset() {
|
fn suggest_subcommand_subset() {
|
||||||
let name = "exhaustive";
|
let mut cmd = Command::new("exhaustive")
|
||||||
let mut cmd = clap::Command::new(name)
|
.subcommand(Command::new("hello-world"))
|
||||||
.subcommand(clap::Command::new("hello-world"))
|
.subcommand(Command::new("hello-moon"))
|
||||||
.subcommand(clap::Command::new("hello-moon"))
|
.subcommand(Command::new("goodbye-world"));
|
||||||
.subcommand(clap::Command::new("goodbye-world"));
|
|
||||||
|
|
||||||
let args = [name, "he"];
|
snapbox::assert_eq(
|
||||||
let arg_index = 1;
|
"hello-moon
|
||||||
let args = IntoIterator::into_iter(args)
|
hello-world
|
||||||
.map(std::ffi::OsString::from)
|
help\tPrint this message or the help of the given subcommand(s)",
|
||||||
.collect::<Vec<_>>();
|
complete!(cmd, "he"),
|
||||||
let current_dir = None;
|
);
|
||||||
|
|
||||||
let completions =
|
|
||||||
clap_complete::dynamic::complete(&mut cmd, args, arg_index, current_dir).unwrap();
|
|
||||||
let completions = completions
|
|
||||||
.into_iter()
|
|
||||||
.map(|s| s.0.to_string_lossy().into_owned())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
assert_eq!(completions, ["hello-moon", "hello-world", "help"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn suggest_long_flag_subset() {
|
fn suggest_long_flag_subset() {
|
||||||
let name = "exhaustive";
|
let mut cmd = Command::new("exhaustive")
|
||||||
let mut cmd = clap::Command::new(name)
|
|
||||||
.arg(
|
.arg(
|
||||||
clap::Arg::new("hello-world")
|
clap::Arg::new("hello-world")
|
||||||
.long("hello-world")
|
.long("hello-world")
|
||||||
|
@ -45,53 +49,33 @@ fn suggest_long_flag_subset() {
|
||||||
.action(clap::ArgAction::Count),
|
.action(clap::ArgAction::Count),
|
||||||
);
|
);
|
||||||
|
|
||||||
let args = [name, "--he"];
|
snapbox::assert_eq(
|
||||||
let arg_index = 1;
|
"--hello-world
|
||||||
let args = IntoIterator::into_iter(args)
|
--hello-moon
|
||||||
.map(std::ffi::OsString::from)
|
--help\tPrint help",
|
||||||
.collect::<Vec<_>>();
|
complete!(cmd, "--he"),
|
||||||
let current_dir = None;
|
);
|
||||||
|
|
||||||
let completions =
|
|
||||||
clap_complete::dynamic::complete(&mut cmd, args, arg_index, current_dir).unwrap();
|
|
||||||
let completions = completions
|
|
||||||
.into_iter()
|
|
||||||
.map(|s| s.0.to_string_lossy().into_owned())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
assert_eq!(completions, ["--hello-world", "--hello-moon", "--help"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn suggest_possible_value_subset() {
|
fn suggest_possible_value_subset() {
|
||||||
let name = "exhaustive";
|
let name = "exhaustive";
|
||||||
let mut cmd = clap::Command::new(name).arg(clap::Arg::new("hello-world").value_parser([
|
let mut cmd = Command::new(name).arg(clap::Arg::new("hello-world").value_parser([
|
||||||
"hello-world",
|
"hello-world",
|
||||||
"hello-moon",
|
"hello-moon",
|
||||||
"goodbye-world",
|
"goodbye-world",
|
||||||
]));
|
]));
|
||||||
|
|
||||||
let args = [name, "hello"];
|
snapbox::assert_eq(
|
||||||
let arg_index = 1;
|
"hello-world
|
||||||
let args = IntoIterator::into_iter(args)
|
hello-moon",
|
||||||
.map(std::ffi::OsString::from)
|
complete!(cmd, "hello"),
|
||||||
.collect::<Vec<_>>();
|
);
|
||||||
let current_dir = None;
|
|
||||||
|
|
||||||
let completions =
|
|
||||||
clap_complete::dynamic::complete(&mut cmd, args, arg_index, current_dir).unwrap();
|
|
||||||
let completions = completions
|
|
||||||
.into_iter()
|
|
||||||
.map(|s| s.0.to_string_lossy().into_owned())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
assert_eq!(completions, ["hello-world", "hello-moon"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn suggest_additional_short_flags() {
|
fn suggest_additional_short_flags() {
|
||||||
let name = "exhaustive";
|
let mut cmd = Command::new("exhaustive")
|
||||||
let mut cmd = clap::Command::new(name)
|
|
||||||
.arg(
|
.arg(
|
||||||
clap::Arg::new("a")
|
clap::Arg::new("a")
|
||||||
.short('a')
|
.short('a')
|
||||||
|
@ -108,19 +92,47 @@ fn suggest_additional_short_flags() {
|
||||||
.action(clap::ArgAction::Count),
|
.action(clap::ArgAction::Count),
|
||||||
);
|
);
|
||||||
|
|
||||||
let args = [name, "-a"];
|
snapbox::assert_eq(
|
||||||
let arg_index = 1;
|
"-aa
|
||||||
let args = IntoIterator::into_iter(args)
|
-ab
|
||||||
.map(std::ffi::OsString::from)
|
-ac
|
||||||
.collect::<Vec<_>>();
|
-ah\tPrint help",
|
||||||
let current_dir = None;
|
complete!(cmd, "-a"),
|
||||||
|
);
|
||||||
let completions =
|
}
|
||||||
clap_complete::dynamic::complete(&mut cmd, args, arg_index, current_dir).unwrap();
|
|
||||||
let completions = completions
|
fn complete(cmd: &mut Command, args: impl AsRef<str>, current_dir: Option<&Path>) -> String {
|
||||||
.into_iter()
|
let input = args.as_ref();
|
||||||
.map(|s| s.0.to_string_lossy().into_owned())
|
let mut args = vec![std::ffi::OsString::from(cmd.get_name())];
|
||||||
.collect::<Vec<_>>();
|
let arg_index;
|
||||||
|
|
||||||
assert_eq!(completions, ["-aa", "-ab", "-ac", "-ah"]);
|
if let Some((prior, after)) = input.split_once("[TAB]") {
|
||||||
|
args.extend(prior.split_whitespace().map(From::from));
|
||||||
|
if prior.ends_with(char::is_whitespace) {
|
||||||
|
args.push(std::ffi::OsString::default())
|
||||||
|
}
|
||||||
|
arg_index = args.len() - 1;
|
||||||
|
// HACK: this cannot handle in-word '[TAB]'
|
||||||
|
args.extend(after.split_whitespace().map(From::from));
|
||||||
|
} else {
|
||||||
|
args.extend(input.split_whitespace().map(From::from));
|
||||||
|
if input.ends_with(char::is_whitespace) {
|
||||||
|
args.push(std::ffi::OsString::default())
|
||||||
|
}
|
||||||
|
arg_index = args.len() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
clap_complete::dynamic::complete(cmd, args, arg_index, current_dir)
|
||||||
|
.unwrap()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(compl, help)| {
|
||||||
|
let compl = compl.to_str().unwrap();
|
||||||
|
if let Some(help) = help {
|
||||||
|
format!("{compl}\t{help}")
|
||||||
|
} else {
|
||||||
|
compl.to_owned()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue