Skip to content

Commit

Permalink
fix: Allow non-bool value_parsers for SetTrue
Browse files Browse the repository at this point in the history
Not sure if we could have originally made this work but it definitely
does now that we use `default_missing_value` for this (clap-rs#4000)
  • Loading branch information
epage committed Aug 19, 2022
1 parent 5950c4b commit 09354de
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -70,6 +70,7 @@ MSRV is now 1.60.0
- `Arg::default_missing_value` now applies per occurrence rather than if a value is missing across all occurrences
- `arg!(--long [value])` to accept `0..=1` per occurrence rather than across all occurrences, making it safe to use with `ArgAction::Append`
- Allow `OsStr`s for `Arg::{required_if_eq,required_if_eq_any,required_if_eq_all}`
- Allow non-bool `value_parser`s for `ArgAction::SetTrue` / `ArgAction::SetFalse`
- *(assert)* Always enforce that version is specified when the `ArgAction::Version` is used
- *(assert)* Add missing `#[track_caller]`s to make it easier to debug asserts
- *(assert)* Ensure `overrides_with` IDs are valid
Expand Down
4 changes: 2 additions & 2 deletions src/builder/action.rs
Expand Up @@ -283,8 +283,8 @@ impl ArgAction {
match self {
Self::Set => None,
Self::Append => None,
Self::SetTrue => Some(AnyValueId::of::<bool>()),
Self::SetFalse => Some(AnyValueId::of::<bool>()),
Self::SetTrue => None,
Self::SetFalse => None,
Self::Count => Some(AnyValueId::of::<CountType>()),
Self::Help => None,
Self::Version => None,
Expand Down
34 changes: 34 additions & 0 deletions tests/derive/flags.rs
Expand Up @@ -12,6 +12,7 @@
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

use clap::ArgAction;
use clap::CommandFactory;
use clap::Parser;

Expand Down Expand Up @@ -43,6 +44,39 @@ fn bool_type_is_flag() {
assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
}

#[test]
fn non_bool_type_flag() {
fn parse_from_flag(b: &str) -> Result<usize, String> {
b.parse::<bool>()
.map(|b| if b { 10 } else { 5 })
.map_err(|e| e.to_string())
}

#[derive(Parser, Debug)]
struct Opt {
#[clap(short, long, action = ArgAction::SetTrue, value_parser = parse_from_flag)]
alice: usize,
#[clap(short, long, action = ArgAction::SetTrue, value_parser = parse_from_flag)]
bob: usize,
}

let opt = Opt::try_parse_from(&["test"]).unwrap();
assert_eq!(opt.alice, 5);
assert_eq!(opt.bob, 5);

let opt = Opt::try_parse_from(&["test", "-a"]).unwrap();
assert_eq!(opt.alice, 10);
assert_eq!(opt.bob, 5);

let opt = Opt::try_parse_from(&["test", "-b"]).unwrap();
assert_eq!(opt.alice, 5);
assert_eq!(opt.bob, 10);

let opt = Opt::try_parse_from(&["test", "-b", "-a"]).unwrap();
assert_eq!(opt.alice, 10);
assert_eq!(opt.bob, 10);
}

#[test]
#[ignore] // Not a good path for supporting this atm
fn inferred_help() {
Expand Down

0 comments on commit 09354de

Please sign in to comment.