New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
requires_ifs does not appear to work #3059
Comments
This works if I change
to
|
Yes
|
And I do feel like we could do a better job clarifying that distinction |
However, while Basically I'm looking for a way to:
Am I missing some magic combo? |
Could you provide code with those cases so we know which APIs you are using in which ways to try to get the behavior you are wanting that isn't working as expected? |
Basically I want the two options to be required of each other |
@epage Here are the four combo's (2-required_ifs and 2-requires_ifs). I expect all to fail but only the first does: #[test]
fn test_requiredifs_options_without_file_fail() {
let res = App::new("prog")
.arg(
Arg::with_name("output")
.long("output")
.short("o")
.takes_value(true)
.possible_values(&["csv", "excel", "stdout"])
.default_value("stdout")
.help("Direct output to file"),
)
.arg(
Arg::with_name("filename")
.long("filename")
.short("f")
.takes_value(true)
.required_ifs(&[("output", "excel"), ("output", "csv")])
.help("Filename for '-o excel' or '-o csv' output"),
)
.get_matches_from_safe(vec!["prog", "-o", "excel"]);
assert!(res.is_err()); // We used -o excel so -f <filename> is required
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
}
#[test]
fn test_requiredifs_options_without_output_should_fail() {
let res = App::new("prog")
.arg(
Arg::with_name("output")
.long("output")
.short("o")
.takes_value(true)
.possible_values(&["csv", "excel", "stdout"])
.default_value("stdout")
.help("Direct output to file"),
)
.arg(
Arg::with_name("filename")
.long("filename")
.short("f")
.takes_value(true)
.required_ifs(&[("output", "excel"), ("output", "csv")])
.help("Filename for '-o excel' or '-o csv' output"),
)
.get_matches_from_safe(vec!["prog", "-f", "filename"]);
assert!(res.is_err()); // We used -o excel so -f <filename> is required
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
}
#[test]
fn test_requiresif_options_without_file_should_fail() {
let res = App::new("prog")
.arg(
Arg::with_name("output")
.long("output")
.short("o")
.takes_value(true)
.possible_values(&["csv", "excel", "stdout"])
.default_value("stdout")
.help("Direct output to file"),
)
.arg(
Arg::with_name("filename")
.long("filename")
.short("f")
.takes_value(true)
.requires_ifs(&[("output", "excel"), ("output", "csv")])
.help("Filename for '-o excel' or '-o csv' output"),
)
.get_matches_from_safe(vec!["prog", "-o", "excel"]);
assert!(res.is_err()); // We used -o excel so -f <filename> is required
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
}
#[test]
fn test_requiresif_options_without_output_should_fail() {
let res = App::new("prog")
.arg(
Arg::with_name("output")
.long("output")
.short("o")
.takes_value(true)
.possible_values(&["csv", "excel", "stdout"])
.default_value("stdout")
.help("Direct output to file"),
)
.arg(
Arg::with_name("filename")
.long("filename")
.short("f")
.takes_value(true)
.requires_ifs(&[("output", "excel"), ("output", "csv")])
.help("Filename for '-o excel' or '-o csv' output"),
)
.get_matches_from_safe(vec!["prog", "-f", "somefile"]);
assert!(res.is_err()); // We used -o excel so -f <filename> is required
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
} |
What you are looking for is something like use clap::{App, Arg, ErrorKind};
fn main() {}
#[test]
fn test_requiresif_options_without_output_should_fail() {
let mut app = App::new("prog")
.arg(
Arg::new("output")
.long("output")
.short('o')
.takes_value(true)
.possible_values(&["csv", "excel", "stdout"])
.requires_ifs(&[("excel", "filename"), ("csv", "filename")])
.help("Direct output to file"),
)
.arg(
Arg::new("filename")
.long("filename")
.short('f')
.takes_value(true)
.requires("output")
.help("Filename for '-o excel' or '-o csv' output"),
);
let res = app.try_get_matches_from_mut(vec!["prog", "-f", "somefile"]);
assert!(res.is_err()); // We used -o excel so -f <filename> is required
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
let res = app.try_get_matches_from_mut(vec!["prog", "-o", "excel"]);
assert!(res.is_err()); // We used -o excel so -f <filename> is required
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
let res = app.try_get_matches_from_mut(vec!["prog", "-o", "stdout"]);
assert!(res.is_ok(), "{:?}", res);
let res = app.try_get_matches_from_mut(vec!["prog", "-o", "excel", "-f", "file.xls"]);
assert!(res.is_ok(), "{:?}", res);
} This is written with clap3. I've not checked to see if there are any gotchas backporting to clap2. Even with clap3, I had to remove the |
Ok, so I had it bass-ackwards to begin with. I can work with your solution if you want to close this And thanks for your help! |
Please complete the following tasks
Rust Version
rustc 1.55.0 (c8dfcfe04 2021-09-06)
Clap Version
clap = "2.33.3"
Minimal reproducible code
Steps to reproduce the bug with the above code
cargo test
Actual Behaviour
No error occurred
Expected Behaviour
Expected error as the
-f <val>
is required if-o excel
or-o csv
is presentAdditional Context
No response
Debug Output
No response
The text was updated successfully, but these errors were encountered: