mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
Add tests, fix grouped_values_of()
Fix clippy type complexity fix
This commit is contained in:
parent
451c5382cc
commit
58b9f35771
3 changed files with 203 additions and 15 deletions
|
@ -242,8 +242,21 @@ impl ArgMatches {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Placeholder documentation.
|
/// Placeholder documentation.
|
||||||
pub fn grouped_values_of<T: Key>(&self, id: T) -> Option<Iter<Vec<OsString>>> {
|
pub fn grouped_values_of<T: Key>(&self, id: T) -> Option<GroupedValues> {
|
||||||
self.args.get(&Id::from(id)).map(|arg| arg.vals())
|
#[allow(clippy::type_complexity)]
|
||||||
|
let arg_values: for<'a> fn(
|
||||||
|
&'a MatchedArg,
|
||||||
|
) -> Map<
|
||||||
|
std::slice::Iter<'a, Vec<OsString>>,
|
||||||
|
fn(&Vec<OsString>) -> Vec<&str>,
|
||||||
|
> = |arg| {
|
||||||
|
arg.vals()
|
||||||
|
.map(|g| g.iter().map(|x| x.to_str().expect(INVALID_UTF8)).collect())
|
||||||
|
};
|
||||||
|
self.args
|
||||||
|
.get(&Id::from(id))
|
||||||
|
.map(arg_values)
|
||||||
|
.map(|iter| GroupedValues { iter })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the lossy values of a specific argument. If the option wasn't present at runtime
|
/// Gets the lossy values of a specific argument. If the option wasn't present at runtime
|
||||||
|
@ -991,7 +1004,7 @@ impl ArgMatches {
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Values<'a> {
|
pub struct Values<'a> {
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
iter: Map<Flatten<std::slice::Iter<'a, Vec<OsString>>>, for<'r> fn(&'r OsString) -> &'r str>,
|
iter: Map<Flatten<Iter<'a, Vec<OsString>>>, for<'r> fn(&'r OsString) -> &'r str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for Values<'a> {
|
impl<'a> Iterator for Values<'a> {
|
||||||
|
@ -1017,12 +1030,44 @@ impl<'a> ExactSizeIterator for Values<'a> {}
|
||||||
impl<'a> Default for Values<'a> {
|
impl<'a> Default for Values<'a> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
static EMPTY: [Vec<OsString>; 0] = [];
|
static EMPTY: [Vec<OsString>; 0] = [];
|
||||||
// This is never called because the iterator is empty:
|
|
||||||
fn to_str_slice(_: &OsString) -> &str {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
Values {
|
Values {
|
||||||
iter: EMPTY[..].iter().flatten().map(to_str_slice),
|
iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
|
pub struct GroupedValues<'a> {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
iter: Map<std::slice::Iter<'a, Vec<OsString>>, fn(&Vec<OsString>) -> Vec<&str>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for GroupedValues<'a> {
|
||||||
|
type Item = Vec<&'a str>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.iter.next()
|
||||||
|
}
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
self.iter.size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DoubleEndedIterator for GroupedValues<'a> {
|
||||||
|
fn next_back(&mut self) -> Option<Self::Item> {
|
||||||
|
self.iter.next_back()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ExactSizeIterator for GroupedValues<'a> {}
|
||||||
|
|
||||||
|
/// Creates an empty iterator. Used for `unwrap_or_default()`.
|
||||||
|
impl<'a> Default for GroupedValues<'a> {
|
||||||
|
fn default() -> Self {
|
||||||
|
static EMPTY: [Vec<OsString>; 0] = [];
|
||||||
|
GroupedValues {
|
||||||
|
iter: EMPTY[..].iter().map(|_| unreachable!()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1052,7 +1097,7 @@ impl<'a> Default for Values<'a> {
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct OsValues<'a> {
|
pub struct OsValues<'a> {
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
iter: Map<Flatten<std::slice::Iter<'a, Vec<OsString>>>, fn(&OsString) -> &OsStr>,
|
iter: Map<Flatten<Iter<'a, Vec<OsString>>>, fn(&OsString) -> &OsStr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for OsValues<'a> {
|
impl<'a> Iterator for OsValues<'a> {
|
||||||
|
@ -1078,12 +1123,8 @@ impl<'a> ExactSizeIterator for OsValues<'a> {}
|
||||||
impl Default for OsValues<'_> {
|
impl Default for OsValues<'_> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
static EMPTY: [Vec<OsString>; 0] = [];
|
static EMPTY: [Vec<OsString>; 0] = [];
|
||||||
// This is never called because the iterator is empty:
|
|
||||||
fn to_str_slice(_: &OsString) -> &OsStr {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
OsValues {
|
OsValues {
|
||||||
iter: EMPTY[..].iter().flatten().map(to_str_slice),
|
iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1251,7 +1251,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
}
|
}
|
||||||
vals
|
vals
|
||||||
} else {
|
} else {
|
||||||
arg_split.into_iter().collect()
|
arg_split.collect()
|
||||||
};
|
};
|
||||||
let vals = vals.into_iter().map(|x| x.to_os_string()).collect();
|
let vals = vals.into_iter().map(|x| x.to_os_string()).collect();
|
||||||
self.add_multiple_vals_to_arg(arg, vals, matcher, ty, append);
|
self.add_multiple_vals_to_arg(arg, vals, matcher, ty, append);
|
||||||
|
|
147
tests/grouped_values.rs
Normal file
147
tests/grouped_values.rs
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
use clap::{App, Arg};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_sets_works() {
|
||||||
|
let m = App::new("cli")
|
||||||
|
.arg(Arg::new("option").long("option").multiple(true))
|
||||||
|
.get_matches_from(&[
|
||||||
|
"cli",
|
||||||
|
"--option",
|
||||||
|
"fr_FR:mon option 1",
|
||||||
|
"en_US:my option 1",
|
||||||
|
"--option",
|
||||||
|
"fr_FR:mon option 2",
|
||||||
|
"en_US:my option 2",
|
||||||
|
]);
|
||||||
|
let grouped_vals: Vec<_> = m.grouped_values_of("option").unwrap().collect();
|
||||||
|
assert_eq!(
|
||||||
|
grouped_vals,
|
||||||
|
vec![
|
||||||
|
vec!["fr_FR:mon option 1", "en_US:my option 1",],
|
||||||
|
vec!["fr_FR:mon option 2", "en_US:my option 2",],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_1026() {
|
||||||
|
let m = App::new("cli")
|
||||||
|
.arg(Arg::new("server").short('s').takes_value(true))
|
||||||
|
.arg(Arg::new("user").short('u').takes_value(true))
|
||||||
|
.arg(Arg::new("target").long("target").multiple(true))
|
||||||
|
.get_matches_from(&[
|
||||||
|
"backup", "-s", "server", "-u", "user", "--target", "target1", "file1", "file2",
|
||||||
|
"file3", "--target", "target2", "file4", "file5", "file6", "file7", "--target",
|
||||||
|
"target3", "file8",
|
||||||
|
]);
|
||||||
|
let grouped_vals: Vec<_> = m.grouped_values_of("target").unwrap().collect();
|
||||||
|
assert_eq!(
|
||||||
|
grouped_vals,
|
||||||
|
vec![
|
||||||
|
vec!["target1", "file1", "file2", "file3"],
|
||||||
|
vec!["target2", "file4", "file5", "file6", "file7",],
|
||||||
|
vec!["target3", "file8"]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_sets_long_flag_delimiter() {
|
||||||
|
let m = App::new("myapp")
|
||||||
|
.arg(
|
||||||
|
Arg::new("option")
|
||||||
|
.long("option")
|
||||||
|
.takes_value(true)
|
||||||
|
.use_delimiter(true)
|
||||||
|
.multiple(true),
|
||||||
|
)
|
||||||
|
.get_matches_from(vec![
|
||||||
|
"myapp",
|
||||||
|
"--option=hmm",
|
||||||
|
"--option=val1,val2,val3",
|
||||||
|
"--option",
|
||||||
|
"alice,bob",
|
||||||
|
]);
|
||||||
|
let grouped_vals: Vec<_> = m.grouped_values_of("option").unwrap().collect();
|
||||||
|
assert_eq!(
|
||||||
|
grouped_vals,
|
||||||
|
vec![
|
||||||
|
vec!["hmm"],
|
||||||
|
vec!["val1", "val2", "val3"],
|
||||||
|
vec!["alice", "bob"]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_sets_short_flag_delimiter() {
|
||||||
|
let m = App::new("myapp")
|
||||||
|
.arg(
|
||||||
|
Arg::new("option")
|
||||||
|
.short('o')
|
||||||
|
.takes_value(true)
|
||||||
|
.use_delimiter(true)
|
||||||
|
.multiple(true),
|
||||||
|
)
|
||||||
|
.get_matches_from(vec!["myapp", "-o=foo", "-o=val1,val2,val3", "-o=bar"]);
|
||||||
|
let grouped_vals: Vec<_> = m.grouped_values_of("option").unwrap().collect();
|
||||||
|
assert_eq!(
|
||||||
|
grouped_vals,
|
||||||
|
vec![vec!["foo"], vec!["val1", "val2", "val3"], vec!["bar"]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_sets_positional_arg() {
|
||||||
|
let m = App::new("multiple_values")
|
||||||
|
.arg(Arg::new("pos").about("multiple positionals").multiple(true))
|
||||||
|
.get_matches_from(vec![
|
||||||
|
"myprog", "val1", "val2", "val3", "val4", "val5", "val6",
|
||||||
|
]);
|
||||||
|
let grouped_vals: Vec<_> = m.grouped_values_of("pos").unwrap().collect();
|
||||||
|
assert_eq!(
|
||||||
|
grouped_vals,
|
||||||
|
vec![vec!["val1", "val2", "val3", "val4", "val5", "val6"]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_sets_multiple_positional_arg() {
|
||||||
|
let m = App::new("multiple_values")
|
||||||
|
.arg(Arg::new("pos1").about("multiple positionals"))
|
||||||
|
.arg(
|
||||||
|
Arg::new("pos2")
|
||||||
|
.about("multiple positionals")
|
||||||
|
.multiple(true),
|
||||||
|
)
|
||||||
|
.get_matches_from(vec![
|
||||||
|
"myprog", "val1", "val2", "val3", "val4", "val5", "val6",
|
||||||
|
]);
|
||||||
|
let grouped_vals: Vec<_> = m.grouped_values_of("pos2").unwrap().collect();
|
||||||
|
assert_eq!(
|
||||||
|
grouped_vals,
|
||||||
|
vec![vec!["val2", "val3", "val4", "val5", "val6"]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_sets_multiple_positional_arg_last_multiple() {
|
||||||
|
let m = App::new("multiple_values")
|
||||||
|
.arg(Arg::new("pos1").about("multiple positionals"))
|
||||||
|
.arg(
|
||||||
|
Arg::new("pos2")
|
||||||
|
.about("multiple positionals")
|
||||||
|
.multiple(true)
|
||||||
|
.last(true),
|
||||||
|
)
|
||||||
|
.get_matches_from(vec![
|
||||||
|
"myprog", "val1", "--", "val2", "val3", "val4", "val5", "val6",
|
||||||
|
]);
|
||||||
|
let grouped_vals: Vec<_> = m.grouped_values_of("pos2").unwrap().collect();
|
||||||
|
assert_eq!(
|
||||||
|
grouped_vals,
|
||||||
|
vec![vec!["val2", "val3", "val4", "val5", "val6"]]
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in a new issue