mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
feat(build/arg/mod.rs): default_vals_if supports an Option as the default
This commit is contained in:
parent
42c03775b5
commit
6626365359
3 changed files with 134 additions and 14 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>,
|
||||
|
@ -2693,7 +2693,8 @@ impl<'help> Arg<'help> {
|
|||
|
||||
/// Specifies the value of the argument if `arg` has been used at runtime. If `val` is set to
|
||||
/// `None`, `arg` only needs to be present. If `val` is set to `"some-val"` then `arg` must be
|
||||
/// present at runtime **and** have the value `val`.
|
||||
/// present at runtime **and** have the value `val`. Setting `default` to `None` removes any
|
||||
/// existing default.
|
||||
///
|
||||
/// **NOTE:** This setting is perfectly compatible with [`Arg::default_value`] but slightly
|
||||
/// different. `Arg::default_value` *only* takes affect when the user has not provided this arg
|
||||
|
@ -2723,7 +2724,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 +2741,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 +2759,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 +2778,44 @@ 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);
|
||||
/// ```
|
||||
///
|
||||
/// We can also remove a default if the flag was set.
|
||||
///
|
||||
/// ```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: impl Into<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.into().map(|s| OsStr::new(s)),
|
||||
)
|
||||
}
|
||||
|
||||
/// Provides a conditional default value in the exact same manner as [`Arg::default_value_if`]
|
||||
|
@ -2804,11 +2827,11 @@ impl<'help> Arg<'help> {
|
|||
mut self,
|
||||
arg_id: T,
|
||||
val: Option<&'help OsStr>,
|
||||
default: &'help OsStr,
|
||||
default: impl Into<Option<&'help OsStr>>,
|
||||
) -> Self {
|
||||
let l = self.default_vals_ifs.len();
|
||||
self.default_vals_ifs
|
||||
.insert(l, (arg_id.into(), val, default));
|
||||
.insert(l, (arg_id.into(), val, default.into()));
|
||||
self.takes_value(true)
|
||||
}
|
||||
|
||||
|
@ -2898,10 +2921,12 @@ 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>, impl Into<Option<&'help str>> + Copy)],
|
||||
) -> Self {
|
||||
for (arg, val, default) in ifs {
|
||||
self = self.default_value_if_os(arg, val.map(OsStr::new), OsStr::new(*default));
|
||||
let default: Option<&'help str> = (*default).into();
|
||||
self =
|
||||
self.default_value_if_os(arg, val.map(OsStr::new), default.map(|s| OsStr::new(s)));
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -2913,9 +2938,14 @@ 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>,
|
||||
impl Into<Option<&'help OsStr>> + Copy,
|
||||
)],
|
||||
) -> Self {
|
||||
for (arg, val, default) in ifs {
|
||||
let default: Option<&'help OsStr> = (*default).into();
|
||||
self = self.default_value_if_os(arg.key(), *val, default);
|
||||
}
|
||||
self
|
||||
|
|
|
@ -1427,7 +1427,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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
@ -357,6 +429,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")
|
||||
|
|
Loading…
Reference in a new issue