mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
commit
aeb295897d
26 changed files with 516 additions and 1482 deletions
712
CHANGELOG.md
712
CHANGELOG.md
File diff suppressed because it is too large
Load diff
|
@ -210,7 +210,7 @@ pub(crate) fn assert_app(app: &App) {
|
|||
}
|
||||
|
||||
assert!(
|
||||
!(arg.is_set(ArgSettings::Required) && arg.global),
|
||||
!(arg.is_set(ArgSettings::Required) && arg.get_global()),
|
||||
"Global arguments cannot be required.\n\n\t'{}' is marked as both global and required",
|
||||
arg.name
|
||||
);
|
||||
|
|
|
@ -290,7 +290,7 @@ impl<'help> App<'help> {
|
|||
/// this `App`.
|
||||
pub fn get_arg_conflicts_with(&self, arg: &Arg) -> Vec<&Arg<'help>> // FIXME: This could probably have been an iterator
|
||||
{
|
||||
if arg.global {
|
||||
if arg.get_global() {
|
||||
self.get_global_arg_conflicts_with(arg)
|
||||
} else {
|
||||
arg.blacklist
|
||||
|
@ -422,34 +422,26 @@ impl<'help> App<'help> {
|
|||
)
|
||||
};
|
||||
|
||||
let mut has_metadata = false;
|
||||
|
||||
for (k, v) in yaml {
|
||||
a = match k.as_str().expect("App fields must be strings") {
|
||||
"_has_metadata" => {
|
||||
has_metadata = true;
|
||||
a
|
||||
}
|
||||
"bin_name" => yaml_to_str!(a, v, bin_name),
|
||||
"version" => yaml_to_str!(a, v, version),
|
||||
"long_version" => yaml_to_str!(a, v, long_version),
|
||||
"author" => yaml_to_str!(a, v, author),
|
||||
"bin_name" => yaml_to_str!(a, v, bin_name),
|
||||
"about" => yaml_to_str!(a, v, about),
|
||||
"long_about" => yaml_to_str!(a, v, long_about),
|
||||
"before_help" => yaml_to_str!(a, v, before_help),
|
||||
"before_long_help" => yaml_to_str!(a, v, before_long_help),
|
||||
"after_help" => yaml_to_str!(a, v, after_help),
|
||||
"after_long_help" => yaml_to_str!(a, v, after_long_help),
|
||||
"help_heading" => yaml_to_str!(a, v, help_heading),
|
||||
"help_template" => yaml_to_str!(a, v, help_template),
|
||||
"override_help" => yaml_to_str!(a, v, override_help),
|
||||
"override_usage" => yaml_to_str!(a, v, override_usage),
|
||||
"template" => yaml_to_str!(a, v, help_template),
|
||||
"usage" => yaml_to_str!(a, v, override_usage),
|
||||
"help" => yaml_to_str!(a, v, override_help),
|
||||
"help_message" => yaml_to_str!(a, v, help_message),
|
||||
"version_message" => yaml_to_str!(a, v, version_message),
|
||||
"alias" => yaml_to_str!(a, v, alias),
|
||||
"aliases" => yaml_vec_or_str!(a, v, alias),
|
||||
"visible_alias" => yaml_to_str!(a, v, visible_alias),
|
||||
"visible_aliases" => yaml_vec_or_str!(a, v, visible_alias),
|
||||
"display_order" => yaml_to_usize!(a, v, display_order),
|
||||
"term_width" => yaml_to_usize!(a, v, term_width),
|
||||
"max_term_width" => yaml_to_usize!(a, v, max_term_width),
|
||||
"args" => {
|
||||
if let Some(vec) = v.as_vec() {
|
||||
for arg_yaml in vec {
|
||||
|
@ -486,13 +478,7 @@ impl<'help> App<'help> {
|
|||
"global_setting" | "global_settings" => {
|
||||
yaml_to_setting!(a, v, global_setting, AppSettings, "AppSetting", err)
|
||||
}
|
||||
"name" => continue,
|
||||
s => {
|
||||
if !has_metadata {
|
||||
panic!("Unknown setting '{}' in YAML file for {}", s, err)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
_ => a,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -869,6 +855,30 @@ impl<'help> App<'help> {
|
|||
self.override_help(help)
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`App::mut_arg`]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `App::mut_arg`")]
|
||||
pub fn help_short(self, c: char) -> Self {
|
||||
self.mut_arg("help", |a| a.short(c))
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`App::mut_arg`]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `App::mut_arg`")]
|
||||
pub fn version_short(self, c: char) -> Self {
|
||||
self.mut_arg("version", |a| a.short(c))
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`App::mut_arg`]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `App::mut_arg`")]
|
||||
pub fn help_message(self, s: impl Into<&'help str>) -> Self {
|
||||
self.mut_arg("help", |a| a.help(s.into()))
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`App::mut_arg`]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `App::mut_arg`")]
|
||||
pub fn version_message(self, s: impl Into<&'help str>) -> Self {
|
||||
self.mut_arg("version", |a| a.help(s.into()))
|
||||
}
|
||||
|
||||
/// Sets the help template to be used, overriding the default format.
|
||||
///
|
||||
/// **NOTE:** The template system is by design very simple. Therefore, the
|
||||
|
@ -954,6 +964,15 @@ impl<'help> App<'help> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`App::setting(a| b)`]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `App::setting(a | b)`")]
|
||||
pub fn settings(mut self, settings: &[AppSettings]) -> Self {
|
||||
for s in settings {
|
||||
self.settings.insert((*s).into());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Remove a setting for the current command or subcommand.
|
||||
///
|
||||
/// See [`AppSettings`] for a full list of possibilities and examples.
|
||||
|
@ -983,6 +1002,15 @@ impl<'help> App<'help> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`App::unset_setting(a| b)`]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `App::unset_setting(a | b)`")]
|
||||
pub fn unset_settings(mut self, settings: &[AppSettings]) -> Self {
|
||||
for s in settings {
|
||||
self.settings.remove((*s).into());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Apply a setting for the current command and all subcommands.
|
||||
///
|
||||
/// See [`App::setting`] to apply a setting only to this command.
|
||||
|
@ -1004,6 +1032,16 @@ impl<'help> App<'help> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`App::global_setting(a| b)`]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `App::global_setting(a | b)`")]
|
||||
pub fn global_settings(mut self, settings: &[AppSettings]) -> Self {
|
||||
for s in settings {
|
||||
self.settings.insert((*s).into());
|
||||
self.g_settings.insert((*s).into());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Remove a setting and stop propagating down to subcommands.
|
||||
///
|
||||
/// See [`AppSettings`] for a full list of possibilities and examples.
|
||||
|
@ -1983,6 +2021,12 @@ impl<'help> App<'help> {
|
|||
self._render_version(false)
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`App::render_version`]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `App::render_version`")]
|
||||
pub fn write_version<W: Write>(&self, w: &mut W) -> ClapResult<()> {
|
||||
write!(w, "{}", self.render_version()).map_err(From::from)
|
||||
}
|
||||
|
||||
/// Version message rendered as if the user ran `--version`.
|
||||
///
|
||||
/// See also [`App::render_version`].
|
||||
|
@ -2007,6 +2051,12 @@ impl<'help> App<'help> {
|
|||
self._render_version(true)
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`App::render_long_version`]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `App::render_long_version`")]
|
||||
pub fn write_long_version<W: Write>(&self, w: &mut W) -> ClapResult<()> {
|
||||
write!(w, "{}", self.render_long_version()).map_err(From::from)
|
||||
}
|
||||
|
||||
/// Usage statement
|
||||
///
|
||||
/// ### Examples
|
||||
|
@ -2465,7 +2515,7 @@ impl<'help> App<'help> {
|
|||
let global_args: Vec<_> = self
|
||||
.args
|
||||
.args()
|
||||
.filter(|a| a.global)
|
||||
.filter(|a| a.get_global())
|
||||
.map(|ga| ga.id.clone())
|
||||
.collect();
|
||||
if let Some(used_subcommand) = matcher.0.subcommand.as_ref() {
|
||||
|
@ -2608,7 +2658,7 @@ impl<'help> App<'help> {
|
|||
debug!("App::_propagate_global_args:{}", self.name);
|
||||
|
||||
for sc in &mut self.subcommands {
|
||||
for a in self.args.args().filter(|a| a.global) {
|
||||
for a in self.args.args().filter(|a| a.get_global()) {
|
||||
let mut propagate = false;
|
||||
let is_generated = matches!(
|
||||
a.provider,
|
||||
|
|
|
@ -103,11 +103,11 @@ impl_settings! { AppSettings, AppFlags,
|
|||
=> Flags::DISABLE_HELP_SC,
|
||||
DisableHelpFlag("disablehelpflag")
|
||||
=> Flags::DISABLE_HELP_FLAG,
|
||||
DisableHelpFlags("disablehelpflag")
|
||||
DisableHelpFlags("disablehelpflags")
|
||||
=> Flags::DISABLE_HELP_FLAG,
|
||||
DisableVersionFlag("disableversionflag")
|
||||
=> Flags::DISABLE_VERSION_FLAG,
|
||||
DisableVersion("disableversionflag")
|
||||
DisableVersion("disableversion")
|
||||
=> Flags::DISABLE_VERSION_FLAG,
|
||||
PropagateVersion("propagateversion")
|
||||
=> Flags::PROPAGATE_VERSION,
|
||||
|
|
|
@ -23,10 +23,6 @@ use std::{
|
|||
#[cfg(feature = "env")]
|
||||
use std::{env, ffi::OsString};
|
||||
|
||||
// Third Party
|
||||
#[cfg(feature = "regex")]
|
||||
use ::regex::Regex;
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
use yaml_rust::Yaml;
|
||||
|
||||
|
@ -119,7 +115,6 @@ pub struct Arg<'help> {
|
|||
pub(crate) terminator: Option<&'help str>,
|
||||
pub(crate) index: Option<usize>,
|
||||
pub(crate) help_heading: Option<Option<&'help str>>,
|
||||
pub(crate) global: bool,
|
||||
pub(crate) exclusive: bool,
|
||||
pub(crate) value_hint: ValueHint,
|
||||
}
|
||||
|
@ -268,7 +263,7 @@ impl<'help> Arg<'help> {
|
|||
|
||||
/// Get information on if this argument is global or not
|
||||
pub fn get_global(&self) -> bool {
|
||||
self.global
|
||||
self.is_set(ArgSettings::Global)
|
||||
}
|
||||
|
||||
/// Get the environment variable name specified for this argument, if any
|
||||
|
@ -356,6 +351,7 @@ impl<'help> Arg<'help> {
|
|||
note = "Maybe clap::Parser would fit your use case? (Issue #9)"
|
||||
)]
|
||||
pub fn from_yaml(y: &'help Yaml) -> Self {
|
||||
#![allow(deprecated)]
|
||||
let yaml_file_hash = y.as_hash().expect("YAML file must be a hash");
|
||||
// We WANT this to panic on error...so expect() is good.
|
||||
let (name_yaml, yaml) = yaml_file_hash
|
||||
|
@ -365,34 +361,21 @@ impl<'help> Arg<'help> {
|
|||
let name_str = name_yaml.as_str().expect("Arg name must be a string");
|
||||
let mut a = Arg::new(name_str);
|
||||
|
||||
let mut has_metadata = false;
|
||||
|
||||
for (k, v) in yaml.as_hash().expect("Arg must be a hash") {
|
||||
a = match k.as_str().expect("Arg fields must be strings") {
|
||||
"_has_metadata" => {
|
||||
has_metadata = true;
|
||||
a
|
||||
}
|
||||
"short" => yaml_to_char!(a, v, short),
|
||||
"long" => yaml_to_str!(a, v, long),
|
||||
"alias" => yaml_to_str!(a, v, alias),
|
||||
"aliases" => yaml_vec_or_str!(a, v, alias),
|
||||
"short_alias" => yaml_to_str!(a, v, alias),
|
||||
"short_aliases" => yaml_to_chars!(a, v, short_aliases),
|
||||
"help" => yaml_to_str!(a, v, help),
|
||||
"long_help" => yaml_to_str!(a, v, long_help),
|
||||
"required" => yaml_to_bool!(a, v, required),
|
||||
"required_if_eq" => yaml_tuple2!(a, v, required_if_eq),
|
||||
"required_if_eq_any" => yaml_array_tuple2!(a, v, required_if_eq_any),
|
||||
"required_if_eq_all" => yaml_array_tuple2!(a, v, required_if_eq_all),
|
||||
"required_if" => yaml_tuple2!(a, v, required_if_eq),
|
||||
"required_ifs" => yaml_tuple2!(a, v, required_if_eq),
|
||||
"takes_value" => yaml_to_bool!(a, v, takes_value),
|
||||
"index" => yaml_to_usize!(a, v, index),
|
||||
"global" => yaml_to_bool!(a, v, global),
|
||||
"multiple_occurrences" => yaml_to_bool!(a, v, multiple_occurrences),
|
||||
"multiple_values" => yaml_to_bool!(a, v, multiple_values),
|
||||
"hide" => yaml_to_bool!(a, v, hide),
|
||||
"hide_long_help" => yaml_to_bool!(a, v, hide_long_help),
|
||||
"hide_short_help" => yaml_to_bool!(a, v, hide_short_help),
|
||||
"multiple" => yaml_to_bool!(a, v, multiple),
|
||||
"hidden" => yaml_to_bool!(a, v, hide),
|
||||
"next_line_help" => yaml_to_bool!(a, v, next_line_help),
|
||||
"group" => yaml_to_str!(a, v, group),
|
||||
"number_of_values" => yaml_to_usize!(a, v, number_of_values),
|
||||
|
@ -401,17 +384,14 @@ impl<'help> Arg<'help> {
|
|||
"value_name" => yaml_to_str!(a, v, value_name),
|
||||
"use_delimiter" => yaml_to_bool!(a, v, use_delimiter),
|
||||
"allow_hyphen_values" => yaml_to_bool!(a, v, allow_hyphen_values),
|
||||
"raw" => yaml_to_bool!(a, v, raw),
|
||||
"require_equals" => yaml_to_bool!(a, v, require_equals),
|
||||
"last" => yaml_to_bool!(a, v, last),
|
||||
"require_delimiter" => yaml_to_bool!(a, v, require_delimiter),
|
||||
"value_terminator" => yaml_to_str!(a, v, value_terminator),
|
||||
"value_delimiter" => yaml_to_char!(a, v, value_delimiter),
|
||||
"required_unless_present" => yaml_to_str!(a, v, required_unless_present),
|
||||
"required_unless" => yaml_to_str!(a, v, required_unless_present),
|
||||
"display_order" => yaml_to_usize!(a, v, display_order),
|
||||
"default_value" => yaml_to_str!(a, v, default_value),
|
||||
"default_value_if" => yaml_tuple3!(a, v, default_value_if),
|
||||
"default_value_ifs" => yaml_tuple3!(a, v, default_value_if),
|
||||
"default_missing_value" => yaml_to_str!(a, v, default_missing_value),
|
||||
#[cfg(feature = "env")]
|
||||
"env" => yaml_to_str!(a, v, env),
|
||||
"value_names" => yaml_vec_or_str!(a, v, value_name),
|
||||
|
@ -420,62 +400,16 @@ impl<'help> Arg<'help> {
|
|||
"requires_if" => yaml_tuple2!(a, v, requires_if),
|
||||
"requires_ifs" => yaml_tuple2!(a, v, requires_if),
|
||||
"conflicts_with" => yaml_vec_or_str!(a, v, conflicts_with),
|
||||
"exclusive" => yaml_to_bool!(a, v, exclusive),
|
||||
"last" => yaml_to_bool!(a, v, last),
|
||||
"help_heading" => yaml_to_str!(a, v, help_heading),
|
||||
"value_hint" => yaml_str_parse!(a, v, value_hint),
|
||||
"hide_default_value" => yaml_to_bool!(a, v, hide_default_value),
|
||||
#[cfg(feature = "env")]
|
||||
"hide_env" => yaml_to_bool!(a, v, hide_env),
|
||||
#[cfg(feature = "env")]
|
||||
"hide_env_values" => yaml_to_bool!(a, v, hide_env_values),
|
||||
"hide_possible_values" => yaml_to_bool!(a, v, hide_possible_values),
|
||||
"overrides_with" => yaml_to_str!(a, v, overrides_with),
|
||||
"overrides_with_all" => yaml_vec_or_str!(a, v, overrides_with),
|
||||
"possible_value" => yaml_to_str!(a, v, possible_value),
|
||||
"possible_values" => yaml_vec_or_str!(a, v, possible_value),
|
||||
"ignore_case" => yaml_to_bool!(a, v, ignore_case),
|
||||
"required_unless_present_any" => yaml_vec!(a, v, required_unless_present_any),
|
||||
"required_unless_present_all" => yaml_vec!(a, v, required_unless_present_all),
|
||||
"visible_alias" => yaml_to_str!(a, v, visible_alias),
|
||||
"visible_aliases" => yaml_vec_or_str!(a, v, visible_alias),
|
||||
"visible_short_alias" => yaml_to_char!(a, v, visible_short_alias),
|
||||
"visible_short_aliases" => yaml_to_chars!(a, v, visible_short_aliases),
|
||||
#[cfg(feature = "regex")]
|
||||
"validator_regex" => {
|
||||
if let Some(vec) = v.as_vec() {
|
||||
debug_assert_eq!(2, vec.len());
|
||||
let regex = yaml_str!(vec[0]);
|
||||
|
||||
match Regex::new(regex) {
|
||||
Err(e) => panic!(
|
||||
"Failed to convert \"{}\" into regular expression: {}",
|
||||
regex, e
|
||||
),
|
||||
Ok(regex) => a.validator_regex(regex, yaml_str!(vec[1])),
|
||||
}
|
||||
} else {
|
||||
panic!("Failed to convert YAML value to vector")
|
||||
}
|
||||
}
|
||||
"setting" | "settings" => {
|
||||
yaml_to_setting!(
|
||||
a,
|
||||
v,
|
||||
setting,
|
||||
ArgSettings,
|
||||
"ArgSetting",
|
||||
format!("arg '{}'", name_str)
|
||||
)
|
||||
}
|
||||
"case_insensitive" => yaml_to_bool!(a, v, ignore_case),
|
||||
"required_unless_one" => yaml_vec!(a, v, required_unless_present_any),
|
||||
"required_unless_all" => yaml_vec!(a, v, required_unless_present_all),
|
||||
s => {
|
||||
if !has_metadata {
|
||||
panic!(
|
||||
"Unknown setting '{}' in YAML file for arg '{}'",
|
||||
s, name_str
|
||||
)
|
||||
}
|
||||
continue;
|
||||
panic!(
|
||||
"Unknown setting '{}' in YAML file for arg '{}'",
|
||||
s, name_str
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1113,7 +1047,7 @@ impl<'help> Arg<'help> {
|
|||
since = "3.0.0",
|
||||
note = "Replaced with `Arg::required_unless_present_any`"
|
||||
)]
|
||||
pub fn required_unless_any<T, I>(self, names: I) -> Self
|
||||
pub fn required_unless_one<T, I>(self, names: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Key,
|
||||
|
@ -3020,6 +2954,8 @@ impl<'help> Arg<'help> {
|
|||
/// If `val` is set to `None`, `arg` only needs to be present. If `val` is set to `"some-val"`
|
||||
/// then `arg` must be present at runtime **and** have the value `val`.
|
||||
///
|
||||
/// If `default` is set to `None`, `default_value` will be removed.
|
||||
///
|
||||
/// **NOTE:** This setting is perfectly compatible with [`Arg::default_value`] but slightly
|
||||
/// different. `Arg::default_value` *only* takes effect when the user has not provided this arg
|
||||
/// at runtime. This setting however only takes effect when the user has not provided a value at
|
||||
|
@ -3791,9 +3727,12 @@ impl<'help> Arg<'help> {
|
|||
/// [`Subcommand`]: crate::Subcommand
|
||||
/// [`ArgMatches::is_present("flag")`]: ArgMatches::is_present()
|
||||
#[inline]
|
||||
pub fn global(mut self, yes: bool) -> Self {
|
||||
self.global = yes;
|
||||
self
|
||||
pub fn global(self, yes: bool) -> Self {
|
||||
if yes {
|
||||
self.setting(ArgSettings::Global)
|
||||
} else {
|
||||
self.unset_setting(ArgSettings::Global)
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies that *multiple values* may only be set using the delimiter.
|
||||
|
@ -5082,7 +5021,6 @@ impl<'help> fmt::Debug for Arg<'help> {
|
|||
.field("terminator", &self.terminator)
|
||||
.field("index", &self.index)
|
||||
.field("help_heading", &self.help_heading)
|
||||
.field("global", &self.global)
|
||||
.field("exclusive", &self.exclusive)
|
||||
.field("value_hint", &self.value_hint)
|
||||
.field("default_missing_vals", &self.default_missing_vals);
|
||||
|
|
|
@ -52,7 +52,7 @@ impl_settings! { ArgSettings, ArgFlags,
|
|||
MultipleValues("multiplevalues") => Flags::MULTIPLE_VALS,
|
||||
Multiple("multiple") => Flags::MULTIPLE,
|
||||
ForbidEmptyValues("forbidemptyvalues") => Flags::NO_EMPTY_VALS,
|
||||
EmptyValues("emptyvalues") => Flags::NO_OP,
|
||||
Global("global") => Flags::GLOBAL,
|
||||
Hidden("hidden") => Flags::HIDDEN,
|
||||
TakesValue("takesvalue") => Flags::TAKES_VAL,
|
||||
UseValueDelimiter("usevaluedelimiter") => Flags::USE_DELIM,
|
||||
|
@ -64,7 +64,7 @@ impl_settings! { ArgSettings, ArgFlags,
|
|||
RequireEquals("requireequals") => Flags::REQUIRE_EQUALS,
|
||||
Last("last") => Flags::LAST,
|
||||
IgnoreCase("ignorecase") => Flags::CASE_INSENSITIVE,
|
||||
CaseInsensitive("ignorecase") => Flags::CASE_INSENSITIVE,
|
||||
CaseInsensitive("caseinsensitive") => Flags::CASE_INSENSITIVE,
|
||||
#[cfg(feature = "env")]
|
||||
HideEnv("hideenv") => Flags::HIDE_ENV,
|
||||
#[cfg(feature = "env")]
|
||||
|
@ -100,13 +100,8 @@ pub enum ArgSettings {
|
|||
Multiple,
|
||||
/// Forbids an arg from accepting empty values such as `""`
|
||||
ForbidEmptyValues,
|
||||
/// Deprecated, this is now the default, see [`ArgSettings::ForbidEmptyValues`] for the
|
||||
/// opposite.
|
||||
#[deprecated(
|
||||
since = "3.0.0",
|
||||
note = "This is now the default see [`ArgSettings::ForbidEmptyValues`] for the opposite."
|
||||
)]
|
||||
EmptyValues,
|
||||
/// Sets an arg to be global (i.e. exist in all subcommands)
|
||||
Global,
|
||||
/// Hides an arg from the help message
|
||||
Hidden,
|
||||
/// Allows an argument to take a value (such as `--option value`)
|
||||
|
|
|
@ -17,25 +17,6 @@ macro_rules! yaml_tuple2 {
|
|||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_array_tuple2 {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
if let Some(vec) = $v.as_vec() {
|
||||
for ys in vec {
|
||||
if let Some(tup) = ys.as_vec() {
|
||||
debug_assert_eq!(2, tup.len());
|
||||
$a = $a.$c(&[(yaml_str!(tup[0]), yaml_str!(tup[1]))]);
|
||||
} else {
|
||||
panic!("Failed to convert YAML value to vec");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("Failed to convert YAML value to vec");
|
||||
}
|
||||
$a
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_tuple3 {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
|
@ -130,28 +111,6 @@ macro_rules! yaml_char {
|
|||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_chars {
|
||||
($v:expr) => {{
|
||||
&$v.as_vec()
|
||||
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a list", $v))
|
||||
.into_iter()
|
||||
.map(|s| {
|
||||
s.as_str()
|
||||
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", s))
|
||||
})
|
||||
.map(|s| {
|
||||
let mut chars = s.chars();
|
||||
let c = chars.next().expect("short aliases must be a single char");
|
||||
if chars.next().is_some() {
|
||||
panic!("short aliases must be a single char");
|
||||
}
|
||||
c
|
||||
})
|
||||
.collect::<Vec<char>>()
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_str {
|
||||
($v:expr) => {{
|
||||
|
@ -160,17 +119,6 @@ macro_rules! yaml_str {
|
|||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_str_parse {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
$a.$c($v
|
||||
.as_str()
|
||||
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v))
|
||||
.parse()
|
||||
.unwrap_or_else(|err| panic!("{}", err)))
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_to_char {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
|
@ -178,13 +126,6 @@ macro_rules! yaml_to_char {
|
|||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_to_chars {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
$a.$c(yaml_chars!($v))
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_to_str {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
|
|
346
src/macros.rs
346
src/macros.rs
|
@ -12,6 +12,166 @@ macro_rules! load_yaml {
|
|||
};
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`ArgMatches::value_of_t`][crate::ArgMatches::value_of_t]
|
||||
#[macro_export]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::value_of_t`")]
|
||||
macro_rules! value_t {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
$crate::value_t!($m.value_of($v), $t)
|
||||
};
|
||||
($m:ident.value_of($v:expr), $t:ty) => {
|
||||
$m.value_of_t::<$t>($v)
|
||||
};
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`ArgMatches::value_of_t_or_exit`][crate::ArgMatches::value_of_t_or_exit]
|
||||
#[macro_export]
|
||||
#[deprecated(
|
||||
since = "3.0.0",
|
||||
note = "Replaced with `ArgMatches::value_of_t_or_exit`"
|
||||
)]
|
||||
macro_rules! value_t_or_exit {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
value_t_or_exit!($m.value_of($v), $t)
|
||||
};
|
||||
($m:ident.value_of($v:expr), $t:ty) => {
|
||||
$m.value_of_t_or_exit::<$t>($v)
|
||||
};
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`ArgMatches::values_of_t`][crate::ArgMatches::value_of_t]
|
||||
#[macro_export]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::values_of_t`")]
|
||||
macro_rules! values_t {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
values_t!($m.values_of($v), $t)
|
||||
};
|
||||
($m:ident.values_of($v:expr), $t:ty) => {
|
||||
$m.values_of_t::<$t>($v)
|
||||
};
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`ArgMatches::values_of_t_or_exit`][crate::ArgMatches::value_of_t_or_exit]
|
||||
#[macro_export]
|
||||
#[deprecated(
|
||||
since = "3.0.0",
|
||||
note = "Replaced with `ArgMatches::values_of_t_or_exit`"
|
||||
)]
|
||||
macro_rules! values_t_or_exit {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
values_t_or_exit!($m.values_of($v), $t)
|
||||
};
|
||||
($m:ident.values_of($v:expr), $t:ty) => {
|
||||
$m.values_of_t_or_exit::<$t>($v)
|
||||
};
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`ArgEnum`][crate::ArgEnum]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `ArgEnum`")]
|
||||
#[macro_export]
|
||||
macro_rules! arg_enum {
|
||||
(@as_item $($i:item)*) => ($($i)*);
|
||||
(@impls ( $($tts:tt)* ) -> ($e:ident, $($v:ident),+)) => {
|
||||
$crate::arg_enum!(@as_item
|
||||
$($tts)*
|
||||
|
||||
impl ::std::str::FromStr for $e {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> ::std::result::Result<Self,Self::Err> {
|
||||
#[allow(deprecated, unused_imports)]
|
||||
use ::std::ascii::AsciiExt;
|
||||
match s {
|
||||
$(stringify!($v) |
|
||||
_ if s.eq_ignore_ascii_case(stringify!($v)) => Ok($e::$v)),+,
|
||||
_ => Err({
|
||||
let v = vec![
|
||||
$(stringify!($v),)+
|
||||
];
|
||||
format!("valid values: {}",
|
||||
v.join(", "))
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ::std::fmt::Display for $e {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
match *self {
|
||||
$($e::$v => write!(f, stringify!($v)),)+
|
||||
}
|
||||
}
|
||||
}
|
||||
impl $e {
|
||||
#[allow(dead_code)]
|
||||
pub fn variants() -> [&'static str; $crate::_clap_count_exprs!($(stringify!($v)),+)] {
|
||||
[
|
||||
$(stringify!($v),)+
|
||||
]
|
||||
}
|
||||
});
|
||||
};
|
||||
($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
|
||||
$crate::arg_enum!(@impls
|
||||
($(#[$($m),+])+
|
||||
pub enum $e {
|
||||
$($v$(=$val)*),+
|
||||
}) -> ($e, $($v),+)
|
||||
);
|
||||
};
|
||||
($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
|
||||
$crate::arg_enum!(@impls
|
||||
($(#[$($m),+])+
|
||||
pub enum $e {
|
||||
$($v$(=$val)*),+
|
||||
}) -> ($e, $($v),+)
|
||||
);
|
||||
};
|
||||
($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
|
||||
$crate::arg_enum!(@impls
|
||||
($(#[$($m),+])+
|
||||
enum $e {
|
||||
$($v$(=$val)*),+
|
||||
}) -> ($e, $($v),+)
|
||||
);
|
||||
};
|
||||
($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
|
||||
$crate::arg_enum!(@impls
|
||||
($(#[$($m),+])+
|
||||
enum $e {
|
||||
$($v$(=$val)*),+
|
||||
}) -> ($e, $($v),+)
|
||||
);
|
||||
};
|
||||
(pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
|
||||
$crate::arg_enum!(@impls
|
||||
(pub enum $e {
|
||||
$($v$(=$val)*),+
|
||||
}) -> ($e, $($v),+)
|
||||
);
|
||||
};
|
||||
(pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
|
||||
$crate::arg_enum!(@impls
|
||||
(pub enum $e {
|
||||
$($v$(=$val)*),+
|
||||
}) -> ($e, $($v),+)
|
||||
);
|
||||
};
|
||||
(enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
|
||||
$crate::arg_enum!(@impls
|
||||
(enum $e {
|
||||
$($v$(=$val)*),+
|
||||
}) -> ($e, $($v),+)
|
||||
);
|
||||
};
|
||||
(enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
|
||||
$crate::arg_enum!(@impls
|
||||
(enum $e {
|
||||
$($v$(=$val)*),+
|
||||
}) -> ($e, $($v),+)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/// Allows you to pull the version from your Cargo.toml at compile time as
|
||||
/// `MAJOR.MINOR.PATCH_PKGVERSION_PRE`
|
||||
///
|
||||
|
@ -464,13 +624,6 @@ macro_rules! clap_app {
|
|||
$($tt)*
|
||||
}
|
||||
};
|
||||
(@app ($builder:expr) (@arg $name:literal: $($tail:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @app
|
||||
($builder.arg(
|
||||
$crate::clap_app!{ @arg ($crate::Arg::new(stringify!($name).trim_matches('"'))) (-) $($tail)* }))
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
(@app ($builder:expr) (@arg $name:ident: $($tail:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @app
|
||||
($builder.arg(
|
||||
|
@ -478,48 +631,35 @@ macro_rules! clap_app {
|
|||
$($tt)*
|
||||
}
|
||||
};
|
||||
// Global Settings
|
||||
(@app ($builder:expr) (@global_setting $setting:ident) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @app
|
||||
($builder.global_setting($crate::AppSettings::$setting))
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
// Settings
|
||||
(@app ($builder:expr) (@setting $setting:ident) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @app
|
||||
($builder.setting($crate::AppSettings::$setting))
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
// Treat the application builder as an argument to set its attributes
|
||||
// Treat the application builder as an argument to set its attributes
|
||||
(@app ($builder:expr) (@attributes $($attr:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @app ($crate::clap_app!{ @arg ($builder) $($attr)* }) $($tt)* }
|
||||
};
|
||||
// ArgGroup
|
||||
(@app ($builder:expr) (@group $name:ident: $($attrs:tt)*) $($tt:tt)*) => {
|
||||
(@app ($builder:expr) (@group $name:ident => $($tail:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @app
|
||||
($crate::clap_app!{ @group ($builder, $crate::ArgGroup::new(stringify!($name))) $($attrs)* })
|
||||
($crate::clap_app!{ @group ($builder, $crate::ArgGroup::new(stringify!($name))) $($tail)* })
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
// Handle subcommand creation
|
||||
(@app ($builder:expr) (@subcommand ($name:expr) => $($tail:tt)*) $($tt:tt)*) => {
|
||||
(@app ($builder:expr) (@group $name:ident !$ident:ident => $($tail:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @app
|
||||
($builder.subcommand(
|
||||
$crate::clap_app!{ @app ($crate::App::new($name)) $($tail)* }
|
||||
))
|
||||
($crate::clap_app!{ @group ($builder, $crate::ArgGroup::new(stringify!($name)).$ident(false)) $($tail)* })
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
(@app ($builder:expr) (@subcommand $name:literal => $($tail:tt)*) $($tt:tt)*) => {
|
||||
(@app ($builder:expr) (@group $name:ident +$ident:ident => $($tail:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @app
|
||||
($builder.subcommand(
|
||||
$crate::clap_app!{ @app ($crate::App::new(stringify!($name).trim_matches('"'))) $($tail)* }
|
||||
))
|
||||
($crate::clap_app!{ @group ($builder, $crate::ArgGroup::new(stringify!($name)).$ident(true)) $($tail)* })
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
// Handle subcommand creation
|
||||
(@app ($builder:expr) (@subcommand $name:ident => $($tail:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @app
|
||||
($builder.subcommand(
|
||||
|
@ -528,32 +668,20 @@ macro_rules! clap_app {
|
|||
$($tt)*
|
||||
}
|
||||
};
|
||||
// Yaml like function calls - used for setting various meta directly against the app
|
||||
// Yaml like function calls - used for setting various meta directly against the app
|
||||
(@app ($builder:expr) ($ident:ident: $($v:expr),*) $($tt:tt)*) => {
|
||||
// $crate::clap_app!{ @app ($builder.$ident($($v),*)) $($tt)* }
|
||||
$crate::clap_app!{ @app
|
||||
($builder.$ident($($v),*))
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
// Add members to group and continue argument handling with the parent builder
|
||||
|
||||
// Add members to group and continue argument handling with the parent builder
|
||||
(@group ($builder:expr, $group:expr)) => { $builder.group($group) };
|
||||
// Treat the group builder as an argument to set its attributes
|
||||
(@group ($builder:expr, $group:expr) (@attributes $($attr:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @group ($builder, $group) $($attr)* $($tt)* }
|
||||
};
|
||||
(@group ($builder:expr, $group:expr) (@arg ($name:expr): $($tail:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @group
|
||||
($crate::clap_app!{ @app ($builder) (@arg ($name): $($tail)*) },
|
||||
$group.arg($name))
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
(@group ($builder:expr, $group:expr) (@arg $name:literal: $($tail:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @group
|
||||
($crate::clap_app!{ @app ($builder) (@arg $name: $($tail)*) },
|
||||
$group.arg(stringify!($name).trim_matches('"')))
|
||||
$($tt)*
|
||||
}
|
||||
$crate::clap_app!{ @group ($builder, $crate::clap_app!{ @arg ($group) (-) $($attr)* }) $($tt)* }
|
||||
};
|
||||
(@group ($builder:expr, $group:expr) (@arg $name:ident: $($tail:tt)*) $($tt:tt)*) => {
|
||||
$crate::clap_app!{ @group
|
||||
|
@ -562,50 +690,16 @@ macro_rules! clap_app {
|
|||
$($tt)*
|
||||
}
|
||||
};
|
||||
// Handle group attributes
|
||||
(@group ($builder:expr, $group:expr) !$ident:ident $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @group ($builder, $group.$ident(false)) $($tail)* }
|
||||
};
|
||||
(@group ($builder:expr, $group:expr) +$ident:ident $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @group ($builder, $group.$ident(true)) $($tail)* }
|
||||
};
|
||||
(@group ($builder:expr, $group:expr) * $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @group ($builder, $group) +required $($tail)* }
|
||||
};
|
||||
(@group ($builder:expr, $group:expr) ... $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @group ($builder, $group) +multiple $($tail)* }
|
||||
};
|
||||
(@group ($builder:expr, $group:expr) $ident:ident[$($target:literal)*] $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @group ($builder, $group $( .$ident(stringify!($target).trim_matches('"')) )*) $($tail)* }
|
||||
};
|
||||
(@group ($builder:expr, $group:expr) $ident:ident[$($target:ident)*] $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @group ($builder, $group $( .$ident(stringify!($target)) )*) $($tail)* }
|
||||
};
|
||||
(@group ($builder:expr, $group:expr) $ident:ident($($expr:expr),*) $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @group ($builder, $group.$ident($($expr),*)) $($tail)* }
|
||||
};
|
||||
(@group ($builder:expr, $group:expr) $ident:ident($($expr:expr,)*) $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @group ($builder, $group.$ident($($expr),*)) $($tail)* }
|
||||
};
|
||||
|
||||
// No more tokens to munch
|
||||
// No more tokens to munch
|
||||
(@arg ($arg:expr) $modes:tt) => { $arg };
|
||||
// Shorthand tokens influenced by the usage_string
|
||||
// Shorthand tokens influenced by the usage_string
|
||||
(@arg ($arg:expr) $modes:tt --($long:expr) $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.long($long)) $modes $($tail)* }
|
||||
};
|
||||
(@arg ($arg:expr) $modes:tt --$long:literal $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.long(stringify!($long).trim_matches('"'))) $modes $($tail)* }
|
||||
};
|
||||
(@arg ($arg:expr) $modes:tt --$long:ident $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.long(stringify!($long))) $modes $($tail)* }
|
||||
};
|
||||
(@arg ($arg:expr) $modes:tt -($short:expr) $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.short($short)) $modes $($tail)* }
|
||||
};
|
||||
(@arg ($arg:expr) $modes:tt -$short:literal $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.short($short.to_string().chars().next().expect(r#""" is not allowed here"#))) $modes $($tail)* }
|
||||
};
|
||||
(@arg ($arg:expr) $modes:tt -$short:ident $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.short(stringify!($short).chars().next().unwrap())) $modes $($tail)* }
|
||||
};
|
||||
|
@ -622,62 +716,52 @@ macro_rules! clap_app {
|
|||
$crate::clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) $($tail)* }
|
||||
};
|
||||
(@arg ($arg:expr) $modes:tt ... $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg) $modes +multiple_values +takes_value $($tail)* }
|
||||
$crate::clap_app!{ @arg ($arg) $modes +multiple +takes_value $($tail)* }
|
||||
};
|
||||
// Shorthand magic
|
||||
// Shorthand magic
|
||||
(@arg ($arg:expr) $modes:tt #{$n:expr, $m:expr} $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg) $modes min_values($n) max_values($m) $($tail)* }
|
||||
};
|
||||
(@arg ($arg:expr) $modes:tt * $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg) $modes +required $($tail)* }
|
||||
};
|
||||
// !foo -> .foo(false)
|
||||
// !foo -> .foo(false)
|
||||
(@arg ($arg:expr) $modes:tt !$ident:ident $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.$ident(false)) $modes $($tail)* }
|
||||
};
|
||||
// +foo -> .foo(true)
|
||||
// +foo -> .foo(true)
|
||||
(@arg ($arg:expr) $modes:tt +$ident:ident $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.$ident(true)) $modes $($tail)* }
|
||||
};
|
||||
// Validator
|
||||
// Validator
|
||||
(@arg ($arg:expr) $modes:tt {$fn_:expr} $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.validator($fn_)) $modes $($tail)* }
|
||||
};
|
||||
(@as_expr $expr:expr) => { $expr };
|
||||
// Help
|
||||
// Help
|
||||
(@arg ($arg:expr) $modes:tt $desc:tt) => { $arg.help($crate::clap_app!{ @as_expr $desc }) };
|
||||
// Handle functions that need to be called multiple times for each argument
|
||||
(@arg ($arg:expr) $modes:tt $ident:ident[$($target:literal)*] $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg $( .$ident(stringify!($target).trim_matches('"')) )*) $modes $($tail)* }
|
||||
};
|
||||
// Handle functions that need to be called multiple times for each argument
|
||||
(@arg ($arg:expr) $modes:tt $ident:ident[$($target:ident)*] $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg $( .$ident(stringify!($target)) )*) $modes $($tail)* }
|
||||
};
|
||||
// Inherit builder's functions, e.g. `index(2)`, `requires_if("val", "arg")`
|
||||
// Inherit builder's functions, e.g. `index(2)`, `requires_if("val", "arg")`
|
||||
(@arg ($arg:expr) $modes:tt $ident:ident($($expr:expr),*) $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.$ident($($expr),*)) $modes $($tail)* }
|
||||
};
|
||||
// Inherit builder's functions with trailing comma, e.g. `index(2,)`, `requires_if("val", "arg",)`
|
||||
// Inherit builder's functions with trailing comma, e.g. `index(2,)`, `requires_if("val", "arg",)`
|
||||
(@arg ($arg:expr) $modes:tt $ident:ident($($expr:expr,)*) $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @arg ($arg.$ident($($expr),*)) $modes $($tail)* }
|
||||
};
|
||||
// Build a subcommand outside of an app.
|
||||
(@subcommand ($name:expr) => $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @app ($crate::App::new($name)) $($tail)* }
|
||||
};
|
||||
(@subcommand $name:literal => $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @app ($crate::App::new(stringify!($name).trim_matches('"'))) $($tail)* }
|
||||
};
|
||||
|
||||
// Build a subcommand outside of an app.
|
||||
(@subcommand $name:ident => $($tail:tt)*) => {
|
||||
$crate::clap_app!{ @app ($crate::App::new(stringify!($name))) $($tail)* }
|
||||
};
|
||||
// Start the magic
|
||||
// Start the magic
|
||||
(($name:expr) => $($tail:tt)*) => {{
|
||||
$crate::clap_app!{ @app ($crate::App::new($name)) $($tail)*}
|
||||
}};
|
||||
($name:literal => $($tail:tt)*) => {{
|
||||
$crate::clap_app!{ @app ($crate::App::new(stringify!($name).trim_matches('"'))) $($tail)*}
|
||||
}};
|
||||
|
||||
($name:ident => $($tail:tt)*) => {{
|
||||
$crate::clap_app!{ @app ($crate::App::new(stringify!($name))) $($tail)*}
|
||||
}};
|
||||
|
@ -819,57 +903,3 @@ macro_rules! debug {
|
|||
macro_rules! debug {
|
||||
($($arg:tt)*) => {};
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`ArgMatches::value_of_t`][crate::ArgMatches::value_of_t]
|
||||
#[macro_export]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::value_of_t`")]
|
||||
macro_rules! value_t {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
clap::value_t!($m.value_of($v), $t)
|
||||
};
|
||||
($m:ident.value_of($v:expr), $t:ty) => {
|
||||
$m.value_of_t::<$t>($v)
|
||||
};
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`ArgMatches::value_of_t_or_exit`][crate::ArgMatches::value_of_t_or_exit]
|
||||
#[macro_export]
|
||||
#[deprecated(
|
||||
since = "3.0.0",
|
||||
note = "Replaced with `ArgMatches::value_of_t_or_exit`"
|
||||
)]
|
||||
macro_rules! value_t_or_exit {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
value_t_or_exit!($m.value_of($v), $t)
|
||||
};
|
||||
($m:ident.value_of($v:expr), $t:ty) => {
|
||||
$m.value_of_t_or_exit::<$t>($v)
|
||||
};
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`ArgMatches::values_of_t`][crate::ArgMatches::value_of_t]
|
||||
#[macro_export]
|
||||
#[deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::values_of_t`")]
|
||||
macro_rules! values_t {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
values_t!($m.values_of($v), $t)
|
||||
};
|
||||
($m:ident.values_of($v:expr), $t:ty) => {
|
||||
$m.values_of_t::<$t>($v)
|
||||
};
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`ArgMatches::values_of_t_or_exit`][crate::ArgMatches::value_of_t_or_exit]
|
||||
#[macro_export]
|
||||
#[deprecated(
|
||||
since = "3.0.0",
|
||||
note = "Replaced with `ArgMatches::values_of_t_or_exit`"
|
||||
)]
|
||||
macro_rules! values_t_or_exit {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
values_t_or_exit!($m.values_of($v), $t)
|
||||
};
|
||||
($m:ident.values_of($v:expr), $t:ty) => {
|
||||
$m.values_of_t_or_exit::<$t>($v)
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,31 +4,26 @@ about: tests clap library
|
|||
author: Kevin K. <kbknapp@gmail.com>
|
||||
settings:
|
||||
- ArgRequiredElseHelp
|
||||
help_message: prints help with a nonstandard description
|
||||
args:
|
||||
- help:
|
||||
short: h
|
||||
long: help
|
||||
help: prints help with a nonstandard description
|
||||
- option:
|
||||
- opt:
|
||||
short: o
|
||||
long: option
|
||||
multiple: true
|
||||
takes_value: true
|
||||
multiple_values: true
|
||||
help: tests options
|
||||
- positional:
|
||||
help: tests positionals
|
||||
index: 1
|
||||
- positional2:
|
||||
help: tests positionals with exclusions
|
||||
index: 2
|
||||
default_value_if:
|
||||
- [flag, null, some]
|
||||
- [positional, other, something]
|
||||
- [flag, Null, some]
|
||||
- [postional, other, something]
|
||||
- flag:
|
||||
short: f
|
||||
long: flag
|
||||
multiple: true
|
||||
takes_value: true
|
||||
multiple_values: true
|
||||
help: tests flags
|
||||
global: true
|
||||
- flag2:
|
||||
|
@ -41,13 +36,11 @@ args:
|
|||
- option2:
|
||||
long: long-option-2
|
||||
help: tests long options with exclusions
|
||||
conflicts_with:
|
||||
- option
|
||||
requires:
|
||||
- positional2
|
||||
- option3:
|
||||
short: O
|
||||
long: option3
|
||||
long: Option
|
||||
help: tests options with specific value sets
|
||||
takes_value: true
|
||||
possible_values:
|
||||
|
@ -56,7 +49,6 @@ args:
|
|||
requires_if:
|
||||
- [fast, flag]
|
||||
- positional3:
|
||||
index: 3
|
||||
help: tests positionals with specific values
|
||||
possible_values: [ vi, emacs ]
|
||||
- multvals:
|
||||
|
@ -67,83 +59,49 @@ args:
|
|||
- two
|
||||
- multvalsmo:
|
||||
long: multvalsmo
|
||||
multiple_values: true
|
||||
multiple: true
|
||||
takes_value: true
|
||||
help: Tests multiple values, not mult occs
|
||||
value_names: [one, two]
|
||||
- multvalsdelim:
|
||||
long: multvalsdelim
|
||||
help: Tests multiple values with required delimiter
|
||||
multiple: true
|
||||
takes_value: true
|
||||
multiple_occurrences: true
|
||||
use_delimiter: true
|
||||
require_delimiter: true
|
||||
- settings:
|
||||
short: s
|
||||
takes_value: true
|
||||
multiple_values: true
|
||||
value_delimiter: ","
|
||||
- singlealias:
|
||||
long: singlealias
|
||||
help: Tests single alias
|
||||
aliases: [alias]
|
||||
required_if_eq:
|
||||
required_if:
|
||||
- [multvalsmo, two]
|
||||
- multaliases:
|
||||
long: multaliases
|
||||
help: Tests multiple aliases
|
||||
aliases: [als1, als2, als3]
|
||||
- singleshortalias:
|
||||
long: singleshortalias
|
||||
help: Tests single short alias
|
||||
short_aliases: [a]
|
||||
required_if_eq:
|
||||
- [multvalsmo, two]
|
||||
- multshortaliases:
|
||||
long: multshortaliases
|
||||
help: Tests multiple short aliases
|
||||
short_aliases: [b, c]
|
||||
- minvals2:
|
||||
long: minvals2
|
||||
multiple_values: true
|
||||
multiple: true
|
||||
takes_value: true
|
||||
help: Tests 2 min vals
|
||||
min_values: 2
|
||||
- maxvals3:
|
||||
long: maxvals3
|
||||
multiple_values: true
|
||||
multiple: true
|
||||
takes_value: true
|
||||
help: Tests 3 max vals
|
||||
max_values: 3
|
||||
- exclusive:
|
||||
long: exclusive
|
||||
help: Tests 3 exclusive
|
||||
exclusive: true
|
||||
- ignore_case:
|
||||
index: 4
|
||||
help: Test ignore case
|
||||
- case_insensitive:
|
||||
help: Test case_insensitive
|
||||
possible_values: [test123, test321]
|
||||
ignore_case: true
|
||||
- value_hint:
|
||||
long: value-hint
|
||||
help: Test value_hint
|
||||
value_hint: FilePath
|
||||
- verbose:
|
||||
short: v
|
||||
multiple_occurrences: true
|
||||
takes_value: false
|
||||
help: Sets the level of verbosity
|
||||
- visiblealiases:
|
||||
long: visiblealiases
|
||||
help: Tests visible aliases
|
||||
visible_alias: visals1
|
||||
visible_aliases: [visals2, visals2, visals3]
|
||||
- visibleshortaliases:
|
||||
long: visibleshortaliases
|
||||
help: Tests visible short aliases
|
||||
visible_short_alias: e
|
||||
visible_short_aliases: [l, m]
|
||||
groups:
|
||||
case_insensitive: true
|
||||
|
||||
arg_groups:
|
||||
- test:
|
||||
args:
|
||||
- maxvals3
|
||||
- minvals2
|
||||
- minmals2
|
||||
conflicts_with:
|
||||
- option3
|
||||
requires:
|
||||
|
@ -157,9 +115,8 @@ subcommands:
|
|||
- scoption:
|
||||
short: o
|
||||
long: option
|
||||
multiple_values: true
|
||||
multiple: true
|
||||
help: tests options
|
||||
takes_value: true
|
||||
- scpositional:
|
||||
help: tests positionals
|
||||
index: 1
|
11
tests/fixtures/app_2space.yaml
vendored
11
tests/fixtures/app_2space.yaml
vendored
|
@ -1,11 +0,0 @@
|
|||
name: claptests
|
||||
version: "1.0"
|
||||
about: tests clap library
|
||||
author: Kevin K. <kbknapp@gmail.com>
|
||||
args:
|
||||
- opt:
|
||||
short: o
|
||||
long: option
|
||||
takes_value: true
|
||||
multiple_values: true
|
||||
help: tests options
|
2
tests/fixtures/app_field_not_string.yaml
vendored
2
tests/fixtures/app_field_not_string.yaml
vendored
|
@ -1,2 +0,0 @@
|
|||
name: claptests
|
||||
1: "invalid"
|
9
tests/fixtures/app_regex.yaml
vendored
9
tests/fixtures/app_regex.yaml
vendored
|
@ -1,9 +0,0 @@
|
|||
name: clapregextest
|
||||
version: "1.0"
|
||||
about: tests clap regex functionality
|
||||
author: Benjamin Kästner <benjamin.kaestner@gmail.com>
|
||||
args:
|
||||
- filter:
|
||||
index: 1
|
||||
validator_regex: ["^*\\.[a-z]+$", expected extension pattern]
|
||||
help: file extension pattern
|
8
tests/fixtures/app_regex_invalid.yaml
vendored
8
tests/fixtures/app_regex_invalid.yaml
vendored
|
@ -1,8 +0,0 @@
|
|||
name: clapregextest
|
||||
version: "1.0"
|
||||
about: tests clap regex functionality
|
||||
author: Benjamin Kästner <benjamin.kaestner@gmail.com>
|
||||
args:
|
||||
- filter:
|
||||
index: 1
|
||||
validator_regex: [")", invalid regular expression]
|
5
tests/fixtures/app_setting_invalid.yaml
vendored
5
tests/fixtures/app_setting_invalid.yaml
vendored
|
@ -1,5 +0,0 @@
|
|||
name: claptests
|
||||
version: "1.0"
|
||||
about: tests clap extra fields
|
||||
settings:
|
||||
- random
|
2
tests/fixtures/arg_field_not_string.yaml
vendored
2
tests/fixtures/arg_field_not_string.yaml
vendored
|
@ -1,2 +0,0 @@
|
|||
claptest-arg:
|
||||
6: false
|
4
tests/fixtures/arg_not_hash.yaml
vendored
4
tests/fixtures/arg_not_hash.yaml
vendored
|
@ -1,4 +0,0 @@
|
|||
name: claptests
|
||||
args:
|
||||
- arg:
|
||||
short: a
|
8
tests/fixtures/arg_setting_invalid.yaml
vendored
8
tests/fixtures/arg_setting_invalid.yaml
vendored
|
@ -1,8 +0,0 @@
|
|||
name: claptests
|
||||
version: "1.0"
|
||||
about: tests clap extra fields
|
||||
args:
|
||||
- option:
|
||||
long: option
|
||||
settings:
|
||||
- random
|
10
tests/fixtures/extra_fields.yaml
vendored
10
tests/fixtures/extra_fields.yaml
vendored
|
@ -1,10 +0,0 @@
|
|||
_has_metadata: true
|
||||
name: claptests
|
||||
version: "1.0"
|
||||
about: tests clap extra fields
|
||||
random: This field is extra
|
||||
args:
|
||||
- option:
|
||||
_has_metadata: true
|
||||
long: option
|
||||
random: This field is extra
|
6
tests/fixtures/extra_fields_invalid_app.yaml
vendored
6
tests/fixtures/extra_fields_invalid_app.yaml
vendored
|
@ -1,6 +0,0 @@
|
|||
name: claptests
|
||||
version: "1.0"
|
||||
about: tests clap extra fields
|
||||
subcommands:
|
||||
- info:
|
||||
random: This field is extra
|
7
tests/fixtures/extra_fields_invalid_arg.yaml
vendored
7
tests/fixtures/extra_fields_invalid_arg.yaml
vendored
|
@ -1,7 +0,0 @@
|
|||
name: claptests
|
||||
version: "1.0"
|
||||
about: tests clap extra fields
|
||||
args:
|
||||
- option:
|
||||
long: option
|
||||
random: This field is extra
|
3
tests/fixtures/field_not_hash.yaml
vendored
3
tests/fixtures/field_not_hash.yaml
vendored
|
@ -1,3 +0,0 @@
|
|||
claptests:
|
||||
- 5
|
||||
- 6
|
21
tests/fixtures/multiple_groups.yaml
vendored
21
tests/fixtures/multiple_groups.yaml
vendored
|
@ -1,21 +0,0 @@
|
|||
name: app
|
||||
|
||||
args:
|
||||
- arg_1:
|
||||
short: a
|
||||
- arg_2:
|
||||
short: b
|
||||
- arg_3:
|
||||
short: c
|
||||
- arg_4:
|
||||
short: d
|
||||
|
||||
groups:
|
||||
- group_1:
|
||||
args:
|
||||
- arg_1
|
||||
- arg_2
|
||||
- group_2:
|
||||
args:
|
||||
- arg_3
|
||||
- arg_4
|
1
tests/fixtures/name_not_string.yaml
vendored
1
tests/fixtures/name_not_string.yaml
vendored
|
@ -1 +0,0 @@
|
|||
100: "claptests"
|
1
tests/fixtures/not_hash.yaml
vendored
1
tests/fixtures/not_hash.yaml
vendored
|
@ -1 +0,0 @@
|
|||
["clap", "tests"]
|
211
tests/macros.rs
211
tests/macros.rs
|
@ -9,7 +9,6 @@ fn basic() {
|
|||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@global_setting AllowNegativeNumbers)
|
||||
(@arg opt: -o --option +takes_value ... "tests options")
|
||||
(@arg positional: index(1) "tests positionals")
|
||||
(@arg flag: -f --flag ... +global "tests flags")
|
||||
|
@ -157,42 +156,6 @@ fn quoted_arg_name() {
|
|||
assert!(matches.is_present("option2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quoted_subcommand_name() {
|
||||
#![allow(deprecated)]
|
||||
clap::clap_app!(claptests =>
|
||||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@arg opt: -o --option +takes_value ... "tests options")
|
||||
(@arg positional: index(1) "tests positionals")
|
||||
(@arg flag: -f --flag ... +global "tests flags")
|
||||
(@arg flag2: -F conflicts_with[flag] requires[option2]
|
||||
"tests flags with exclusions")
|
||||
(@arg option2: --long_option_2 conflicts_with[option] requires[positional2]
|
||||
"tests long options with exclusions")
|
||||
(@arg positional2: index(2) "tests positionals with exclusions")
|
||||
(@arg option3: -O --Option +takes_value possible_value[fast slow]
|
||||
"tests options with specific value sets")
|
||||
(@arg positional3: index(3) ... possible_value[vi emacs]
|
||||
"tests positionals with specific values")
|
||||
(@arg multvals: --multvals +takes_value value_name[one two]
|
||||
"Tests multiple values, not mult occs")
|
||||
(@arg multvalsmo: --multvalsmo ... +takes_value value_name[one two]
|
||||
"Tests multiple values, not mult occs")
|
||||
(@arg minvals: --minvals2 min_values(1) ... +takes_value "Tests 2 min vals")
|
||||
(@arg maxvals: --maxvals3 ... +takes_value max_values(3) "Tests 3 max vals")
|
||||
(@subcommand subcmd =>
|
||||
(about: "tests subcommands")
|
||||
(version: "0.1")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@arg scoption: -o --option ... +takes_value "tests options")
|
||||
(@arg scpositional: index(1) "tests positionals"))
|
||||
(@subcommand ("other-subcmd") =>
|
||||
(about: "some other subcommand"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_macro() {
|
||||
#![allow(deprecated)]
|
||||
|
@ -200,7 +163,7 @@ fn group_macro() {
|
|||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty:
|
||||
(@group difficulty =>
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
|
@ -221,7 +184,7 @@ fn group_macro_set_multiple() {
|
|||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty: +multiple
|
||||
(@group difficulty +multiple =>
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
|
@ -244,7 +207,7 @@ fn group_macro_set_not_multiple() {
|
|||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty: !multiple
|
||||
(@group difficulty !multiple =>
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
|
@ -264,7 +227,7 @@ fn group_macro_set_required() {
|
|||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty: +required
|
||||
(@group difficulty +required =>
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
|
@ -284,7 +247,7 @@ fn group_macro_set_not_required() {
|
|||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty: !required
|
||||
(@group difficulty !required =>
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
|
@ -297,145 +260,6 @@ fn group_macro_set_not_required() {
|
|||
assert!(!matches.is_present("difficulty"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_macro_attributes_alternative() {
|
||||
#![allow(deprecated)]
|
||||
let app = clap::clap_app!(claptests =>
|
||||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty:
|
||||
(@attributes +multiple +required)
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
)
|
||||
);
|
||||
|
||||
let result = app
|
||||
.clone()
|
||||
.try_get_matches_from(vec!["bin_name", "--hard", "--easy"]);
|
||||
assert!(result.is_ok());
|
||||
let matches = result.expect("Expected to successfully match the given args.");
|
||||
assert!(matches.is_present("difficulty"));
|
||||
assert!(matches.is_present("hard"));
|
||||
assert!(matches.is_present("easy"));
|
||||
assert!(!matches.is_present("normal"));
|
||||
|
||||
let result = app.try_get_matches_from(vec!["bin_name"]);
|
||||
assert!(result.is_err());
|
||||
let err = result.unwrap_err();
|
||||
assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_macro_multiple_methods() {
|
||||
#![allow(deprecated)]
|
||||
let app = clap::clap_app!(claptests =>
|
||||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty: +multiple +required
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
)
|
||||
);
|
||||
|
||||
let result = app
|
||||
.clone()
|
||||
.try_get_matches_from(vec!["bin_name", "--hard", "--easy"]);
|
||||
assert!(result.is_ok());
|
||||
let matches = result.expect("Expected to successfully match the given args.");
|
||||
assert!(matches.is_present("difficulty"));
|
||||
assert!(matches.is_present("hard"));
|
||||
assert!(matches.is_present("easy"));
|
||||
assert!(!matches.is_present("normal"));
|
||||
|
||||
let result = app.try_get_matches_from(vec!["bin_name"]);
|
||||
assert!(result.is_err());
|
||||
let err = result.unwrap_err();
|
||||
assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_macro_multiple_methods_alternative() {
|
||||
#![allow(deprecated)]
|
||||
let app = clap::clap_app!(claptests =>
|
||||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty: * ...
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
)
|
||||
);
|
||||
|
||||
let result = app
|
||||
.clone()
|
||||
.try_get_matches_from(vec!["bin_name", "--hard", "--easy"]);
|
||||
assert!(result.is_ok());
|
||||
let matches = result.expect("Expected to successfully match the given args.");
|
||||
assert!(matches.is_present("difficulty"));
|
||||
assert!(matches.is_present("hard"));
|
||||
assert!(matches.is_present("easy"));
|
||||
assert!(!matches.is_present("normal"));
|
||||
|
||||
let result = app.try_get_matches_from(vec!["bin_name"]);
|
||||
assert!(result.is_err());
|
||||
let err = result.unwrap_err();
|
||||
assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_macro_multiple_invocations() {
|
||||
#![allow(deprecated)]
|
||||
let app = clap::clap_app!(claptests =>
|
||||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@arg foo: --foo)
|
||||
(@arg bar: --bar)
|
||||
(@group difficulty: conflicts_with[foo bar]
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
)
|
||||
);
|
||||
|
||||
let result = app
|
||||
.clone()
|
||||
.try_get_matches_from(vec!["bin_name", "--hard", "--foo"]);
|
||||
assert!(result.is_err());
|
||||
let err = result.unwrap_err();
|
||||
assert_eq!(err.kind, ErrorKind::ArgumentConflict);
|
||||
|
||||
let result = app.try_get_matches_from(vec!["bin_name", "--hard", "--bar"]);
|
||||
assert!(result.is_err());
|
||||
let err = result.unwrap_err();
|
||||
assert_eq!(err.kind, ErrorKind::ArgumentConflict);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn literals() {
|
||||
#![allow(deprecated)]
|
||||
clap::clap_app!("clap-tests" =>
|
||||
(version: "0.1")
|
||||
(@arg "task-num": -"t-n" --"task-num" +takes_value possible_value["all" 0 1 2]
|
||||
"Task number")
|
||||
(@group priority:
|
||||
(@arg "4": -4 --4 "Sets priority to 4")
|
||||
(@arg ("5"): -('5') --5 "Sets priority to 5")
|
||||
(@arg 6: -6 --6 "Sets priority to 6")
|
||||
)
|
||||
(@subcommand "view-tasks" =>
|
||||
(about: "View all tasks"))
|
||||
(@subcommand 0 =>
|
||||
(about: "Set everything to zero priority"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiarg() {
|
||||
#![allow(deprecated)]
|
||||
|
@ -465,31 +289,6 @@ fn multiarg() {
|
|||
assert_eq!(matches.value_of("multiarg2"), Some("flag-set"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validator() {
|
||||
#![allow(deprecated)]
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
fn validate(val: &str) -> Result<u32, String> {
|
||||
val.parse::<u32>().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
let app = clap::clap_app!(claptests =>
|
||||
(@arg inline: { |val| val.parse::<u16>() })
|
||||
(@arg func1: { validate })
|
||||
(@arg func2: { u64::from_str })
|
||||
);
|
||||
|
||||
let matches = app
|
||||
.try_get_matches_from(&["bin", "12", "34", "56"])
|
||||
.expect("match failed");
|
||||
|
||||
assert_eq!(matches.value_of_t::<u16>("inline").ok(), Some(12));
|
||||
assert_eq!(matches.value_of_t::<u16>("func1").ok(), Some(34));
|
||||
assert_eq!(matches.value_of_t::<u16>("func2").ok(), Some(56));
|
||||
}
|
||||
|
||||
mod arg {
|
||||
#[test]
|
||||
fn name_explicit() {
|
||||
|
|
254
tests/yaml.rs
254
tests/yaml.rs
|
@ -1,268 +1,38 @@
|
|||
#![cfg(feature = "yaml")]
|
||||
#![allow(deprecated)]
|
||||
|
||||
use clap::{load_yaml, App, Arg, ErrorKind, ValueHint};
|
||||
use clap::{load_yaml, App};
|
||||
|
||||
#[test]
|
||||
fn create_app_from_yaml() {
|
||||
let yaml = load_yaml!("fixtures/app.yaml");
|
||||
let _ = App::from_yaml(yaml);
|
||||
let yml = load_yaml!("app.yml");
|
||||
App::from_yaml(yml);
|
||||
}
|
||||
|
||||
// TODO: Uncomment to test yaml with 2 spaces https://github.com/chyh1990/yaml-rust/issues/101
|
||||
// #[test]
|
||||
// fn create_app_from_yaml_2spaces() {
|
||||
// let yaml = load_yaml!("fixtures/app_2space.yaml");
|
||||
// App::from_yaml(yaml);
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn help_message() {
|
||||
let yaml = load_yaml!("fixtures/app.yaml");
|
||||
let mut app = App::from_yaml(yaml);
|
||||
let yml = load_yaml!("app.yml");
|
||||
let mut app = App::from_yaml(yml);
|
||||
// Generate the full help message!
|
||||
let _ = app.try_get_matches_from_mut(Vec::<String>::new());
|
||||
let _ = app.get_matches_from_safe_borrow(Vec::<String>::new());
|
||||
|
||||
let mut help_buffer = Vec::new();
|
||||
app.write_help(&mut help_buffer).unwrap();
|
||||
let help_string = String::from_utf8(help_buffer).unwrap();
|
||||
println!("{}", help_string);
|
||||
assert!(help_string
|
||||
.contains("-h, --help\n prints help with a nonstandard description\n"));
|
||||
println!("{}", &help_string);
|
||||
assert!(help_string.contains("tests positionals with exclusions\n"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn author() {
|
||||
let yaml = load_yaml!("fixtures/app.yaml");
|
||||
let mut app = App::from_yaml(yaml);
|
||||
let yml = load_yaml!("app.yml");
|
||||
let mut app = App::from_yaml(yml);
|
||||
// Generate the full help message!
|
||||
let _ = app.try_get_matches_from_mut(Vec::<String>::new());
|
||||
let _ = app.get_matches_from_safe_borrow(Vec::<String>::new());
|
||||
|
||||
let mut help_buffer = Vec::new();
|
||||
app.write_help(&mut help_buffer).unwrap();
|
||||
let help_string = String::from_utf8(help_buffer).unwrap();
|
||||
println!("{}", &help_string);
|
||||
assert!(help_string.contains("Kevin K. <kbknapp@gmail.com>"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_settings() {
|
||||
let yaml = load_yaml!("fixtures/app.yaml");
|
||||
let app = App::from_yaml(yaml);
|
||||
|
||||
let m = app.try_get_matches_from(vec!["prog"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(
|
||||
m.unwrap_err().kind,
|
||||
ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Unknown AppSetting 'random' found in YAML file for app"]
|
||||
fn app_setting_invalid() {
|
||||
let yaml = load_yaml!("fixtures/app_setting_invalid.yaml");
|
||||
let _ = App::from_yaml(yaml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Unknown ArgSetting 'random' found in YAML file for arg 'option'"]
|
||||
fn arg_setting_invalid() {
|
||||
let yaml = load_yaml!("fixtures/arg_setting_invalid.yaml");
|
||||
let _ = App::from_yaml(yaml);
|
||||
}
|
||||
|
||||
// ValueHint must be parsed correctly from Yaml
|
||||
#[test]
|
||||
fn value_hint() {
|
||||
let yml = load_yaml!("fixtures/app.yaml");
|
||||
let app = App::from_yaml(yml);
|
||||
|
||||
let arg = app
|
||||
.get_arguments()
|
||||
.find(|a| a.get_name() == "value_hint")
|
||||
.unwrap();
|
||||
assert_eq!(arg.get_value_hint(), ValueHint::FilePath);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_value_if_not_triggered_by_argument() {
|
||||
let yml = load_yaml!("fixtures/app.yaml");
|
||||
let app = App::from_yaml(yml);
|
||||
|
||||
// Fixtures use "other" as value
|
||||
let matches = app.try_get_matches_from(vec!["prog", "wrong"]).unwrap();
|
||||
|
||||
assert!(matches.value_of("positional2").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_value_if_triggered_by_matching_argument() {
|
||||
let yml = load_yaml!("fixtures/app.yaml");
|
||||
let app = App::from_yaml(yml);
|
||||
|
||||
let matches = app.try_get_matches_from(vec!["prog", "other"]).unwrap();
|
||||
assert_eq!(matches.value_of("positional2").unwrap(), "something");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_value_if_triggered_by_flag() {
|
||||
let yml = load_yaml!("fixtures/app.yaml");
|
||||
let app = App::from_yaml(yml);
|
||||
|
||||
let matches = app
|
||||
.try_get_matches_from(vec!["prog", "--flag", "flagvalue"])
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(matches.value_of("positional2").unwrap(), "some");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_value_if_triggered_by_flag_and_argument() {
|
||||
let yml = load_yaml!("fixtures/app.yaml");
|
||||
let app = App::from_yaml(yml);
|
||||
|
||||
let matches = app
|
||||
.try_get_matches_from(vec!["prog", "--flag", "flagvalue", "other"])
|
||||
.unwrap();
|
||||
|
||||
// First condition triggers, therefore "some"
|
||||
assert_eq!(matches.value_of("positional2").unwrap(), "some");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yaml_multiple_occurrences() {
|
||||
let yaml = load_yaml!("fixtures/app.yaml");
|
||||
let matches = App::from_yaml(yaml)
|
||||
.try_get_matches_from(vec!["prog", "-vvv"])
|
||||
.unwrap();
|
||||
assert_eq!(matches.occurrences_of("verbose"), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yaml_multiple_values() {
|
||||
let yaml = load_yaml!("fixtures/app.yaml");
|
||||
let matches = App::from_yaml(yaml)
|
||||
.try_get_matches_from(vec!["prog", "-s", "aaa", "bbb"])
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
matches
|
||||
.values_of("settings")
|
||||
.unwrap()
|
||||
.collect::<Vec<&str>>(),
|
||||
vec!["aaa", "bbb"]
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "regex")]
|
||||
#[test]
|
||||
fn regex_with_invalid_string() {
|
||||
let yml = load_yaml!("fixtures/app_regex.yaml");
|
||||
let app = App::from_yaml(yml);
|
||||
let res = app.try_get_matches_from(vec!["prog", "not a proper filter"]);
|
||||
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
#[cfg(feature = "regex")]
|
||||
#[test]
|
||||
fn regex_with_valid_string() {
|
||||
let yml = load_yaml!("fixtures/app_regex.yaml");
|
||||
let app = App::from_yaml(yml);
|
||||
|
||||
let matches = app.try_get_matches_from(vec!["prog", "*.txt"]).unwrap();
|
||||
|
||||
assert_eq!(matches.value_of("filter").unwrap(), "*.txt");
|
||||
}
|
||||
|
||||
#[cfg(feature = "regex")]
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn regex_with_invalid_yaml() {
|
||||
let yml = load_yaml!("fixtures/app_regex_invalid.yaml");
|
||||
let _ = App::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extra_fields() {
|
||||
let yml = load_yaml!("fixtures/extra_fields.yaml");
|
||||
let _ = App::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Unknown setting 'random' in YAML file for arg 'option'"]
|
||||
fn extra_fields_invalid_arg() {
|
||||
let yml = load_yaml!("fixtures/extra_fields_invalid_arg.yaml");
|
||||
let _ = App::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Unknown setting 'random' in YAML file for subcommand 'info'"]
|
||||
fn extra_fields_invalid_app() {
|
||||
let yml = load_yaml!("fixtures/extra_fields_invalid_app.yaml");
|
||||
let _ = App::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "YAML file must be a hash"]
|
||||
fn app_not_hash() {
|
||||
let yml = load_yaml!("fixtures/not_hash.yaml");
|
||||
let _ = App::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "YAML file must be a hash"]
|
||||
fn arg_file_not_hash() {
|
||||
let yml = load_yaml!("fixtures/not_hash.yaml");
|
||||
let _ = Arg::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Subcommand must be a hash"]
|
||||
fn subcommand_not_hash() {
|
||||
let yml = load_yaml!("fixtures/field_not_hash.yaml");
|
||||
let _ = App::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Arg must be a hash"]
|
||||
fn arg_not_hash() {
|
||||
let yml = load_yaml!("fixtures/arg_not_hash.yaml");
|
||||
let _ = App::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Subcommand name must be a string"]
|
||||
fn subcommand_name_not_string() {
|
||||
let yml = load_yaml!("fixtures/name_not_string.yaml");
|
||||
let _ = App::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Arg name must be a string"]
|
||||
fn arg_name_not_string() {
|
||||
let yml = load_yaml!("fixtures/name_not_string.yaml");
|
||||
let _ = Arg::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "App fields must be strings"]
|
||||
fn app_field_not_string() {
|
||||
let yml = load_yaml!("fixtures/app_field_not_string.yaml");
|
||||
let _ = App::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Arg fields must be strings"]
|
||||
fn arg_field_not_string() {
|
||||
let yml = load_yaml!("fixtures/arg_field_not_string.yaml");
|
||||
let _ = Arg::from_yaml(yml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_groups() {
|
||||
let yml = load_yaml!("fixtures/multiple_groups.yaml");
|
||||
let matches = App::from_yaml(yml).try_get_matches_from(&["app", "-a", "-c"]);
|
||||
eprintln!("{:?}", matches);
|
||||
assert!(matches.is_ok());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue