2022-09-13 12:15:56 +00:00
|
|
|
use clap::Parser;
|
|
|
|
|
2022-09-29 20:56:53 +00:00
|
|
|
use crate::utils::assert_output;
|
|
|
|
|
2022-09-13 12:15:56 +00:00
|
|
|
#[test]
|
|
|
|
fn test_safely_nest_parser() {
|
|
|
|
#[derive(Parser, Debug, PartialEq)]
|
|
|
|
struct Opt {
|
|
|
|
#[command(flatten)]
|
|
|
|
foo: Foo,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Parser, Debug, PartialEq)]
|
|
|
|
struct Foo {
|
|
|
|
#[arg(long)]
|
|
|
|
foo: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
Opt {
|
|
|
|
foo: Foo { foo: true }
|
|
|
|
},
|
2022-11-24 13:54:25 +00:00
|
|
|
Opt::try_parse_from(["test", "--foo"]).unwrap()
|
2022-09-13 12:15:56 +00:00
|
|
|
);
|
|
|
|
}
|
2022-09-30 14:05:48 +00:00
|
|
|
|
2022-09-29 20:56:53 +00:00
|
|
|
#[test]
|
|
|
|
fn implicit_struct_group() {
|
|
|
|
#[derive(Parser, Debug)]
|
|
|
|
struct Opt {
|
|
|
|
#[arg(short, long, requires = "Source")]
|
|
|
|
add: bool,
|
|
|
|
|
|
|
|
#[command(flatten)]
|
|
|
|
source: Source,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(clap::Args, Debug)]
|
|
|
|
struct Source {
|
|
|
|
crates: Vec<String>,
|
|
|
|
#[arg(long)]
|
|
|
|
path: Option<std::path::PathBuf>,
|
|
|
|
#[arg(long)]
|
|
|
|
git: Option<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
const OUTPUT: &str = "\
|
2023-01-03 16:22:40 +00:00
|
|
|
error: the following required arguments were not provided:
|
2022-09-29 20:56:53 +00:00
|
|
|
<CRATES|--path <PATH>|--git <GIT>>
|
|
|
|
|
|
|
|
Usage: prog --add <CRATES|--path <PATH>|--git <GIT>>
|
|
|
|
|
2023-01-03 19:22:35 +00:00
|
|
|
For more information, try '--help'.
|
2022-09-29 20:56:53 +00:00
|
|
|
";
|
|
|
|
assert_output::<Opt>("prog --add", OUTPUT, true);
|
2022-09-30 17:24:18 +00:00
|
|
|
|
|
|
|
use clap::Args;
|
|
|
|
assert_eq!(Source::group_id(), Some(clap::Id::from("Source")));
|
|
|
|
assert_eq!(Opt::group_id(), Some(clap::Id::from("Opt")));
|
2022-09-29 20:56:53 +00:00
|
|
|
}
|
|
|
|
|
2022-09-30 14:05:48 +00:00
|
|
|
#[test]
|
|
|
|
fn skip_group_avoids_duplicate_ids() {
|
|
|
|
#[derive(Parser, Debug)]
|
2022-09-30 18:44:10 +00:00
|
|
|
#[group(skip)]
|
2022-09-30 14:05:48 +00:00
|
|
|
struct Opt {
|
|
|
|
#[command(flatten)]
|
|
|
|
first: Compose<Empty, Empty>,
|
|
|
|
#[command(flatten)]
|
|
|
|
second: Compose<Empty, Empty>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(clap::Args, Debug)]
|
2022-09-30 14:13:38 +00:00
|
|
|
#[group(skip)]
|
2022-09-30 14:05:48 +00:00
|
|
|
pub struct Compose<L: clap::Args, R: clap::Args> {
|
2023-02-19 00:42:07 +00:00
|
|
|
#[command(flatten)]
|
2022-09-30 14:05:48 +00:00
|
|
|
pub left: L,
|
2023-02-19 00:42:07 +00:00
|
|
|
#[command(flatten)]
|
2022-09-30 14:05:48 +00:00
|
|
|
pub right: R,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(clap::Args, Clone, Copy, Debug)]
|
2022-09-30 14:13:38 +00:00
|
|
|
#[group(skip)]
|
2022-09-30 14:05:48 +00:00
|
|
|
pub struct Empty;
|
|
|
|
|
|
|
|
use clap::CommandFactory;
|
|
|
|
Opt::command().debug_assert();
|
2022-09-30 17:24:18 +00:00
|
|
|
|
|
|
|
use clap::Args;
|
|
|
|
assert_eq!(Empty::group_id(), None);
|
|
|
|
assert_eq!(Compose::<Empty, Empty>::group_id(), None);
|
2022-09-30 18:44:10 +00:00
|
|
|
assert_eq!(Opt::group_id(), None);
|
2022-09-30 14:05:48 +00:00
|
|
|
}
|
2022-09-30 17:56:43 +00:00
|
|
|
|
2023-02-01 04:45:13 +00:00
|
|
|
#[test]
|
|
|
|
fn optional_flatten() {
|
|
|
|
#[derive(Parser, Debug, PartialEq, Eq)]
|
|
|
|
struct Opt {
|
|
|
|
#[command(flatten)]
|
|
|
|
source: Option<Source>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(clap::Args, Debug, PartialEq, Eq)]
|
|
|
|
struct Source {
|
|
|
|
crates: Vec<String>,
|
|
|
|
#[arg(long)]
|
|
|
|
path: Option<std::path::PathBuf>,
|
|
|
|
#[arg(long)]
|
|
|
|
git: Option<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(Opt { source: None }, Opt::try_parse_from(["test"]).unwrap());
|
|
|
|
assert_eq!(
|
|
|
|
Opt {
|
|
|
|
source: Some(Source {
|
|
|
|
crates: vec!["serde".to_owned()],
|
|
|
|
path: None,
|
|
|
|
git: None,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
Opt::try_parse_from(["test", "serde"]).unwrap()
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
Opt {
|
|
|
|
source: Some(Source {
|
|
|
|
crates: Vec::new(),
|
|
|
|
path: Some("./".into()),
|
|
|
|
git: None,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
Opt::try_parse_from(["test", "--path=./"]).unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-09-30 17:56:43 +00:00
|
|
|
#[test]
|
|
|
|
#[should_panic = "\
|
|
|
|
Command clap: Argument group name must be unique
|
|
|
|
|
2023-03-25 01:47:27 +00:00
|
|
|
\t'Compose' is already in use"]
|
2022-09-30 17:56:43 +00:00
|
|
|
fn helpful_panic_on_duplicate_groups() {
|
|
|
|
#[derive(Parser, Debug)]
|
|
|
|
struct Opt {
|
|
|
|
#[command(flatten)]
|
|
|
|
first: Compose<Empty, Empty>,
|
|
|
|
#[command(flatten)]
|
|
|
|
second: Compose<Empty, Empty>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(clap::Args, Debug)]
|
|
|
|
pub struct Compose<L: clap::Args, R: clap::Args> {
|
2023-02-19 00:42:07 +00:00
|
|
|
#[command(flatten)]
|
2022-09-30 17:56:43 +00:00
|
|
|
pub left: L,
|
2023-02-19 00:42:07 +00:00
|
|
|
#[command(flatten)]
|
2022-09-30 17:56:43 +00:00
|
|
|
pub right: R,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(clap::Args, Clone, Copy, Debug)]
|
|
|
|
pub struct Empty;
|
|
|
|
|
|
|
|
use clap::CommandFactory;
|
|
|
|
Opt::command().debug_assert();
|
|
|
|
}
|
2023-02-01 04:45:13 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn custom_group_id() {
|
|
|
|
#[derive(Parser, Debug, PartialEq, Eq)]
|
|
|
|
struct Opt {
|
|
|
|
#[command(flatten)]
|
|
|
|
source: Option<Source>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(clap::Args, Debug, PartialEq, Eq)]
|
|
|
|
#[group(id = "source")]
|
|
|
|
struct Source {
|
|
|
|
crates: Vec<String>,
|
|
|
|
#[arg(long)]
|
|
|
|
path: Option<std::path::PathBuf>,
|
|
|
|
#[arg(long)]
|
|
|
|
git: Option<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(Opt { source: None }, Opt::try_parse_from(["test"]).unwrap());
|
|
|
|
assert_eq!(
|
|
|
|
Opt {
|
|
|
|
source: Some(Source {
|
|
|
|
crates: vec!["serde".to_owned()],
|
|
|
|
path: None,
|
|
|
|
git: None,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
Opt::try_parse_from(["test", "serde"]).unwrap()
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
Opt {
|
|
|
|
source: Some(Source {
|
|
|
|
crates: Vec::new(),
|
|
|
|
path: Some("./".into()),
|
|
|
|
git: None,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
Opt::try_parse_from(["test", "--path=./"]).unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn required_group() {
|
|
|
|
#[derive(Parser, Debug, PartialEq, Eq)]
|
|
|
|
struct Opt {
|
|
|
|
#[command(flatten)]
|
|
|
|
source: Source,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(clap::Args, Debug, PartialEq, Eq)]
|
|
|
|
#[group(required = true, multiple = false)]
|
|
|
|
struct Source {
|
|
|
|
#[arg(long)]
|
|
|
|
path: Option<std::path::PathBuf>,
|
|
|
|
#[arg(long)]
|
|
|
|
git: Option<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
Opt {
|
|
|
|
source: Source {
|
|
|
|
path: Some("./".into()),
|
|
|
|
git: None,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Opt::try_parse_from(["test", "--path=./"]).unwrap()
|
|
|
|
);
|
|
|
|
|
|
|
|
const OUTPUT: &str = "\
|
|
|
|
error: the following required arguments were not provided:
|
|
|
|
<--path <PATH>|--git <GIT>>
|
|
|
|
|
|
|
|
Usage: test <--path <PATH>|--git <GIT>>
|
|
|
|
|
|
|
|
For more information, try '--help'.
|
|
|
|
";
|
|
|
|
assert_output::<Opt>("test", OUTPUT, true);
|
|
|
|
}
|