Skip to content

Commit f167424

Browse files
committed
feat: Add default_values_if and default_values_ifs to match default_values
1 parent 475cbdc commit f167424

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-4
lines changed

clap_builder/src/builder/arg.rs

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ pub struct Arg {
8181
pub(crate) num_vals: Option<ValueRange>,
8282
pub(crate) val_delim: Option<char>,
8383
pub(crate) default_vals: Vec<OsStr>,
84-
pub(crate) default_vals_ifs: Vec<(Id, ArgPredicate, Option<OsStr>)>,
84+
pub(crate) default_vals_ifs: Vec<(Id, ArgPredicate, Vec<Option<OsStr>>)>,
8585
pub(crate) default_missing_vals: Vec<OsStr>,
8686
#[cfg(feature = "env")]
8787
pub(crate) env: Option<(OsStr, Option<OsString>)>,
@@ -3058,11 +3058,62 @@ impl Arg {
30583058
self.default_vals_ifs.push((
30593059
arg_id.into(),
30603060
predicate.into(),
3061-
default.into_resettable().into_option(),
3061+
vec![default.into_resettable().into_option()],
30623062
));
30633063
self
30643064
}
30653065

3066+
/// Specifies the values of the argument if `arg` has been used at runtime.
3067+
///
3068+
/// See [`Arg::default_value_if`].
3069+
///
3070+
/// # Examples
3071+
///
3072+
/// ```rust
3073+
/// use clap_builder::arg;
3074+
/// use clap_builder::Command;
3075+
/// use clap_builder::Arg;
3076+
/// let r = Command::new("df")
3077+
/// .arg(arg!(--opt <FILE> "some arg"))
3078+
/// .arg(
3079+
/// Arg::new("args")
3080+
/// .long("args")
3081+
/// .num_args(2)
3082+
/// .default_values_if("opt", "value", ["df1","df2"]),
3083+
/// )
3084+
/// .try_get_matches_from(vec!["", "--opt", "value"]);
3085+
///
3086+
/// let m = r.unwrap();
3087+
/// assert_eq!(
3088+
/// m.get_many::<String>("args").unwrap().collect::<Vec<_>>(),
3089+
/// ["df1", "df2"]
3090+
/// );
3091+
/// ```
3092+
///
3093+
/// [`Arg::default_value_if`]: Arg::default_value_if()
3094+
#[must_use]
3095+
pub fn default_values_if(
3096+
mut self,
3097+
arg_id: impl Into<Id>,
3098+
predicate: impl Into<ArgPredicate>,
3099+
defaults: impl IntoIterator<Item = impl Into<OsStr>>,
3100+
) -> Self {
3101+
let default_vals: Vec<Option<OsStr>> = defaults
3102+
.into_iter()
3103+
.map(|val| {
3104+
let val_osstr: OsStr = val.into();
3105+
if val_osstr.is_empty() {
3106+
None
3107+
} else {
3108+
Some(val_osstr)
3109+
}
3110+
})
3111+
.collect();
3112+
self.default_vals_ifs
3113+
.push((arg_id.into(), predicate.into(), default_vals));
3114+
self
3115+
}
3116+
30663117
#[must_use]
30673118
#[doc(hidden)]
30683119
#[cfg_attr(
@@ -3185,6 +3236,28 @@ impl Arg {
31853236
self
31863237
}
31873238

3239+
/// Specifies multiple values and conditions in the same manner as [`Arg::default_values_if`].
3240+
///
3241+
/// See [`Arg::default_values_if`].
3242+
///
3243+
/// [`Arg::default_values_if`]: Arg::default_values_if()
3244+
#[must_use]
3245+
pub fn default_values_ifs(
3246+
mut self,
3247+
ifs: impl IntoIterator<
3248+
Item = (
3249+
impl Into<Id>,
3250+
impl Into<ArgPredicate>,
3251+
impl IntoIterator<Item = impl Into<OsStr>>,
3252+
),
3253+
>,
3254+
) -> Self {
3255+
for (arg, predicate, default) in ifs {
3256+
self = self.default_values_if(arg, predicate, default);
3257+
}
3258+
self
3259+
}
3260+
31883261
#[must_use]
31893262
#[doc(hidden)]
31903263
#[cfg_attr(

clap_builder/src/parser/parser.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,8 +1461,13 @@ impl<'cmd> Parser<'cmd> {
14611461
};
14621462

14631463
if add {
1464-
if let Some(default) = default {
1465-
let arg_values = vec![default.to_os_string()];
1464+
let arg_values: Vec<_> = default
1465+
.iter()
1466+
.filter_map(|option_val| {
1467+
option_val.as_ref().map(|val| val.to_os_string())
1468+
})
1469+
.collect();
1470+
if !arg_values.is_empty() {
14661471
let trailing_idx = None;
14671472
let _ = ok!(self.react(
14681473
None,

0 commit comments

Comments
 (0)