Skip to content

Commit

Permalink
Merge pull request clap-rs#4213 from epage/reset
Browse files Browse the repository at this point in the history
feat: Allow resetting builder methods
  • Loading branch information
epage authored Sep 13, 2022
2 parents ee387c6 + 23ce67e commit 7ee121a
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 124 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ Deprecated
- `Arg::requires_all` in favor of `Arg::requires_ifs` now that it takes an `ArgPredicate` to avoid having multiple ways of doing the same thing
- `Arg::number_of_values` in favor of `Arg::num_args` to clarify semantic differences
- `default_value_os`, `default_values_os`, `default_value_if_os`, and `default_value_ifs_os` as the non `_os` variants now accept either a `str` or an `OsStr` (#4141)
- `Arg::env_os` in favor of `Arg::env`
- `Command::dont_collapse_args_in_usage` is now the default (#4151)
- `Command::trailing_var_arg` in favor of `Arg::trailing_var_arg` to make it clearer which arg it is meant to apply to (#4187)
- `Command::allow_hyphen_values` in favor of `Arg::allow_hyphen_values` to make it clearer which arg it is meant to apply to (#4187)
Expand All @@ -262,6 +263,7 @@ Behavior Changes

- `Arg::num_args` now accepts ranges, allowing setting both the minimum and maximum number of values per occurrence (#2688, #4023)
- Allow non-bool `value_parser`s for `ArgAction::SetTrue` / `ArgAction::SetFalse` (#4092)
- Allow resetting most builder methods
- *(error)* `Error::apply` for changing the formatter for dropping binary size (#4111)
- *(help)* Show `PossibleValue::help` in long help (`--help`) (#3312)
- *(help)* New `{tab}` variable for `Command::help_template` (#4161)
Expand Down
180 changes: 117 additions & 63 deletions src/builder/arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,13 @@ impl Arg {
/// ```
#[inline]
#[must_use]
pub fn short(mut self, s: char) -> Self {
assert!(s != '-', "short option name cannot be `-`");

self.short = Some(s);
pub fn short(mut self, s: impl IntoResettable<char>) -> Self {
if let Some(s) = s.into_resettable().into_option() {
assert!(s != '-', "short option name cannot be `-`");
self.short = Some(s);
} else {
self.short = None;
}
self
}

Expand Down Expand Up @@ -182,8 +185,8 @@ impl Arg {
/// ```
#[inline]
#[must_use]
pub fn long(mut self, l: impl Into<Str>) -> Self {
self.long = Some(l.into());
pub fn long(mut self, l: impl IntoResettable<Str>) -> Self {
self.long = l.into_resettable().into_option();
self
}

Expand All @@ -207,8 +210,12 @@ impl Arg {
/// assert_eq!(m.get_one::<String>("test").unwrap(), "cool");
/// ```
#[must_use]
pub fn alias(mut self, name: impl Into<Str>) -> Self {
self.aliases.push((name.into(), false));
pub fn alias(mut self, name: impl IntoResettable<Str>) -> Self {
if let Some(name) = name.into_resettable().into_option() {
self.aliases.push((name, false));
} else {
self.aliases.clear();
}
self
}

Expand All @@ -232,10 +239,13 @@ impl Arg {
/// assert_eq!(m.get_one::<String>("test").unwrap(), "cool");
/// ```
#[must_use]
pub fn short_alias(mut self, name: char) -> Self {
assert!(name != '-', "short alias name cannot be `-`");

self.short_aliases.push((name, false));
pub fn short_alias(mut self, name: impl IntoResettable<char>) -> Self {
if let Some(name) = name.into_resettable().into_option() {
assert!(name != '-', "short alias name cannot be `-`");
self.short_aliases.push((name, false));
} else {
self.short_aliases.clear();
}
self
}

Expand Down Expand Up @@ -317,8 +327,12 @@ impl Arg {
/// ```
/// [`Command::alias`]: Arg::alias()
#[must_use]
pub fn visible_alias(mut self, name: impl Into<Str>) -> Self {
self.aliases.push((name.into(), true));
pub fn visible_alias(mut self, name: impl IntoResettable<Str>) -> Self {
if let Some(name) = name.into_resettable().into_option() {
self.aliases.push((name, true));
} else {
self.aliases.clear();
}
self
}

Expand All @@ -341,10 +355,13 @@ impl Arg {
/// assert_eq!(m.get_one::<String>("test").unwrap(), "coffee");
/// ```
#[must_use]
pub fn visible_short_alias(mut self, name: char) -> Self {
assert!(name != '-', "short alias name cannot be `-`");

self.short_aliases.push((name, true));
pub fn visible_short_alias(mut self, name: impl IntoResettable<char>) -> Self {
if let Some(name) = name.into_resettable().into_option() {
assert!(name != '-', "short alias name cannot be `-`");
self.short_aliases.push((name, true));
} else {
self.short_aliases.clear();
}
self
}

Expand Down Expand Up @@ -454,8 +471,8 @@ impl Arg {
/// [`Command`]: crate::Command
#[inline]
#[must_use]
pub fn index(mut self, idx: usize) -> Self {
self.index = Some(idx);
pub fn index(mut self, idx: impl IntoResettable<usize>) -> Self {
self.index = idx.into_resettable().into_option();
self
}

Expand Down Expand Up @@ -694,8 +711,12 @@ impl Arg {
/// [Conflicting]: Arg::conflicts_with()
/// [override]: Arg::overrides_with()
#[must_use]
pub fn requires(mut self, arg_id: impl Into<Id>) -> Self {
self.requires.push((ArgPredicate::IsPresent, arg_id.into()));
pub fn requires(mut self, arg_id: impl IntoResettable<Id>) -> Self {
if let Some(arg_id) = arg_id.into_resettable().into_option() {
self.requires.push((ArgPredicate::IsPresent, arg_id));
} else {
self.requires.clear();
}
self
}

Expand Down Expand Up @@ -841,8 +862,8 @@ impl Arg {
/// ```
#[inline]
#[must_use]
pub fn action(mut self, action: ArgAction) -> Self {
self.action = Some(action);
pub fn action(mut self, action: impl IntoResettable<ArgAction>) -> Self {
self.action = action.into_resettable().into_option();
self
}

Expand Down Expand Up @@ -901,8 +922,8 @@ impl Arg {
/// .expect("required");
/// assert_eq!(port, 3001);
/// ```
pub fn value_parser(mut self, parser: impl Into<super::ValueParser>) -> Self {
self.value_parser = Some(parser.into());
pub fn value_parser(mut self, parser: impl IntoResettable<super::ValueParser>) -> Self {
self.value_parser = parser.into_resettable().into_option();
self
}

Expand Down Expand Up @@ -1053,9 +1074,8 @@ impl Arg {
/// ```
#[inline]
#[must_use]
pub fn num_args(mut self, qty: impl Into<ValueRange>) -> Self {
let qty = qty.into();
self.num_vals = Some(qty);
pub fn num_args(mut self, qty: impl IntoResettable<ValueRange>) -> Self {
self.num_vals = qty.into_resettable().into_option();
self
}

Expand Down Expand Up @@ -1114,8 +1134,13 @@ impl Arg {
/// [`Arg::action(ArgAction::Set)`]: Arg::action()
#[inline]
#[must_use]
pub fn value_name(self, name: impl Into<Str>) -> Self {
self.value_names([name])
pub fn value_name(mut self, name: impl IntoResettable<Str>) -> Self {
if let Some(name) = name.into_resettable().into_option() {
self.value_names([name])
} else {
self.val_names.clear();
self
}
}

/// Placeholders for the argument's values in the help message / usage.
Expand Down Expand Up @@ -1206,8 +1231,8 @@ impl Arg {
/// );
/// ```
#[must_use]
pub fn value_hint(mut self, value_hint: ValueHint) -> Self {
self.value_hint = Some(value_hint);
pub fn value_hint(mut self, value_hint: impl IntoResettable<ValueHint>) -> Self {
self.value_hint = value_hint.into_resettable().into_option();
self
}

Expand Down Expand Up @@ -1451,8 +1476,8 @@ impl Arg {
/// [`Arg::action(ArgAction::Set)`]: Arg::action()
#[inline]
#[must_use]
pub fn value_delimiter(mut self, d: impl Into<Option<char>>) -> Self {
self.val_delim = d.into();
pub fn value_delimiter(mut self, d: impl IntoResettable<char>) -> Self {
self.val_delim = d.into_resettable().into_option();
self
}

Expand Down Expand Up @@ -1504,8 +1529,8 @@ impl Arg {
/// [`num_args`]: Arg::num_args()
#[inline]
#[must_use]
pub fn value_terminator(mut self, term: impl Into<Str>) -> Self {
self.terminator = Some(term.into());
pub fn value_terminator(mut self, term: impl IntoResettable<Str>) -> Self {
self.terminator = term.into_resettable().into_option();
self
}

Expand Down Expand Up @@ -1596,8 +1621,13 @@ impl Arg {
/// [`Arg::default_value_if`]: Arg::default_value_if()
#[inline]
#[must_use]
pub fn default_value(self, val: impl Into<OsStr>) -> Self {
self.default_values([val])
pub fn default_value(mut self, val: impl IntoResettable<OsStr>) -> Self {
if let Some(val) = val.into_resettable().into_option() {
self.default_values([val])
} else {
self.default_vals.clear();
self
}
}

#[inline]
Expand Down Expand Up @@ -1725,8 +1755,13 @@ impl Arg {
/// [`Arg::default_value`]: Arg::default_value()
#[inline]
#[must_use]
pub fn default_missing_value(self, val: impl Into<OsStr>) -> Self {
self.default_missing_values_os([val])
pub fn default_missing_value(mut self, val: impl IntoResettable<OsStr>) -> Self {
if let Some(val) = val.into_resettable().into_option() {
self.default_missing_values_os([val])
} else {
self.default_missing_vals.clear();
self
}
}

/// Value for the argument when the flag is present but no value is specified.
Expand Down Expand Up @@ -1916,21 +1951,24 @@ impl Arg {
#[cfg(feature = "env")]
#[inline]
#[must_use]
pub fn env(self, name: impl Into<OsStr>) -> Self {
self.env_os(name)
pub fn env(mut self, name: impl IntoResettable<OsStr>) -> Self {
if let Some(name) = name.into_resettable().into_option() {
let value = env::var_os(&name);
self.env = Some((name, value));
} else {
self.env = None;
}
self
}

/// Read from `name` environment variable when argument is not present.
///
/// See [`Arg::env`].
#[cfg(feature = "env")]
#[inline]
#[must_use]
pub fn env_os(mut self, name: impl Into<OsStr>) -> Self {
let name = name.into();
let value = env::var_os(&name);
self.env = Some((name, value));
self
#[doc(hidden)]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "4.0.0", note = "Replaced with `Arg::env`")
)]
pub fn env_os(self, name: impl Into<OsStr>) -> Self {
self.env(name)
}
}

Expand Down Expand Up @@ -2099,8 +2137,8 @@ impl Arg {
/// [index]: Arg::index()
#[inline]
#[must_use]
pub fn display_order(mut self, ord: usize) -> Self {
self.disp_ord = Some(ord);
pub fn display_order(mut self, ord: impl IntoResettable<usize>) -> Self {
self.disp_ord = ord.into_resettable().into_option();
self
}

Expand Down Expand Up @@ -2516,8 +2554,12 @@ impl Arg {
///
/// [`ArgGroup`]: crate::ArgGroup
#[must_use]
pub fn group(mut self, group_id: impl Into<Id>) -> Self {
self.groups.push(group_id.into());
pub fn group(mut self, group_id: impl IntoResettable<Id>) -> Self {
if let Some(group_id) = group_id.into_resettable().into_option() {
self.groups.push(group_id);
} else {
self.groups.clear();
}
self
}

Expand Down Expand Up @@ -2873,8 +2915,12 @@ impl Arg {
/// ```
/// [required]: Arg::required()
#[must_use]
pub fn required_unless_present(mut self, arg_id: impl Into<Id>) -> Self {
self.r_unless.push(arg_id.into());
pub fn required_unless_present(mut self, arg_id: impl IntoResettable<Id>) -> Self {
if let Some(arg_id) = arg_id.into_resettable().into_option() {
self.r_unless.push(arg_id);
} else {
self.r_unless.clear();
}
self
}

Expand Down Expand Up @@ -3476,8 +3522,12 @@ impl Arg {
/// [`Arg::conflicts_with_all(names)`]: Arg::conflicts_with_all()
/// [`Arg::exclusive(true)`]: Arg::exclusive()
#[must_use]
pub fn conflicts_with(mut self, arg_id: impl Into<Id>) -> Self {
self.blacklist.push(arg_id.into());
pub fn conflicts_with(mut self, arg_id: impl IntoResettable<Id>) -> Self {
if let Some(arg_id) = arg_id.into_resettable().into_option() {
self.blacklist.push(arg_id);
} else {
self.blacklist.clear();
}
self
}

Expand Down Expand Up @@ -3564,8 +3614,12 @@ impl Arg {
/// assert!(!*m.get_one::<bool>("flag").unwrap());
/// ```
#[must_use]
pub fn overrides_with(mut self, arg_id: impl Into<Id>) -> Self {
self.overrides.push(arg_id.into());
pub fn overrides_with(mut self, arg_id: impl IntoResettable<Id>) -> Self {
if let Some(arg_id) = arg_id.into_resettable().into_option() {
self.overrides.push(arg_id);
} else {
self.overrides.clear();
}
self
}

Expand Down
Loading

0 comments on commit 7ee121a

Please sign in to comment.