mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 06:42:33 +00:00
Merge pull request #2400 from ldm0/unset-default
Support unsetting/removing the default if an option/flag is set
This commit is contained in:
commit
30d784ffd1
5 changed files with 162 additions and 40 deletions
|
@ -110,7 +110,7 @@ pub struct Arg<'help> {
|
|||
pub(crate) validator_os: Option<Arc<Mutex<ValidatorOs<'help>>>>,
|
||||
pub(crate) val_delim: Option<char>,
|
||||
pub(crate) default_vals: Vec<&'help OsStr>,
|
||||
pub(crate) default_vals_ifs: VecMap<(Id, Option<&'help OsStr>, &'help OsStr)>,
|
||||
pub(crate) default_vals_ifs: VecMap<(Id, Option<&'help OsStr>, Option<&'help OsStr>)>,
|
||||
pub(crate) default_missing_vals: Vec<&'help OsStr>,
|
||||
pub(crate) env: Option<(&'help OsStr, Option<OsString>)>,
|
||||
pub(crate) terminator: Option<&'help str>,
|
||||
|
@ -2723,7 +2723,7 @@ impl<'help> Arg<'help> {
|
|||
/// .long("flag"))
|
||||
/// .arg(Arg::new("other")
|
||||
/// .long("other")
|
||||
/// .default_value_if("flag", None, "default"))
|
||||
/// .default_value_if("flag", None, Some("default")))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog", "--flag"
|
||||
/// ]);
|
||||
|
@ -2740,7 +2740,7 @@ impl<'help> Arg<'help> {
|
|||
/// .long("flag"))
|
||||
/// .arg(Arg::new("other")
|
||||
/// .long("other")
|
||||
/// .default_value_if("flag", None, "default"))
|
||||
/// .default_value_if("flag", None, Some("default")))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog"
|
||||
/// ]);
|
||||
|
@ -2758,7 +2758,7 @@ impl<'help> Arg<'help> {
|
|||
/// .long("opt"))
|
||||
/// .arg(Arg::new("other")
|
||||
/// .long("other")
|
||||
/// .default_value_if("opt", Some("special"), "default"))
|
||||
/// .default_value_if("opt", Some("special"), Some("default")))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog", "--opt", "special"
|
||||
/// ]);
|
||||
|
@ -2777,22 +2777,41 @@ impl<'help> Arg<'help> {
|
|||
/// .long("opt"))
|
||||
/// .arg(Arg::new("other")
|
||||
/// .long("other")
|
||||
/// .default_value_if("opt", Some("special"), "default"))
|
||||
/// .default_value_if("opt", Some("special"), Some("default")))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog", "--opt", "hahaha"
|
||||
/// ]);
|
||||
///
|
||||
/// assert_eq!(m.value_of("other"), None);
|
||||
/// ```
|
||||
///
|
||||
/// If we want to unset the default value for an Arg based on the presence or
|
||||
/// value of some other Arg.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg};
|
||||
/// let m = App::new("prog")
|
||||
/// .arg(Arg::new("flag")
|
||||
/// .long("flag"))
|
||||
/// .arg(Arg::new("other")
|
||||
/// .long("other")
|
||||
/// .default_value("default")
|
||||
/// .default_value_if("flag", None, None))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog", "--flag"
|
||||
/// ]);
|
||||
///
|
||||
/// assert_eq!(m.value_of("other"), None);
|
||||
/// ```
|
||||
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
||||
/// [`Arg::default_value`]: ./struct.Arg.html#method.default_value
|
||||
pub fn default_value_if<T: Key>(
|
||||
self,
|
||||
arg_id: T,
|
||||
val: Option<&'help str>,
|
||||
default: &'help str,
|
||||
default: Option<&'help str>,
|
||||
) -> Self {
|
||||
self.default_value_if_os(arg_id, val.map(OsStr::new), OsStr::new(default))
|
||||
self.default_value_if_os(arg_id, val.map(OsStr::new), default.map(OsStr::new))
|
||||
}
|
||||
|
||||
/// Provides a conditional default value in the exact same manner as [`Arg::default_value_if`]
|
||||
|
@ -2804,7 +2823,7 @@ impl<'help> Arg<'help> {
|
|||
mut self,
|
||||
arg_id: T,
|
||||
val: Option<&'help OsStr>,
|
||||
default: &'help OsStr,
|
||||
default: Option<&'help OsStr>,
|
||||
) -> Self {
|
||||
let l = self.default_vals_ifs.len();
|
||||
self.default_vals_ifs
|
||||
|
@ -2841,8 +2860,8 @@ impl<'help> Arg<'help> {
|
|||
/// .arg(Arg::new("other")
|
||||
/// .long("other")
|
||||
/// .default_value_ifs(&[
|
||||
/// ("flag", None, "default"),
|
||||
/// ("opt", Some("channal"), "chan"),
|
||||
/// ("flag", None, Some("default")),
|
||||
/// ("opt", Some("channal"), Some("chan")),
|
||||
/// ]))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog", "--opt", "channal"
|
||||
|
@ -2861,8 +2880,8 @@ impl<'help> Arg<'help> {
|
|||
/// .arg(Arg::new("other")
|
||||
/// .long("other")
|
||||
/// .default_value_ifs(&[
|
||||
/// ("flag", None, "default"),
|
||||
/// ("opt", Some("channal"), "chan"),
|
||||
/// ("flag", None, Some("default")),
|
||||
/// ("opt", Some("channal"), Some("chan")),
|
||||
/// ]))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog"
|
||||
|
@ -2885,8 +2904,8 @@ impl<'help> Arg<'help> {
|
|||
/// .arg(Arg::new("other")
|
||||
/// .long("other")
|
||||
/// .default_value_ifs(&[
|
||||
/// ("flag", None, "default"),
|
||||
/// ("opt", Some("channal"), "chan"),
|
||||
/// ("flag", None, Some("default")),
|
||||
/// ("opt", Some("channal"), Some("chan")),
|
||||
/// ]))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog", "--opt", "channal", "--flag"
|
||||
|
@ -2898,10 +2917,10 @@ impl<'help> Arg<'help> {
|
|||
/// [`Arg::default_value_if`]: ./struct.Arg.html#method.default_value_if
|
||||
pub fn default_value_ifs<T: Key>(
|
||||
mut self,
|
||||
ifs: &[(T, Option<&'help str>, &'help str)],
|
||||
ifs: &[(T, Option<&'help str>, Option<&'help str>)],
|
||||
) -> Self {
|
||||
for (arg, val, default) in ifs {
|
||||
self = self.default_value_if_os(arg, val.map(OsStr::new), OsStr::new(*default));
|
||||
self = self.default_value_if_os(arg, val.map(OsStr::new), default.map(OsStr::new));
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -2913,10 +2932,10 @@ impl<'help> Arg<'help> {
|
|||
/// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
|
||||
pub fn default_value_ifs_os<T: Key>(
|
||||
mut self,
|
||||
ifs: &[(T, Option<&'help OsStr>, &'help OsStr)],
|
||||
ifs: &[(T, Option<&'help OsStr>, Option<&'help OsStr>)],
|
||||
) -> Self {
|
||||
for (arg, val, default) in ifs {
|
||||
self = self.default_value_if_os(arg.key(), *val, default);
|
||||
self = self.default_value_if_os(arg.key(), *val, *default);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
|
|
@ -43,7 +43,11 @@ macro_rules! yaml_tuple3 {
|
|||
for ys in vec {
|
||||
if let Some(tup) = ys.as_vec() {
|
||||
debug_assert_eq!(3, tup.len());
|
||||
$a = $a.$c(yaml_str!(tup[0]), yaml_opt_str!(tup[1]), yaml_str!(tup[2]));
|
||||
$a = $a.$c(
|
||||
yaml_str!(tup[0]),
|
||||
yaml_opt_str!(tup[1]),
|
||||
yaml_opt_str!(tup[2]),
|
||||
);
|
||||
} else {
|
||||
panic!("Failed to convert YAML value to vec");
|
||||
}
|
||||
|
|
|
@ -1435,7 +1435,9 @@ impl<'help, 'app> Parser<'help, 'app> {
|
|||
};
|
||||
|
||||
if add {
|
||||
self.add_val_to_arg(arg, ArgStr::new(default), matcher, ty, false);
|
||||
if let Some(default) = default {
|
||||
self.add_val_to_arg(arg, ArgStr::new(default), matcher, ty, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ fn osstr_positional_user_override() {
|
|||
fn default_if_arg_present_no_default() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", None, "default"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", None, Some("default")))
|
||||
.try_get_matches_from(vec!["", "--opt", "some"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
|
@ -133,7 +133,7 @@ fn default_if_arg_present_no_default() {
|
|||
fn default_if_arg_present_no_default_user_override() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", None, "default"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", None, Some("default")))
|
||||
.try_get_matches_from(vec!["", "--opt", "some", "other"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
|
@ -148,7 +148,7 @@ fn default_if_arg_present_no_arg_with_default() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_if("opt", None, "default"),
|
||||
.default_value_if("opt", None, Some("default")),
|
||||
)
|
||||
.try_get_matches_from(vec![""]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -164,7 +164,7 @@ fn default_if_arg_present_with_default() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_if("opt", None, "default"),
|
||||
.default_value_if("opt", None, Some("default")),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--opt", "some"]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -180,7 +180,7 @@ fn default_if_arg_present_with_default_user_override() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_if("opt", None, "default"),
|
||||
.default_value_if("opt", None, Some("default")),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--opt", "some", "other"]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -196,7 +196,7 @@ fn default_if_arg_present_no_arg_with_default_user_override() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_if("opt", None, "default"),
|
||||
.default_value_if("opt", None, Some("default")),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "other"]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -211,7 +211,7 @@ fn default_if_arg_present_no_arg_with_default_user_override() {
|
|||
fn default_if_arg_present_with_value_no_default() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", Some("value"), "default"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", Some("value"), Some("default")))
|
||||
.try_get_matches_from(vec!["", "--opt", "value"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
|
@ -223,7 +223,7 @@ fn default_if_arg_present_with_value_no_default() {
|
|||
fn default_if_arg_present_with_value_no_default_fail() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", Some("value"), "default"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", Some("value"), Some("default")))
|
||||
.try_get_matches_from(vec!["", "--opt", "other"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
|
@ -234,7 +234,7 @@ fn default_if_arg_present_with_value_no_default_fail() {
|
|||
fn default_if_arg_present_with_value_no_default_user_override() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", Some("some"), "default"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", Some("some"), Some("default")))
|
||||
.try_get_matches_from(vec!["", "--opt", "some", "other"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
|
@ -249,7 +249,7 @@ fn default_if_arg_present_with_value_no_arg_with_default() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_if("opt", Some("some"), "default"),
|
||||
.default_value_if("opt", Some("some"), Some("default")),
|
||||
)
|
||||
.try_get_matches_from(vec![""]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -265,7 +265,7 @@ fn default_if_arg_present_with_value_no_arg_with_default_fail() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_if("opt", Some("some"), "default"),
|
||||
.default_value_if("opt", Some("some"), Some("default")),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--opt", "other"]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -281,7 +281,7 @@ fn default_if_arg_present_with_value_with_default() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_if("opt", Some("some"), "default"),
|
||||
.default_value_if("opt", Some("some"), Some("default")),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--opt", "some"]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -297,7 +297,7 @@ fn default_if_arg_present_with_value_with_default_user_override() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_if("opt", Some("some"), "default"),
|
||||
.default_value_if("opt", Some("some"), Some("default")),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--opt", "some", "other"]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -313,7 +313,7 @@ fn default_if_arg_present_no_arg_with_value_with_default_user_override() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_if("opt", Some("some"), "default"),
|
||||
.default_value_if("opt", Some("some"), Some("default")),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "other"]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -329,7 +329,7 @@ fn default_if_arg_present_no_arg_with_value_with_default_user_override_fail() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_if("opt", Some("some"), "default"),
|
||||
.default_value_if("opt", Some("some"), Some("default")),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--opt", "value", "other"]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -338,6 +338,78 @@ fn default_if_arg_present_no_arg_with_value_with_default_user_override_fail() {
|
|||
assert_eq!(m.value_of("arg").unwrap(), "other");
|
||||
}
|
||||
|
||||
// Unsetting the default
|
||||
|
||||
#[test]
|
||||
fn option_default_if_arg_present_with_value_no_default() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", Some("value"), Some("default")))
|
||||
.try_get_matches_from(vec!["", "--opt", "value"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.value_of("arg").unwrap(), "default");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_default_if_arg_present_with_value_no_default() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(Arg::from("[arg] 'some arg'").default_value_if("opt", Some("value"), None))
|
||||
.try_get_matches_from(vec!["", "--opt", "value"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(!m.is_present("arg"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_default_if_arg_present_with_value_with_default() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("default")
|
||||
.default_value_if("opt", Some("value"), None),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--opt", "value"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(!m.is_present("arg"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_default_if_arg_present_with_value_with_default_user_override() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("default")
|
||||
.default_value_if("opt", Some("value"), None),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--opt", "value", "other"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.value_of("arg").unwrap(), "other");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_default_if_arg_present_no_arg_with_value_with_default() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("default")
|
||||
.default_value_if("opt", Some("value"), None),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--opt", "other"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.value_of("arg").unwrap(), "default");
|
||||
}
|
||||
|
||||
// Multiple conditions
|
||||
|
||||
#[test]
|
||||
|
@ -348,7 +420,10 @@ fn default_ifs_arg_present() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_ifs(&[("opt", Some("some"), "default"), ("flag", None, "flg")]),
|
||||
.default_value_ifs(&[
|
||||
("opt", Some("some"), Some("default")),
|
||||
("flag", None, Some("flg")),
|
||||
]),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--flag"]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -357,6 +432,22 @@ fn default_ifs_arg_present() {
|
|||
assert_eq!(m.value_of("arg").unwrap(), "flg");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_default_ifs_arg_present() {
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from("--opt [FILE] 'some arg'"))
|
||||
.arg(Arg::from("--flag 'some arg'"))
|
||||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_ifs(&[("opt", Some("some"), Some("default")), ("flag", None, None)]),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--flag"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(!m.is_present("arg"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_ifs_arg_present_user_override() {
|
||||
let r = App::new("df")
|
||||
|
@ -365,7 +456,10 @@ fn default_ifs_arg_present_user_override() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_ifs(&[("opt", Some("some"), "default"), ("flag", None, "flg")]),
|
||||
.default_value_ifs(&[
|
||||
("opt", Some("some"), Some("default")),
|
||||
("flag", None, Some("flg")),
|
||||
]),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--flag", "value"]);
|
||||
assert!(r.is_ok());
|
||||
|
@ -382,7 +476,10 @@ fn default_ifs_arg_present_order() {
|
|||
.arg(
|
||||
Arg::from("[arg] 'some arg'")
|
||||
.default_value("first")
|
||||
.default_value_ifs(&[("opt", Some("some"), "default"), ("flag", None, "flg")]),
|
||||
.default_value_ifs(&[
|
||||
("opt", Some("some"), Some("default")),
|
||||
("flag", None, Some("flg")),
|
||||
]),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "--opt=some", "--flag"]);
|
||||
assert!(r.is_ok());
|
||||
|
|
|
@ -454,10 +454,10 @@ fn multiarg() {
|
|||
let app = clap_app!(claptests =>
|
||||
(@arg flag: --flag "value")
|
||||
(@arg multiarg: --multiarg
|
||||
default_value("flag-unset") default_value_if("flag", None, "flag-set")
|
||||
default_value("flag-unset") default_value_if("flag", None, Some("flag-set"))
|
||||
"multiarg")
|
||||
(@arg multiarg2: --multiarg2
|
||||
default_value("flag-unset") default_value_if("flag", None, "flag-set",)
|
||||
default_value("flag-unset") default_value_if("flag", None, Some("flag-set"))
|
||||
"multiarg2")
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue