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<RichFormatter>>;

    // Provided methods
    fn parse(
        &self,
        cmd: &Command,
        arg: Option<&Arg>,
        value: OsString
    ) -> Result<Self::Value, Error<RichFormatter>> { ... }
    fn possible_values(
        &self
    ) -> Option<Box<dyn Iterator<Item = PossibleValue>, Global>> { ... }
    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 + Send + Sync + 'static, Global>> { ... }
}
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<RichFormatter>>

Parse the argument value

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

Provided Methods§

source

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

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>, Global>>

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 + Send + Sync + 'static, Global>>,

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"))
);

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<E> TypedValueParser for EnumValueParser<E>where E: ValueEnum + Clone + Send + Sync + 'static,

§

type Value = E

source§

impl<F, T, E> TypedValueParser for Fwhere F: Fn(&str) -> Result<T, E> + Clone + Send + Sync + 'static, E: Into<Box<dyn Error + Send + Sync + 'static, Global>>, 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<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