pub trait TypedValueParser: Clone + Send + Sync + 'static {
    type Value: Send + Sync + Clone;

    // Required method
    fn parse_ref(
        &self,
        cmd: &Command,
        arg: Option<&Arg>,
        value: &OsStr
    ) -> Result<Self::Value, Error>;

    // Provided methods
    fn parse_ref_(
        &self,
        cmd: &Command,
        arg: Option<&Arg>,
        value: &OsStr,
        _source: ValueSource
    ) -> Result<Self::Value, Error> { ... }
    fn parse(
        &self,
        cmd: &Command,
        arg: Option<&Arg>,
        value: OsString
    ) -> Result<Self::Value, Error> { ... }
    fn parse_(
        &self,
        cmd: &Command,
        arg: Option<&Arg>,
        value: OsString,
        _source: ValueSource
    ) -> Result<Self::Value, Error> { ... }
    fn possible_values(
        &self
    ) -> Option<Box<dyn Iterator<Item = PossibleValue> + '_>> { ... }
    fn map<T, F>(self, func: F) -> MapValueParser<Self, F>
       where T: Send + Sync + Clone,
             F: Fn(Self::Value) -> T + Clone { ... }
    fn try_map<T, E, F>(self, func: F) -> TryMapValueParser<Self, F>
       where F: Fn(Self::Value) -> Result<T, E> + Clone + Send + Sync + 'static,
             T: Send + Sync + Clone,
             E: Into<Box<dyn Error + Sync + Send>> { ... }
}
Expand description

Parse/validate argument values

As alternatives to implementing TypedValueParser,

See ValueParserFactory to register TypedValueParser::Value with value_parser!.

§Example

#[derive(Clone)]
struct Custom(u32);

#[derive(Clone)]
struct CustomValueParser;

impl clap::builder::TypedValueParser for CustomValueParser {
    type Value = Custom;

    fn parse_ref(
        &self,
        cmd: &clap::Command,
        arg: Option<&clap::Arg>,
        value: &std::ffi::OsStr,
    ) -> Result<Self::Value, clap::Error> {
        let inner = clap::value_parser!(u32);
        let val = inner.parse_ref(cmd, arg, value)?;

        const INVALID_VALUE: u32 = 10;
        if val == INVALID_VALUE {
            let mut err = clap::Error::new(ErrorKind::ValueValidation)
                .with_cmd(cmd);
            if let Some(arg) = arg {
                err.insert(ContextKind::InvalidArg, ContextValue::String(arg.to_string()));
            }
            err.insert(ContextKind::InvalidValue, ContextValue::String(INVALID_VALUE.to_string()));
            return Err(err);
        }

        Ok(Custom(val))
    }
}

Required Associated Types§

source

type Value: Send + Sync + Clone

Argument’s value type

Required Methods§

source

fn parse_ref( &self, cmd: &Command, arg: Option<&Arg>, value: &OsStr ) -> Result<Self::Value, Error>

Parse the argument value

When arg is None, an external subcommand value is being parsed.

Provided Methods§

source

fn parse_ref_( &self, cmd: &Command, arg: Option<&Arg>, value: &OsStr, _source: ValueSource ) -> Result<Self::Value, Error>

Parse the argument value

When arg is None, an external subcommand value is being parsed.

source

fn parse( &self, cmd: &Command, arg: Option<&Arg>, value: OsString ) -> Result<Self::Value, Error>

Parse the argument value

When arg is None, an external subcommand value is being parsed.

source

fn parse_( &self, cmd: &Command, arg: Option<&Arg>, value: OsString, _source: ValueSource ) -> Result<Self::Value, Error>

Parse the argument value

When arg is None, an external subcommand value is being parsed.

source

fn possible_values( &self ) -> Option<Box<dyn Iterator<Item = PossibleValue> + '_>>

Reflect on enumerated value properties

Error checking should not be done with this; it is mostly targeted at user-facing applications like errors and completion.

source

fn map<T, F>(self, func: F) -> MapValueParser<Self, F>
where T: Send + Sync + Clone, F: Fn(Self::Value) -> T + Clone,

Adapt a TypedValueParser from one value to another

§Example
let cmd = Command::new("mycmd")
    .arg(
        Arg::new("flag")
            .long("flag")
            .action(clap::ArgAction::SetTrue)
            .value_parser(
                BoolishValueParser::new()
                .map(|b| -> usize {
                    if b { 10 } else { 5 }
                })
            )
    );

let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap();
assert!(matches.contains_id("flag"));
assert_eq!(
    matches.get_one::<usize>("flag").copied(),
    Some(10)
);

let matches = cmd.try_get_matches_from(["mycmd"]).unwrap();
assert!(matches.contains_id("flag"));
assert_eq!(
    matches.get_one::<usize>("flag").copied(),
    Some(5)
);
source

fn try_map<T, E, F>(self, func: F) -> TryMapValueParser<Self, F>
where F: Fn(Self::Value) -> Result<T, E> + Clone + Send + Sync + 'static, T: Send + Sync + Clone, E: Into<Box<dyn Error + Sync + Send>>,

Adapt a TypedValueParser from one value to another

§Example
let cmd = Command::new("mycmd")
    .arg(
        Arg::new("flag")
            .long("flag")
            .value_parser(
                OsStringValueParser::new()
                .try_map(verify_ext)
            )
    );

fn verify_ext(os: OsString) -> Result<PathBuf, &'static str> {
    let path = PathBuf::from(os);
    if path.extension() != Some(OsStr::new("rs")) {
        return Err("only Rust files are supported");
    }
    Ok(path)
}

let error = cmd.clone().try_get_matches_from(["mycmd", "--flag", "foo.txt"]).unwrap_err();
error.print();

let matches = cmd.try_get_matches_from(["mycmd", "--flag", "foo.rs"]).unwrap();
assert!(matches.contains_id("flag"));
assert_eq!(
    matches.get_one::<PathBuf>("flag").map(|s| s.as_path()),
    Some(Path::new("foo.rs"))
);

Object Safety§

This trait is not object safe.

Implementors§

source§

impl TypedValueParser for BoolValueParser

§

type Value = bool

source§

impl TypedValueParser for BoolishValueParser

§

type Value = bool

source§

impl TypedValueParser for FalseyValueParser

§

type Value = bool

source§

impl TypedValueParser for NonEmptyStringValueParser

source§

impl TypedValueParser for OsStringValueParser

source§

impl TypedValueParser for PathBufValueParser

source§

impl TypedValueParser for PossibleValuesParser

source§

impl TypedValueParser for StringValueParser

source§

impl TypedValueParser for UnknownArgumentValueParser

source§

impl<E> TypedValueParser for EnumValueParser<E>
where E: ValueEnum + Clone + Send + Sync + 'static,

§

type Value = E

source§

impl<F, T, E> TypedValueParser for F
where F: Fn(&str) -> Result<T, E> + Clone + Send + Sync + 'static, E: Into<Box<dyn Error + Sync + Send>>, T: Send + Sync + Clone,

§

type Value = T

source§

impl<P, F, T> TypedValueParser for MapValueParser<P, F>
where P: TypedValueParser, <P as TypedValueParser>::Value: Send + Sync + Clone, F: Fn(<P as TypedValueParser>::Value) -> T + Clone + Send + Sync + 'static, T: Send + Sync + Clone,

§

type Value = T

source§

impl<P, F, T, E> TypedValueParser for TryMapValueParser<P, F>
where P: TypedValueParser, <P as TypedValueParser>::Value: Send + Sync + Clone, F: Fn(<P as TypedValueParser>::Value) -> Result<T, E> + Clone + Send + Sync + 'static, T: Send + Sync + Clone, E: Into<Box<dyn Error + Sync + Send>>,

§

type Value = T

source§

impl<T> TypedValueParser for RangedI64ValueParser<T>
where T: TryFrom<i64> + Clone + Send + Sync + 'static, <T as TryFrom<i64>>::Error: Send + Sync + 'static + Error + ToString,

§

type Value = T

source§

impl<T> TypedValueParser for RangedU64ValueParser<T>
where T: TryFrom<u64> + Clone + Send + Sync + 'static, <T as TryFrom<u64>>::Error: Send + Sync + 'static + Error + ToString,

§

type Value = T