Repository: clap-rs/clap (language: rust)

Issue:
More Resettable builder methods
## Command
### Application-wide Settings
- `term_width`
- `max_term_width`
**Also what is the actual difference in behavior, I feel the documentation is lacking**


### Command-specific Settings
- [x] `bin_name`
- [x] `display_name`
- [x] `author`
- [x] `about`
- [x] `long_about`
- [x] `after_help`
- [x] `after_long_help`
- [x] `before_help`
- [x] `before_long_help`
- [x] `version`
- [x] `long_version`
- [x] `override_usage`
- [x] `override_help`
- [x] `help_template`
- [x] `next_help_heading`
- [x] `next_display_order`, this one uses `Option` currently
- [ ] `replace`, this one uses `IntoIterator`, maybe passing `Vec::new()` would be the same behavior
- [x] `short_flag`
- [x] `long_flag`
- [ ] `aliases`, `IntoIterator` 
- [ ] `short_flag_aliases`, `IntoIterator` 
- [ ] `long_flag_aliases`, `IntoIterator` 
- [ ] `visible_aliases`, `IntoIterator` 
- [ ] `visible_short_flag_aliases`, `IntoIterator` 
- [ ] `visible_long_flag_aliases`, `IntoIterator` 
- [x] `display_order`, default is 999, possible to set manually
- [ ] `external_subcommand_value_parser`
- [x] `subcommand_value_name`
- [x] `subcommand_help_heading`

Theoretically the `bool` switches also, though not necessary, as long as the default is known they can be manually reset.



Discussion / hints:
I feel like `name` should not be resettable as it would have dramatically different semantics than any other resettable
> I feel like `name` should not be resettable as it would have dramatically different semantics than any other resettable

yes that's why I put it seperately, I agree that only values that can be optionally set should be unsettable
I completed the list for `Command`
> Application-wide Settings
>
> term_width
> max_term_width
> Also what is the actual difference in behavior, I feel the documentation is lacking

If you leave `term_width` at default (or reset it), clap will see how wide your terminal is and then cap that by `max_term_width`.

I had to look at the code to make sense of it.


I'm looking at update the docs but I feel like there is a typography / CSS term of phrase that would apply here to help clarify it but I can't think of what it would be
#4212 for `max_term_width` documentation
I think I'll skip any of the iterables for now.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b792fc13919..894b1ea5cb2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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)
@@ -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)
diff --git a/src/builder/arg.rs b/src/builder/arg.rs
index 136f2f21f1a..4f42926c72d 100644
--- a/src/builder/arg.rs
+++ b/src/builder/arg.rs
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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.
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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]
@@ -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.
@@ -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)
     }
 }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
@@ -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
     }
 
diff --git a/src/builder/arg_group.rs b/src/builder/arg_group.rs
index 9f97f24e57b..9cb5450c377 100644
--- a/src/builder/arg_group.rs
+++ b/src/builder/arg_group.rs
@@ -1,4 +1,5 @@
 // Internal
+use crate::builder::IntoResettable;
 use crate::util::Id;
 
 /// Family of related [arguments].
@@ -148,8 +149,12 @@ impl ArgGroup {
     /// ```
     /// [argument]: crate::Arg
     #[must_use]
-    pub fn arg(mut self, arg_id: impl Into<Id>) -> Self {
-        self.args.push(arg_id.into());
+    pub fn arg(mut self, arg_id: impl IntoResettable<Id>) -> Self {
+        if let Some(arg_id) = arg_id.into_resettable().into_option() {
+            self.args.push(arg_id);
+        } else {
+            self.args.clear();
+        }
         self
     }
 
@@ -314,8 +319,12 @@ impl ArgGroup {
     /// [required group]: ArgGroup::required()
     /// [argument requirement rules]: crate::Arg::requires()
     #[must_use]
-    pub fn requires(mut self, id: impl Into<Id>) -> Self {
-        self.requires.push(id.into());
+    pub fn requires(mut self, id: impl IntoResettable<Id>) -> Self {
+        if let Some(id) = id.into_resettable().into_option() {
+            self.requires.push(id);
+        } else {
+            self.requires.clear();
+        }
         self
     }
 
@@ -397,8 +406,12 @@ impl ArgGroup {
     /// ```
     /// [argument exclusion rules]: crate::Arg::conflicts_with()
     #[must_use]
-    pub fn conflicts_with(mut self, id: impl Into<Id>) -> Self {
-        self.conflicts.push(id.into());
+    pub fn conflicts_with(mut self, id: impl IntoResettable<Id>) -> Self {
+        if let Some(id) = id.into_resettable().into_option() {
+            self.conflicts.push(id);
+        } else {
+            self.conflicts.clear();
+        }
         self
     }
 
diff --git a/src/builder/command.rs b/src/builder/command.rs
index 58c8c9e2c25..e842ffb8295 100644
--- a/src/builder/command.rs
+++ b/src/builder/command.rs
@@ -1375,8 +1375,8 @@ impl Command {
     /// # ;
     /// ```
     #[must_use]
-    pub fn bin_name(mut self, name: impl Into<Str>) -> Self {
-        self.bin_name = Some(name.into());
+    pub fn bin_name(mut self, name: impl IntoResettable<Str>) -> Self {
+        self.bin_name = name.into_resettable().into_option();
         self
     }
 
@@ -1391,8 +1391,8 @@ impl Command {
     /// # ;
     /// ```
     #[must_use]
-    pub fn display_name(mut self, name: impl Into<Str>) -> Self {
-        self.display_name = Some(name.into());
+    pub fn display_name(mut self, name: impl IntoResettable<Str>) -> Self {
+        self.display_name = name.into_resettable().into_option();
         self
     }
 
@@ -1412,8 +1412,8 @@ impl Command {
     /// ```
     /// [`crate_authors!`]: ./macro.crate_authors!.html
     #[must_use]
-    pub fn author(mut self, author: impl Into<Str>) -> Self {
-        self.author = Some(author.into());
+    pub fn author(mut self, author: impl IntoResettable<Str>) -> Self {
+        self.author = author.into_resettable().into_option();
         self
     }
 
@@ -1482,8 +1482,8 @@ impl Command {
     /// ```
     ///
     #[must_use]
-    pub fn after_help(mut self, help: impl Into<StyledStr>) -> Self {
-        self.after_help = Some(help.into());
+    pub fn after_help(mut self, help: impl IntoResettable<StyledStr>) -> Self {
+        self.after_help = help.into_resettable().into_option();
         self
     }
 
@@ -1504,8 +1504,8 @@ impl Command {
     /// # ;
     /// ```
     #[must_use]
-    pub fn after_long_help(mut self, help: impl Into<StyledStr>) -> Self {
-        self.after_long_help = Some(help.into());
+    pub fn after_long_help(mut self, help: impl IntoResettable<StyledStr>) -> Self {
+        self.after_long_help = help.into_resettable().into_option();
         self
     }
 
@@ -1524,8 +1524,8 @@ impl Command {
     /// # ;
     /// ```
     #[must_use]
-    pub fn before_help(mut self, help: impl Into<StyledStr>) -> Self {
-        self.before_help = Some(help.into());
+    pub fn before_help(mut self, help: impl IntoResettable<StyledStr>) -> Self {
+        self.before_help = help.into_resettable().into_option();
         self
     }
 
@@ -1544,8 +1544,8 @@ impl Command {
     /// # ;
     /// ```
     #[must_use]
-    pub fn before_long_help(mut self, help: impl Into<StyledStr>) -> Self {
-        self.before_long_help = Some(help.into());
+    pub fn before_long_help(mut self, help: impl IntoResettable<StyledStr>) -> Self {
+        self.before_long_help = help.into_resettable().into_option();
         self
     }
 
@@ -1567,8 +1567,8 @@ impl Command {
     /// ```
     /// [`crate_version!`]: ./macro.crate_version!.html
     #[must_use]
-    pub fn version(mut self, ver: impl Into<Str>) -> Self {
-        self.version = Some(ver.into());
+    pub fn version(mut self, ver: impl IntoResettable<Str>) -> Self {
+        self.version = ver.into_resettable().into_option();
         self
     }
 
@@ -1595,8 +1595,8 @@ impl Command {
     /// ```
     /// [`crate_version!`]: ./macro.crate_version!.html
     #[must_use]
-    pub fn long_version(mut self, ver: impl Into<Str>) -> Self {
-        self.long_version = Some(ver.into());
+    pub fn long_version(mut self, ver: impl IntoResettable<Str>) -> Self {
+        self.long_version = ver.into_resettable().into_option();
         self
     }
 
@@ -1638,8 +1638,8 @@ impl Command {
     ///
     /// [`ArgMatches::usage`]: ArgMatches::usage()
     #[must_use]
-    pub fn override_usage(mut self, usage: impl Into<StyledStr>) -> Self {
-        self.usage_str = Some(usage.into());
+    pub fn override_usage(mut self, usage: impl IntoResettable<StyledStr>) -> Self {
+        self.usage_str = usage.into_resettable().into_option();
         self
     }
 
@@ -1675,8 +1675,8 @@ impl Command {
     /// # ;
     /// ```
     #[must_use]
-    pub fn override_help(mut self, help: impl Into<StyledStr>) -> Self {
-        self.help_str = Some(help.into());
+    pub fn override_help(mut self, help: impl IntoResettable<StyledStr>) -> Self {
+        self.help_str = help.into_resettable().into_option();
         self
     }
 
@@ -1726,8 +1726,8 @@ impl Command {
     /// [`Command::before_help`]: Command::before_help()
     /// [`Command::before_long_help`]: Command::before_long_help()
     #[must_use]
-    pub fn help_template(mut self, s: impl Into<StyledStr>) -> Self {
-        self.template = Some(s.into());
+    pub fn help_template(mut self, s: impl IntoResettable<StyledStr>) -> Self {
+        self.template = s.into_resettable().into_option();
         self
     }
 
@@ -1790,8 +1790,8 @@ impl Command {
     /// This will be used for any arg that hasn't had [`Arg::display_order`] called.
     #[inline]
     #[must_use]
-    pub fn next_display_order(mut self, disp_ord: impl Into<Option<usize>>) -> Self {
-        self.current_disp_ord = disp_ord.into();
+    pub fn next_display_order(mut self, disp_ord: impl IntoResettable<usize>) -> Self {
+        self.current_disp_ord = disp_ord.into_resettable().into_option();
         self
     }
 
@@ -2122,8 +2122,8 @@ impl Command {
     /// ```
     /// [`Arg::short`]: Arg::short()
     #[must_use]
-    pub fn short_flag(mut self, short: char) -> Self {
-        self.short_flag = Some(short);
+    pub fn short_flag(mut self, short: impl IntoResettable<char>) -> Self {
+        self.short_flag = short.into_resettable().into_option();
         self
     }
 
@@ -2191,8 +2191,12 @@ impl Command {
     /// ```
     /// [`Command::visible_alias`]: Command::visible_alias()
     #[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
     }
 
@@ -2213,9 +2217,13 @@ impl Command {
     /// assert_eq!(m.subcommand_name(), Some("test"));
     /// ```
     #[must_use]
-    pub fn short_flag_alias(mut self, name: char) -> Self {
-        assert!(name != '-', "short alias name cannot be `-`");
-        self.short_flag_aliases.push((name, false));
+    pub fn short_flag_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_flag_aliases.push((name, false));
+        } else {
+            self.short_flag_aliases.clear();
+        }
         self
     }
 
@@ -2236,8 +2244,12 @@ impl Command {
     /// assert_eq!(m.subcommand_name(), Some("test"));
     /// ```
     #[must_use]
-    pub fn long_flag_alias(mut self, name: impl Into<Str>) -> Self {
-        self.long_flag_aliases.push((name.into(), false));
+    pub fn long_flag_alias(mut self, name: impl IntoResettable<Str>) -> Self {
+        if let Some(name) = name.into_resettable().into_option() {
+            self.long_flag_aliases.push((name, false));
+        } else {
+            self.long_flag_aliases.clear();
+        }
         self
     }
 
@@ -2359,8 +2371,12 @@ impl Command {
     /// ```
     /// [`Command::alias`]: Command::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
     }
 
@@ -2384,9 +2400,13 @@ impl Command {
     /// ```
     /// [`Command::short_flag_alias`]: Command::short_flag_alias()
     #[must_use]
-    pub fn visible_short_flag_alias(mut self, name: char) -> Self {
-        assert!(name != '-', "short alias name cannot be `-`");
-        self.short_flag_aliases.push((name, true));
+    pub fn visible_short_flag_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_flag_aliases.push((name, true));
+        } else {
+            self.short_flag_aliases.clear();
+        }
         self
     }
 
@@ -2410,8 +2430,12 @@ impl Command {
     /// ```
     /// [`Command::long_flag_alias`]: Command::long_flag_alias()
     #[must_use]
-    pub fn visible_long_flag_alias(mut self, name: impl Into<Str>) -> Self {
-        self.long_flag_aliases.push((name.into(), true));
+    pub fn visible_long_flag_alias(mut self, name: impl IntoResettable<Str>) -> Self {
+        if let Some(name) = name.into_resettable().into_option() {
+            self.long_flag_aliases.push((name, true));
+        } else {
+            self.long_flag_aliases.clear();
+        }
         self
     }
 
@@ -2548,8 +2572,8 @@ impl Command {
     /// ```
     #[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
     }
 
@@ -2707,9 +2731,9 @@ impl Command {
     /// [`subcommands`]: crate::Command::subcommand()
     pub fn external_subcommand_value_parser(
         mut self,
-        parser: impl Into<super::ValueParser>,
+        parser: impl IntoResettable<super::ValueParser>,
     ) -> Self {
-        self.external_value_parser = Some(parser.into());
+        self.external_value_parser = parser.into_resettable().into_option();
         self
     }
 
@@ -3041,8 +3065,8 @@ impl Command {
     ///     -V, --version    Print version information
     /// ```
     #[must_use]
-    pub fn subcommand_value_name(mut self, value_name: impl Into<Str>) -> Self {
-        self.subcommand_value_name = Some(value_name.into());
+    pub fn subcommand_value_name(mut self, value_name: impl IntoResettable<Str>) -> Self {
+        self.subcommand_value_name = value_name.into_resettable().into_option();
         self
     }
 
@@ -3105,8 +3129,8 @@ impl Command {
     ///     -V, --version    Print version information
     /// ```
     #[must_use]
-    pub fn subcommand_help_heading(mut self, heading: impl Into<Str>) -> Self {
-        self.subcommand_heading = Some(heading.into());
+    pub fn subcommand_help_heading(mut self, heading: impl IntoResettable<Str>) -> Self {
+        self.subcommand_heading = heading.into_resettable().into_option();
         self
     }
 }
diff --git a/src/builder/possible_value.rs b/src/builder/possible_value.rs
index 93f012e89d4..5fbca9f9ed4 100644
--- a/src/builder/possible_value.rs
+++ b/src/builder/possible_value.rs
@@ -1,5 +1,6 @@
 use std::{borrow::Cow, iter};
 
+use crate::builder::IntoResettable;
 use crate::builder::Str;
 use crate::builder::StyledStr;
 use crate::util::eq_ignore_case;
@@ -76,8 +77,8 @@ impl PossibleValue {
     /// ```
     #[inline]
     #[must_use]
-    pub fn help(mut self, help: impl Into<StyledStr>) -> Self {
-        self.help = Some(help.into());
+    pub fn help(mut self, help: impl IntoResettable<StyledStr>) -> Self {
+        self.help = help.into_resettable().into_option();
         self
     }
 
@@ -113,8 +114,12 @@ impl PossibleValue {
     /// # ;
     /// ```
     #[must_use]
-    pub fn alias(mut self, name: impl Into<Str>) -> Self {
-        self.aliases.push(name.into());
+    pub fn alias(mut self, name: impl IntoResettable<Str>) -> Self {
+        if let Some(name) = name.into_resettable().into_option() {
+            self.aliases.push(name);
+        } else {
+            self.aliases.clear();
+        }
         self
     }
 
diff --git a/src/builder/resettable.rs b/src/builder/resettable.rs
index 158ff059407..9b20b602ef1 100644
--- a/src/builder/resettable.rs
+++ b/src/builder/resettable.rs
@@ -1,9 +1,13 @@
 // Unlike `impl Into<Option<T>>` or `Option<impl Into<T>>`, this isn't ambiguous for the `None`
 // case.
 
+use crate::builder::ArgAction;
 use crate::builder::OsStr;
 use crate::builder::Str;
 use crate::builder::StyledStr;
+use crate::builder::ValueHint;
+use crate::builder::ValueParser;
+use crate::builder::ValueRange;
 
 /// Clearable builder value
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -44,6 +48,51 @@ pub trait IntoResettable<T> {
     fn into_resettable(self) -> Resettable<T>;
 }
 
+impl IntoResettable<char> for Option<char> {
+    fn into_resettable(self) -> Resettable<char> {
+        match self {
+            Some(s) => Resettable::Value(s),
+            None => Resettable::Reset,
+        }
+    }
+}
+
+impl IntoResettable<usize> for Option<usize> {
+    fn into_resettable(self) -> Resettable<usize> {
+        match self {
+            Some(s) => Resettable::Value(s),
+            None => Resettable::Reset,
+        }
+    }
+}
+
+impl IntoResettable<ArgAction> for Option<ArgAction> {
+    fn into_resettable(self) -> Resettable<ArgAction> {
+        match self {
+            Some(s) => Resettable::Value(s),
+            None => Resettable::Reset,
+        }
+    }
+}
+
+impl IntoResettable<ValueHint> for Option<ValueHint> {
+    fn into_resettable(self) -> Resettable<ValueHint> {
+        match self {
+            Some(s) => Resettable::Value(s),
+            None => Resettable::Reset,
+        }
+    }
+}
+
+impl IntoResettable<ValueParser> for Option<ValueParser> {
+    fn into_resettable(self) -> Resettable<ValueParser> {
+        match self {
+            Some(s) => Resettable::Value(s),
+            None => Resettable::Reset,
+        }
+    }
+}
+
 impl IntoResettable<StyledStr> for Option<&'static str> {
     fn into_resettable(self) -> Resettable<StyledStr> {
         match self {
@@ -77,6 +126,42 @@ impl<T> IntoResettable<T> for Resettable<T> {
     }
 }
 
+impl IntoResettable<char> for char {
+    fn into_resettable(self) -> Resettable<char> {
+        Resettable::Value(self)
+    }
+}
+
+impl IntoResettable<usize> for usize {
+    fn into_resettable(self) -> Resettable<usize> {
+        Resettable::Value(self)
+    }
+}
+
+impl IntoResettable<ArgAction> for ArgAction {
+    fn into_resettable(self) -> Resettable<ArgAction> {
+        Resettable::Value(self)
+    }
+}
+
+impl IntoResettable<ValueHint> for ValueHint {
+    fn into_resettable(self) -> Resettable<ValueHint> {
+        Resettable::Value(self)
+    }
+}
+
+impl<I: Into<ValueRange>> IntoResettable<ValueRange> for I {
+    fn into_resettable(self) -> Resettable<ValueRange> {
+        Resettable::Value(self.into())
+    }
+}
+
+impl<I: Into<ValueParser>> IntoResettable<ValueParser> for I {
+    fn into_resettable(self) -> Resettable<ValueParser> {
+        Resettable::Value(self.into())
+    }
+}
+
 impl<I: Into<StyledStr>> IntoResettable<StyledStr> for I {
     fn into_resettable(self) -> Resettable<StyledStr> {
         Resettable::Value(self.into())


Test patch:
diff --git a/tests/builder/env.rs b/tests/builder/env.rs
index 99c2f6261ab..e3f5ad9bc03 100644
--- a/tests/builder/env.rs
+++ b/tests/builder/env.rs
@@ -69,7 +69,7 @@ fn env_os() {
     let r = Command::new("df")
         .arg(
             arg!([arg] "some opt")
-                .env_os(OsStr::new("CLP_TEST_ENV_OS"))
+                .env(OsStr::new("CLP_TEST_ENV_OS"))
                 .action(ArgAction::Set),
         )
         .try_get_matches_from(vec![""]);