Repository: clap-rs/clap
Pull request #4659 (2023-01-23 15:24:07)

docs: Prefer `get_flag` over `get_one::<bool>`
Inspired by #4654

<!--
Thanks for helping out!

Please link the appropriate issue from your PR.

If you don't have an issue, we'd recommend starting with one first so the PR can focus on the
implementation (unless its an obvious bug or documentation fix that will have
little conversation).
-->



Patch:
diff --git a/examples/tutorial_builder/01_quick.rs b/examples/tutorial_builder/01_quick.rs
index 7e53fc65..8126e335 100644
--- a/examples/tutorial_builder/01_quick.rs
+++ b/examples/tutorial_builder/01_quick.rs
@@ -48,7 +48,7 @@ fn main() {
     // matches just as you would the top level cmd
     if let Some(matches) = matches.subcommand_matches("test") {
         // "$ myapp test" was run
-        if *matches.get_one::<bool>("list").expect("defaulted by clap") {
+        if matches.get_flag("list") {
             // "$ myapp test -l" was run
             println!("Printing testing lists...");
         } else {
diff --git a/src/builder/action.rs b/src/builder/action.rs
index 01d1f07b..9739f880 100644
--- a/src/builder/action.rs
+++ b/src/builder/action.rs
@@ -99,15 +99,15 @@ pub enum ArgAction {
     /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap();
     /// assert!(matches.contains_id("flag"));
     /// assert_eq!(
-    ///     matches.get_one::<bool>("flag").copied(),
-    ///     Some(true)
+    ///     matches.get_flag("flag"),
+    ///     true
     /// );
     ///
     /// let matches = cmd.try_get_matches_from(["mycmd"]).unwrap();
     /// assert!(matches.contains_id("flag"));
     /// assert_eq!(
-    ///     matches.get_one::<bool>("flag").copied(),
-    ///     Some(false)
+    ///     matches.get_flag("flag"),
+    ///     false
     /// );
     /// ```
     ///
@@ -172,15 +172,15 @@ pub enum ArgAction {
     /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap();
     /// assert!(matches.contains_id("flag"));
     /// assert_eq!(
-    ///     matches.get_one::<bool>("flag").copied(),
-    ///     Some(false)
+    ///     matches.get_flag("flag"),
+    ///     false
     /// );
     ///
     /// let matches = cmd.try_get_matches_from(["mycmd"]).unwrap();
     /// assert!(matches.contains_id("flag"));
     /// assert_eq!(
-    ///     matches.get_one::<bool>("flag").copied(),
-    ///     Some(true)
+    ///     matches.get_flag("flag"),
+    ///     true
     /// );
     /// ```
     SetFalse,
diff --git a/src/builder/arg.rs b/src/builder/arg.rs
index bea0807f..ca2d6acb 100644
--- a/src/builder/arg.rs
+++ b/src/builder/arg.rs
@@ -286,7 +286,7 @@ impl Arg {
     ///             .get_matches_from(vec![
     ///                 "prog", "--do-tests"
     ///             ]);
-    /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
+    /// assert_eq!(m.get_flag("test"), true);
     /// ```
     #[must_use]
     pub fn aliases(mut self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self {
@@ -314,7 +314,7 @@ impl Arg {
     ///             .get_matches_from(vec![
     ///                 "prog", "-s"
     ///             ]);
-    /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
+    /// assert_eq!(m.get_flag("test"), true);
     /// ```
     #[must_use]
     pub fn short_aliases(mut self, names: impl IntoIterator<Item = char>) -> Self {
@@ -399,7 +399,7 @@ impl Arg {
     ///        .get_matches_from(vec![
     ///             "prog", "--awesome"
     ///         ]);
-    /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
+    /// assert_eq!(m.get_flag("test"), true);
     /// ```
     /// [`Command::aliases`]: Arg::aliases()
     #[must_use]
@@ -425,7 +425,7 @@ impl Arg {
     ///        .get_matches_from(vec![
     ///             "prog", "-t"
     ///         ]);
-    /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
+    /// assert_eq!(m.get_flag("test"), true);
     /// ```
     #[must_use]
     pub fn visible_short_aliases(mut self, names: impl IntoIterator<Item = char>) -> Self {
@@ -807,7 +807,7 @@ impl Arg {
     ///
     /// assert_eq!(m.subcommand_name(), Some("do-stuff"));
     /// let sub_m = m.subcommand_matches("do-stuff").unwrap();
-    /// assert_eq!(*sub_m.get_one::<bool>("verb").expect("defaulted by clap"), true);
+    /// assert_eq!(sub_m.get_flag("verb"), true);
     /// ```
     ///
     /// [`Subcommand`]: crate::Subcommand
@@ -1900,9 +1900,9 @@ impl Arg {
     ///         "prog"
     ///     ]);
     ///
-    /// assert!(*m.get_one::<bool>("true_flag").unwrap());
-    /// assert!(!*m.get_one::<bool>("false_flag").unwrap());
-    /// assert!(!*m.get_one::<bool>("absent_flag").unwrap());
+    /// assert!(m.get_flag("true_flag"));
+    /// assert!(!m.get_flag("false_flag"));
+    /// assert!(!m.get_flag("absent_flag"));
     /// ```
     ///
     /// In this example, we show the variable coming from an option on the CLI:
@@ -3639,10 +3639,10 @@ impl Arg {
     ///         "prog", "-f", "-d", "-c"]);
     ///             //    ^~~~~~~~~~~~^~~~~ flag is overridden by color
     ///
-    /// assert!(*m.get_one::<bool>("color").unwrap());
-    /// assert!(*m.get_one::<bool>("debug").unwrap()); // even though flag conflicts with debug, it's as if flag
+    /// assert!(m.get_flag("color"));
+    /// assert!(m.get_flag("debug")); // even though flag conflicts with debug, it's as if flag
     ///                                 // was never used because it was overridden with color
-    /// assert!(!*m.get_one::<bool>("flag").unwrap());
+    /// assert!(!m.get_flag("flag"));
     /// ```
     #[must_use]
     pub fn overrides_with(mut self, arg_id: impl IntoResettable<Id>) -> Self {
@@ -3678,11 +3678,11 @@ impl Arg {
     ///         "prog", "-f", "-d", "-c"]);
     ///             //    ^~~~~~^~~~~~~~~ flag and debug are overridden by color
     ///
-    /// assert!(*m.get_one::<bool>("color").unwrap()); // even though flag conflicts with color, it's as if flag
+    /// assert!(m.get_flag("color")); // even though flag conflicts with color, it's as if flag
     ///                                 // and debug were never used because they were overridden
     ///                                 // with color
-    /// assert!(!*m.get_one::<bool>("debug").unwrap());
-    /// assert!(!*m.get_one::<bool>("flag").unwrap());
+    /// assert!(!m.get_flag("debug"));
+    /// assert!(!m.get_flag("flag"));
     /// ```
     #[must_use]
     pub fn overrides_with_all(mut self, names: impl IntoIterator<Item = impl Into<Id>>) -> Self {
diff --git a/src/builder/command.rs b/src/builder/command.rs
index dd5ee5b3..4d307379 100644
--- a/src/builder/command.rs
+++ b/src/builder/command.rs
@@ -449,7 +449,7 @@ impl Command {
     ///
     /// fn main() {
     ///     let m = cmd().get_matches_from(vec!["foo", "-b"]);
-    ///     println!("{}", *m.get_one::<bool>("bar").expect("defaulted by clap"));
+    ///     println!("{}", m.get_flag("bar"));
     /// }
     /// ```
     pub fn debug_assert(mut self) {
@@ -963,7 +963,7 @@ impl Command {
     /// assert!(r.is_ok(), "unexpected error: {:?}", r);
     /// let m = r.unwrap();
     /// assert_eq!(m.get_one::<String>("config").unwrap(), "file");
-    /// assert!(*m.get_one::<bool>("f").expect("defaulted"));
+    /// assert!(m.get_flag("f"));
     /// assert_eq!(m.get_one::<String>("stuff"), None);
     /// ```
     #[inline]
@@ -1760,7 +1760,7 @@ impl Command {
     ///   * `{options}`             - Help for options.
     ///   * `{positionals}`         - Help for positional arguments.
     ///   * `{subcommands}`         - Help for subcommands.
-    ///   * `{tab}`                 - Standard tab sized used within clap
+    ///   * `{tag}`                 - Standard tab sized used within clap
     ///   * `{after-help}`          - Help from [`Command::after_help`] or [`Command::after_long_help`].
     ///   * `{before-help}`         - Help from [`Command::before_help`] or [`Command::before_long_help`].
     ///
@@ -1943,8 +1943,8 @@ impl Command {
     ///     .replace("--save-all", &["--save-context", "--save-runtime"])
     ///     .get_matches_from(vec!["cmd", "--save-all"]);
     ///
-    /// assert!(*m.get_one::<bool>("save-context").expect("defaulted by clap"));
-    /// assert!(*m.get_one::<bool>("save-runtime").expect("defaulted by clap"));
+    /// assert!(m.get_flag("save-context"));
+    /// assert!(m.get_flag("save-runtime"));
     /// ```
     ///
     /// This can also be used with options, for example if our application with
@@ -1969,8 +1969,8 @@ impl Command {
     ///     .replace("--save-all", &["--save-context", "--save-runtime", "--format=json"])
     ///     .get_matches_from(vec!["cmd", "--save-all"]);
     ///
-    /// assert!(*m.get_one::<bool>("save-context").expect("defaulted by clap"));
-    /// assert!(*m.get_one::<bool>("save-runtime").expect("defaulted by clap"));
+    /// assert!(m.get_flag("save-context"));
+    /// assert!(m.get_flag("save-runtime"));
     /// assert_eq!(m.get_one::<String>("format").unwrap(), "json");
     /// ```
     ///
@@ -2191,7 +2191,7 @@ impl Command {
     ///
     /// assert_eq!(matches.subcommand_name().unwrap(), "sync");
     /// let sync_matches = matches.subcommand_matches("sync").unwrap();
-    /// assert!(*sync_matches.get_one::<bool>("search").expect("defaulted by clap"));
+    /// assert!(sync_matches.get_flag("search"));
     /// ```
     /// [`Arg::short`]: Arg::short()
     #[must_use]
@@ -2228,7 +2228,7 @@ impl Command {
     ///
     /// assert_eq!(matches.subcommand_name().unwrap(), "sync");
     /// let sync_matches = matches.subcommand_matches("sync").unwrap();
-    /// assert!(*sync_matches.get_one::<bool>("search").expect("defaulted by clap"));
+    /// assert!(sync_matches.get_flag("search"));
     /// ```
     ///
     /// [`Arg::long`]: Arg::long()
diff --git a/src/derive.rs b/src/derive.rs
index a49379cc..a30f2da5 100644
--- a/src/derive.rs
+++ b/src/derive.rs
@@ -69,7 +69,7 @@ use std::ffi::OsString;
 /// impl From<ArgMatches> for Context {
 ///     fn from(m: ArgMatches) -> Self {
 ///         Context {
-///             verbose: *m.get_one::<bool>("verbose").expect("defaulted_by_clap"),
+///             verbose: m.get_flag("verbose"),
 ///             name: m.get_one::<String>("name").cloned(),
 ///         }
 ///     }
@@ -201,7 +201,7 @@ pub trait FromArgMatches: Sized {
     ///    fn from(m: ArgMatches) -> Self {
     ///        Context {
     ///            name: m.get_one::<String>("name").unwrap().clone(),
-    ///            debug: *m.get_one::<bool>("debug").expect("defaulted by clap"),
+    ///            debug: m.get_flag("debug"),
     ///        }
     ///    }
     /// }
@@ -235,7 +235,7 @@ pub trait FromArgMatches: Sized {
     ///    fn from(m: ArgMatches) -> Self {
     ///        Context {
     ///            name: m.get_one::<String>("name").unwrap().to_string(),
-    ///            debug: *m.get_one::<bool>("debug").expect("defaulted by clap"),
+    ///            debug: m.get_flag("debug"),
     ///        }
     ///    }
     /// }
diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs
index 9347e697..23f53c02 100644
--- a/src/parser/matches/arg_matches.rs
+++ b/src/parser/matches/arg_matches.rs
@@ -1005,7 +1005,7 @@ impl ArgMatches {
     ///     ]);
     ///
     /// // Both parent commands, and child subcommands can have arguments present at the same times
-    /// assert!(*app_m.get_one::<bool>("debug").expect("defaulted by clap"));
+    /// assert!(app_m.get_flag("debug"));
     ///
     /// // Get the subcommand's ArgMatches instance
     /// if let Some(sub_m) = app_m.subcommand_matches("test") {


Test patch:
diff --git a/tests/builder/action.rs b/tests/builder/action.rs
index 4c5bf810..b0a0abf2 100644
--- a/tests/builder/action.rs
+++ b/tests/builder/action.rs
@@ -84,7 +84,7 @@ fn set_true() {
         Command::new("test").arg(Arg::new("mammal").long("mammal").action(ArgAction::SetTrue));
 
     let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("mammal"), false);
     assert_eq!(matches.contains_id("mammal"), true);
     assert_eq!(matches.index_of("mammal"), Some(1));
 
@@ -92,7 +92,7 @@ fn set_true() {
         .clone()
         .try_get_matches_from(["test", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("mammal"), true);
     assert_eq!(matches.contains_id("mammal"), true);
     assert_eq!(matches.index_of("mammal"), Some(1));
 
@@ -107,7 +107,7 @@ fn set_true() {
         .args_override_self(true)
         .try_get_matches_from(["test", "--mammal", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("mammal"), true);
     assert_eq!(matches.contains_id("mammal"), true);
     assert_eq!(matches.index_of("mammal"), Some(2));
 }
@@ -125,12 +125,12 @@ fn set_true_with_explicit_default_value() {
         .clone()
         .try_get_matches_from(["test", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("mammal"), true);
     assert_eq!(matches.contains_id("mammal"), true);
     assert_eq!(matches.index_of("mammal"), Some(1));
 
     let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("mammal"), false);
     assert_eq!(matches.contains_id("mammal"), true);
     assert_eq!(matches.index_of("mammal"), Some(1));
 }
@@ -147,19 +147,19 @@ fn set_true_with_default_value_if_present() {
         .arg(Arg::new("dog").long("dog").action(ArgAction::SetTrue));
 
     let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("dog"), false);
+    assert_eq!(matches.get_flag("mammal"), false);
 
     let matches = cmd.clone().try_get_matches_from(["test", "--dog"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("dog"), true);
+    assert_eq!(matches.get_flag("mammal"), true);
 
     let matches = cmd
         .clone()
         .try_get_matches_from(["test", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("dog"), false);
+    assert_eq!(matches.get_flag("mammal"), true);
 }
 
 #[test]
@@ -174,19 +174,19 @@ fn set_true_with_default_value_if_value() {
         .arg(Arg::new("dog").long("dog").action(ArgAction::SetTrue));
 
     let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("dog"), false);
+    assert_eq!(matches.get_flag("mammal"), false);
 
     let matches = cmd.clone().try_get_matches_from(["test", "--dog"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("dog"), true);
+    assert_eq!(matches.get_flag("mammal"), true);
 
     let matches = cmd
         .clone()
         .try_get_matches_from(["test", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("dog"), false);
+    assert_eq!(matches.get_flag("mammal"), true);
 }
 
 #[test]
@@ -204,8 +204,8 @@ fn set_true_with_required_if_eq() {
         .clone()
         .try_get_matches_from(["test", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("dog"), false);
+    assert_eq!(matches.get_flag("mammal"), true);
 
     cmd.clone()
         .try_get_matches_from(["test", "--dog"])
@@ -215,8 +215,8 @@ fn set_true_with_required_if_eq() {
         .clone()
         .try_get_matches_from(["test", "--dog", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("dog"), true);
+    assert_eq!(matches.get_flag("mammal"), true);
 }
 
 #[test]
@@ -228,7 +228,7 @@ fn set_false() {
     );
 
     let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("mammal"), true);
     assert_eq!(matches.contains_id("mammal"), true);
     assert_eq!(matches.index_of("mammal"), Some(1));
 
@@ -236,7 +236,7 @@ fn set_false() {
         .clone()
         .try_get_matches_from(["test", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("mammal"), false);
     assert_eq!(matches.contains_id("mammal"), true);
     assert_eq!(matches.index_of("mammal"), Some(1));
 
@@ -251,7 +251,7 @@ fn set_false() {
         .args_override_self(true)
         .try_get_matches_from(["test", "--mammal", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("mammal"), false);
     assert_eq!(matches.contains_id("mammal"), true);
     assert_eq!(matches.index_of("mammal"), Some(2));
 }
@@ -269,12 +269,12 @@ fn set_false_with_explicit_default_value() {
         .clone()
         .try_get_matches_from(["test", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("mammal"), false);
     assert_eq!(matches.contains_id("mammal"), true);
     assert_eq!(matches.index_of("mammal"), Some(1));
 
     let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("mammal"), true);
     assert_eq!(matches.contains_id("mammal"), true);
     assert_eq!(matches.index_of("mammal"), Some(1));
 }
@@ -291,19 +291,19 @@ fn set_false_with_default_value_if_present() {
         .arg(Arg::new("dog").long("dog").action(ArgAction::SetFalse));
 
     let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("dog"), true);
+    assert_eq!(matches.get_flag("mammal"), true);
 
     let matches = cmd.clone().try_get_matches_from(["test", "--dog"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("dog"), false);
+    assert_eq!(matches.get_flag("mammal"), false);
 
     let matches = cmd
         .clone()
         .try_get_matches_from(["test", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("dog"), true);
+    assert_eq!(matches.get_flag("mammal"), false);
 }
 
 #[test]
@@ -318,19 +318,19 @@ fn set_false_with_default_value_if_value() {
         .arg(Arg::new("dog").long("dog").action(ArgAction::SetFalse));
 
     let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
+    assert_eq!(matches.get_flag("dog"), true);
+    assert_eq!(matches.get_flag("mammal"), true);
 
     let matches = cmd.clone().try_get_matches_from(["test", "--dog"]).unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("dog"), false);
+    assert_eq!(matches.get_flag("mammal"), false);
 
     let matches = cmd
         .clone()
         .try_get_matches_from(["test", "--mammal"])
         .unwrap();
-    assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
-    assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
+    assert_eq!(matches.get_flag("dog"), true);
+    assert_eq!(matches.get_flag("mammal"), false);
 }
 
 #[test]
diff --git a/tests/builder/multiple_values.rs b/tests/builder/multiple_values.rs
index 466d6b0c..5cbfee44 100644
--- a/tests/builder/multiple_values.rs
+++ b/tests/builder/multiple_values.rs
@@ -1311,7 +1311,7 @@ fn low_index_positional_with_extra_flags() {
     assert_eq!(m.get_one::<String>("output").unwrap(), "8");
     assert_eq!(m.get_one::<String>("one").unwrap(), "1");
     assert_eq!(m.get_one::<String>("two").unwrap(), "2");
-    assert!(!*m.get_one::<bool>("yes").unwrap());
+    assert!(!m.get_flag("yes"));
 }
 
 #[test]