mirror of
https://github.com/clap-rs/clap
synced 2025-03-04 23:37:32 +00:00
commit
3b2e3ffddf
13 changed files with 201 additions and 89 deletions
|
@ -4,13 +4,19 @@
|
|||
|
||||
use clap::{ArgEnum, Clap};
|
||||
|
||||
#[derive(ArgEnum, Debug, PartialEq)]
|
||||
#[derive(ArgEnum, Debug, PartialEq, Clone)]
|
||||
enum ArgChoice {
|
||||
/// Descriptions are supported as doc-comment
|
||||
Foo,
|
||||
// Renames are supported
|
||||
#[clap(name = "b-a-r")]
|
||||
Bar,
|
||||
// Aliases are supported
|
||||
#[clap(alias = "b", alias = "z")]
|
||||
Baz,
|
||||
// Hiding variants from help and completion is supported
|
||||
#[clap(hidden = true)]
|
||||
Hidden,
|
||||
}
|
||||
|
||||
#[derive(Clap, PartialEq, Debug)]
|
||||
|
|
|
@ -19,7 +19,7 @@ use std::ffi::OsString;
|
|||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(ArgEnum, Debug, PartialEq)]
|
||||
#[derive(ArgEnum, Debug, PartialEq, Clone)]
|
||||
enum GeneratorChoice {
|
||||
Bash,
|
||||
Elvish,
|
||||
|
|
|
@ -819,14 +819,6 @@ impl Attrs {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn enum_aliases(&self) -> Vec<TokenStream> {
|
||||
self.methods
|
||||
.iter()
|
||||
.filter(|m| m.name == "alias")
|
||||
.map(|m| m.args.clone())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn casing(&self) -> Sp<CasingStyle> {
|
||||
self.casing.clone()
|
||||
}
|
||||
|
|
|
@ -47,9 +47,8 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr
|
|||
);
|
||||
|
||||
let lits = lits(&e.variants, &attrs);
|
||||
let variants = gen_variants(&lits);
|
||||
let from_str = gen_from_str(&lits);
|
||||
let as_arg = gen_as_arg(&lits);
|
||||
let arg_values = gen_arg_values(&lits);
|
||||
let arg_value = gen_arg_value(&lits);
|
||||
|
||||
quote! {
|
||||
#[allow(dead_code, unreachable_code, unused_variables)]
|
||||
|
@ -65,9 +64,8 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr
|
|||
)]
|
||||
#[deny(clippy::correctness)]
|
||||
impl clap::ArgEnum for #name {
|
||||
#variants
|
||||
#from_str
|
||||
#as_arg
|
||||
#arg_values
|
||||
#arg_value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,54 +85,35 @@ fn lits(
|
|||
if let Kind::Skip(_) = &*attrs.kind() {
|
||||
None
|
||||
} else {
|
||||
Some((variant, attrs))
|
||||
let fields = attrs.field_methods();
|
||||
let name = attrs.cased_name();
|
||||
Some((
|
||||
quote! {
|
||||
clap::ArgValue::new(#name)
|
||||
#fields
|
||||
},
|
||||
variant.ident.clone(),
|
||||
))
|
||||
}
|
||||
})
|
||||
.flat_map(|(variant, attrs)| {
|
||||
let mut ret = vec![(attrs.cased_name(), variant.ident.clone())];
|
||||
|
||||
attrs
|
||||
.enum_aliases()
|
||||
.into_iter()
|
||||
.for_each(|x| ret.push((x, variant.ident.clone())));
|
||||
|
||||
ret
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn gen_variants(lits: &[(TokenStream, Ident)]) -> TokenStream {
|
||||
let lit = lits.iter().map(|l| &l.0).collect::<Vec<_>>();
|
||||
fn gen_arg_values(lits: &[(TokenStream, Ident)]) -> TokenStream {
|
||||
let lit = lits.iter().map(|l| &l.1).collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
const VARIANTS: &'static [&'static str] = &[#(#lit),*];
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_from_str(lits: &[(TokenStream, Ident)]) -> TokenStream {
|
||||
let (lit, variant): (Vec<TokenStream>, Vec<Ident>) = lits.iter().cloned().unzip();
|
||||
|
||||
quote! {
|
||||
fn from_str(input: &str, case_insensitive: bool) -> ::std::result::Result<Self, String> {
|
||||
let func = if case_insensitive {
|
||||
::std::ascii::AsciiExt::eq_ignore_ascii_case
|
||||
} else {
|
||||
str::eq
|
||||
};
|
||||
|
||||
match input {
|
||||
#(val if func(val, #lit) => Ok(Self::#variant),)*
|
||||
e => Err(format!("Invalid variant: {}", e)),
|
||||
}
|
||||
fn value_variants<'a>() -> &'a [Self]{
|
||||
&[#(Self::#lit),*]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_as_arg(lits: &[(TokenStream, Ident)]) -> TokenStream {
|
||||
fn gen_arg_value(lits: &[(TokenStream, Ident)]) -> TokenStream {
|
||||
let (lit, variant): (Vec<TokenStream>, Vec<Ident>) = lits.iter().cloned().unzip();
|
||||
|
||||
quote! {
|
||||
fn as_arg(&self) -> Option<&'static str> {
|
||||
fn arg_value<'a>(&self) -> Option<clap::ArgValue<'a>> {
|
||||
match self {
|
||||
#(Self::#variant => Some(#lit),)*
|
||||
_ => None
|
||||
|
|
|
@ -361,7 +361,7 @@ pub fn gen_augment(
|
|||
|
||||
fn gen_arg_enum_possible_values(ty: &Type) -> TokenStream {
|
||||
quote_spanned! { ty.span()=>
|
||||
.possible_values(<#ty as clap::ArgEnum>::VARIANTS.into_iter().copied())
|
||||
.possible_values(<#ty as clap::ArgEnum>::value_variants().iter().filter_map(clap::ArgEnum::arg_value))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,11 +76,13 @@ pub fn args(name: &Ident) {
|
|||
pub fn arg_enum(name: &Ident) {
|
||||
append_dummy(quote! {
|
||||
impl clap::ArgEnum for #name {
|
||||
const VARIANTS: &'static [&'static str] = &[];
|
||||
fn value_variants<'a>() -> &'a [Self]{
|
||||
unimplemented!()
|
||||
}
|
||||
fn from_str(_input: &str, _case_insensitive: bool) -> Result<Self, String> {
|
||||
unimplemented!()
|
||||
}
|
||||
fn as_arg(&self) -> Option<&'static str> {
|
||||
fn arg_value<'a>(&self) -> Option<clap::ArgValue<'a>>{
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
use clap::{ArgEnum, Clap};
|
||||
use clap::{ArgEnum, ArgValue, Clap};
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
|
@ -40,7 +40,7 @@ fn basic() {
|
|||
|
||||
#[test]
|
||||
fn default_value() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
|
@ -54,7 +54,7 @@ fn default_value() {
|
|||
|
||||
impl std::fmt::Display for ArgChoice {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
std::fmt::Display::fmt(self.as_arg().unwrap(), f)
|
||||
std::fmt::Display::fmt(self.arg_value().unwrap().get_name(), f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ fn default_value() {
|
|||
|
||||
#[test]
|
||||
fn multi_word_is_renamed_kebab() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
enum ArgChoice {
|
||||
FooBar,
|
||||
|
@ -116,7 +116,7 @@ fn multi_word_is_renamed_kebab() {
|
|||
|
||||
#[test]
|
||||
fn variant_with_defined_casing() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
FooBar,
|
||||
|
@ -139,7 +139,7 @@ fn variant_with_defined_casing() {
|
|||
|
||||
#[test]
|
||||
fn casing_is_propogated_from_parent() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
enum ArgChoice {
|
||||
FooBar,
|
||||
|
@ -162,7 +162,7 @@ fn casing_is_propogated_from_parent() {
|
|||
|
||||
#[test]
|
||||
fn casing_propogation_is_overridden() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
enum ArgChoice {
|
||||
#[clap(rename_all = "camel")]
|
||||
|
@ -187,7 +187,7 @@ fn casing_propogation_is_overridden() {
|
|||
|
||||
#[test]
|
||||
fn case_insensitive() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ fn case_insensitive() {
|
|||
|
||||
#[test]
|
||||
fn case_insensitive_set_to_false() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ fn case_insensitive_set_to_false() {
|
|||
|
||||
#[test]
|
||||
fn alias() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
#[clap(alias = "TOTP")]
|
||||
TOTP,
|
||||
|
@ -264,7 +264,7 @@ fn alias() {
|
|||
|
||||
#[test]
|
||||
fn multiple_alias() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
#[clap(alias = "TOTP", alias = "t")]
|
||||
TOTP,
|
||||
|
@ -298,7 +298,7 @@ fn multiple_alias() {
|
|||
|
||||
#[test]
|
||||
fn option() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
|
@ -328,7 +328,7 @@ fn option() {
|
|||
|
||||
#[test]
|
||||
fn vector() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
|
@ -358,7 +358,7 @@ fn vector() {
|
|||
|
||||
#[test]
|
||||
fn skip_variant() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
#[allow(dead_code)] // silence warning about `Baz` being unused
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
|
@ -367,7 +367,14 @@ fn skip_variant() {
|
|||
Baz,
|
||||
}
|
||||
|
||||
assert_eq!(ArgChoice::VARIANTS, ["foo", "bar"]);
|
||||
assert_eq!(
|
||||
ArgChoice::value_variants()
|
||||
.iter()
|
||||
.map(ArgEnum::arg_value)
|
||||
.map(Option::unwrap)
|
||||
.collect::<Vec<_>>(),
|
||||
vec![ArgValue::new("foo"), ArgValue::new("bar")]
|
||||
);
|
||||
assert!(ArgChoice::from_str("foo", true).is_ok());
|
||||
assert!(ArgChoice::from_str("bar", true).is_ok());
|
||||
assert!(ArgChoice::from_str("baz", true).is_err());
|
||||
|
@ -375,7 +382,7 @@ fn skip_variant() {
|
|||
|
||||
#[test]
|
||||
fn from_str_invalid() {
|
||||
#[derive(ArgEnum, PartialEq, Debug)]
|
||||
#[derive(ArgEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use clap::ArgEnum;
|
||||
|
||||
#[derive(ArgEnum, Debug)]
|
||||
#[derive(ArgEnum, Clone, Debug)]
|
||||
struct Opt {}
|
||||
|
||||
fn main() {
|
||||
println!("{:?}", Opt::VARIANTS);
|
||||
println!("{:?}", Opt::value_variants());
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
error: `#[derive(ArgEnum)]` only supports enums
|
||||
--> $DIR/arg_enum_on_struct.rs:3:10
|
||||
|
|
||||
3 | #[derive(ArgEnum, Debug)]
|
||||
3 | #[derive(ArgEnum, Clone, Debug)]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `ArgEnum` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::iter;
|
||||
|
||||
/// The representation of a possible value of an argument.
|
||||
///
|
||||
/// This is used for specifying [possible values] of [Args].
|
||||
|
@ -20,10 +22,11 @@
|
|||
/// [possible values]: crate::Arg::possible_value()
|
||||
/// [hide]: ArgValue::hidden()
|
||||
/// [about]: ArgValue::about()
|
||||
#[derive(Debug, Default, Clone)]
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
pub struct ArgValue<'help> {
|
||||
pub(crate) name: &'help str,
|
||||
pub(crate) about: Option<&'help str>,
|
||||
pub(crate) aliases: Vec<&'help str>, // (name, visible)
|
||||
pub(crate) hidden: bool,
|
||||
}
|
||||
|
||||
|
@ -61,6 +64,37 @@ impl<'help> ArgValue<'help> {
|
|||
Some(self.name)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns all valid values of the argument value.
|
||||
/// Namely the name and all aliases.
|
||||
pub fn get_name_and_aliases(&self) -> impl Iterator<Item = &str> {
|
||||
iter::once(&self.name).chain(&self.aliases).copied()
|
||||
}
|
||||
|
||||
/// Tests if the value is valid for this argument value
|
||||
///
|
||||
/// The value is valid if it is either the name or one of the aliases.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::ArgValue;
|
||||
/// let arg_value = ArgValue::new("fast").alias("not-slow");
|
||||
///
|
||||
/// assert!(arg_value.matches("fast", false));
|
||||
/// assert!(arg_value.matches("not-slow", false));
|
||||
///
|
||||
/// assert!(arg_value.matches("FAST", true));
|
||||
/// assert!(!arg_value.matches("FAST", false));
|
||||
/// ```
|
||||
pub fn matches(&self, value: &str, ignore_case: bool) -> bool {
|
||||
if ignore_case {
|
||||
self.get_name_and_aliases()
|
||||
.any(|name| name.eq_ignore_ascii_case(value))
|
||||
} else {
|
||||
self.get_name_and_aliases().any(|name| name == value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'help> ArgValue<'help> {
|
||||
|
@ -123,4 +157,41 @@ impl<'help> ArgValue<'help> {
|
|||
self.hidden = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets an alias for this argument value.
|
||||
///
|
||||
/// The alias will be hidden from completion and help texts.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::ArgValue;
|
||||
/// ArgValue::new("slow")
|
||||
/// .alias("not-fast")
|
||||
/// # ;
|
||||
/// ```
|
||||
pub fn alias(mut self, name: &'help str) -> Self {
|
||||
self.aliases.push(name);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets multiple aliases for this argument value.
|
||||
///
|
||||
/// The aliases will be hidden from completion and help texts.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::ArgValue;
|
||||
/// ArgValue::new("slow")
|
||||
/// .aliases(["not-fast", "snake-like"])
|
||||
/// # ;
|
||||
/// ```
|
||||
pub fn aliases<I>(mut self, names: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = &'help str>,
|
||||
{
|
||||
self.aliases.extend(names.into_iter());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! This module contains traits that are usable with the `#[derive(...)].`
|
||||
//! macros in [`clap_derive`].
|
||||
|
||||
use crate::{App, ArgMatches, Error};
|
||||
use crate::{App, ArgMatches, ArgValue, Error};
|
||||
|
||||
use std::ffi::OsString;
|
||||
|
||||
|
@ -273,7 +273,7 @@ pub trait Subcommand: FromArgMatches + Sized {
|
|||
/// level: Level,
|
||||
/// }
|
||||
///
|
||||
/// #[derive(clap::ArgEnum)]
|
||||
/// #[derive(clap::ArgEnum, Clone)]
|
||||
/// enum Level {
|
||||
/// Debug,
|
||||
/// Info,
|
||||
|
@ -281,17 +281,23 @@ pub trait Subcommand: FromArgMatches + Sized {
|
|||
/// Error,
|
||||
/// }
|
||||
/// ```
|
||||
pub trait ArgEnum: Sized {
|
||||
/// All possible argument choices, in display order.
|
||||
const VARIANTS: &'static [&'static str];
|
||||
pub trait ArgEnum: Sized + Clone {
|
||||
/// All possible argument values, in display order.
|
||||
fn value_variants<'a>() -> &'a [Self];
|
||||
|
||||
/// Parse an argument into `Self`.
|
||||
fn from_str(input: &str, case_insensitive: bool) -> Result<Self, String>;
|
||||
fn from_str(input: &str, case_insensitive: bool) -> Result<Self, String> {
|
||||
Self::value_variants()
|
||||
.iter()
|
||||
.find(|v| v.arg_value().unwrap().matches(input, case_insensitive))
|
||||
.cloned()
|
||||
.ok_or_else(|| format!("Invalid variant: {}", input))
|
||||
}
|
||||
|
||||
/// The canonical argument value.
|
||||
///
|
||||
/// The value is `None` for skipped variants.
|
||||
fn as_arg(&self) -> Option<&'static str>;
|
||||
fn arg_value<'a>(&self) -> Option<ArgValue<'a>>;
|
||||
}
|
||||
|
||||
impl<T: Clap> Clap for Box<T> {
|
||||
|
|
|
@ -104,13 +104,10 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
|||
arg.possible_vals
|
||||
);
|
||||
let val_str = val.to_string_lossy();
|
||||
let ok = if arg.is_set(ArgSettings::IgnoreCase) {
|
||||
arg.possible_vals
|
||||
.iter()
|
||||
.any(|pv| pv.name.eq_ignore_ascii_case(&val_str))
|
||||
} else {
|
||||
arg.possible_vals.iter().any(|pv| pv.name == &*val_str)
|
||||
};
|
||||
let ok = arg
|
||||
.possible_vals
|
||||
.iter()
|
||||
.any(|pv| pv.matches(&val_str, arg.is_set(ArgSettings::IgnoreCase)));
|
||||
if !ok {
|
||||
let used: Vec<Id> = matcher
|
||||
.arg_names()
|
||||
|
|
|
@ -219,6 +219,22 @@ fn possible_values_output() {
|
|||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn possible_values_alias_output() {
|
||||
assert!(utils::compare_output(
|
||||
App::new("test").arg(
|
||||
Arg::new("option")
|
||||
.short('O')
|
||||
.possible_value("slow")
|
||||
.possible_value(ArgValue::new("fast").alias("fost"))
|
||||
.possible_value(ArgValue::new("ludicrous speed").aliases(["ls", "lcs"]))
|
||||
),
|
||||
"clap-test -O slo",
|
||||
PV_ERROR,
|
||||
true
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn possible_values_hidden_output() {
|
||||
assert!(utils::compare_output(
|
||||
|
@ -249,6 +265,42 @@ fn escaped_possible_values_output() {
|
|||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alias() {
|
||||
let m = App::new("pv")
|
||||
.arg(
|
||||
Arg::new("option")
|
||||
.short('o')
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value(ArgValue::new("test123").alias("123"))
|
||||
.possible_value("test321")
|
||||
.case_insensitive(true),
|
||||
)
|
||||
.try_get_matches_from(vec!["pv", "--option", "123"]);
|
||||
|
||||
assert!(m.is_ok());
|
||||
assert!(m.unwrap().value_of("option").unwrap().eq("123"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aliases() {
|
||||
let m = App::new("pv")
|
||||
.arg(
|
||||
Arg::new("option")
|
||||
.short('o')
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value(ArgValue::new("test123").aliases(["1", "2", "3"]))
|
||||
.possible_value("test321")
|
||||
.case_insensitive(true),
|
||||
)
|
||||
.try_get_matches_from(vec!["pv", "--option", "2"]);
|
||||
|
||||
assert!(m.is_ok());
|
||||
assert!(m.unwrap().value_of("option").unwrap().eq("2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn case_insensitive() {
|
||||
let m = App::new("pv")
|
||||
|
@ -272,7 +324,7 @@ fn case_insensitive() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn case_insensitive_faili() {
|
||||
fn case_insensitive_fail() {
|
||||
let m = App::new("pv")
|
||||
.arg(
|
||||
Arg::new("option")
|
||||
|
|
Loading…
Add table
Reference in a new issue