Merge pull request #3963 from epage/deprecated

fix!: Remove deprecated APIs
This commit is contained in:
Ed Page 2022-07-21 19:22:15 -05:00 committed by GitHub
commit 017b87abb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
139 changed files with 291 additions and 28541 deletions

28
Cargo.lock generated
View file

@ -17,15 +17,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
@ -138,7 +129,6 @@ dependencies = [
"humantime",
"indexmap",
"once_cell",
"regex",
"rustversion",
"shlex",
"snapbox",
@ -150,7 +140,6 @@ dependencies = [
"trybuild",
"trycmd",
"unicase",
"yaml-rust",
]
[[package]]
@ -494,12 +483,6 @@ version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "log"
version = "0.4.17"
@ -722,8 +705,6 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
@ -1124,15 +1105,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]
[[package]]
name = "yansi"
version = "0.5.1"

View file

@ -60,7 +60,7 @@ default = [
"suggestions",
]
debug = ["clap_derive/debug", "backtrace"] # Enables debug messages
unstable-doc = ["derive", "cargo", "wrap_help", "yaml", "env", "unicode", "regex", "unstable-replace", "unstable-grouped"] # for docs.rs
unstable-doc = ["derive", "cargo", "wrap_help", "env", "unicode", "unstable-replace", "unstable-grouped"] # for docs.rs
# Used in default
std = ["indexmap/std"] # support for no_std in a backwards-compatible way
@ -73,7 +73,6 @@ deprecated = ["clap_derive/deprecated"] # Guided experience to prepare for next
derive = ["clap_derive", "once_cell"]
cargo = ["once_cell"] # Disable if you're not using Cargo, enables Cargo-env-var-dependent macros
wrap_help = ["terminal_size", "textwrap/terminal_size"]
yaml = ["yaml-rust"]
env = [] # Use environment variables during arg parsing
unicode = ["textwrap/unicode-width", "unicase"] # Support for unicode characters in arguments and help messages
@ -94,16 +93,13 @@ textwrap = { version = "0.15.0", default-features = false, features = [] }
unicase = { version = "2.6", optional = true }
indexmap = "1.0"
strsim = { version = "0.10", optional = true }
yaml-rust = { version = "0.4.1", optional = true }
atty = { version = "0.2", optional = true }
termcolor = { version = "1.1.1", optional = true }
terminal_size = { version = "0.1.12", optional = true }
regex = { version = "1.0", optional = true }
backtrace = { version = "0.3", optional = true }
once_cell = { version = "1.12.0", optional = true }
[dev-dependencies]
regex = "1.0"
trybuild = "1.0.18"
rustversion = "1"
# Cutting out `filesystem` feature

View file

@ -15,8 +15,8 @@ MSRV?=1.56.1
_FEATURES = minimal default wasm full debug release
_FEATURES_minimal = --no-default-features --features "std"
_FEATURES_default =
_FEATURES_wasm = --features "deprecated derive cargo env unicode yaml regex unstable-replace unstable-grouped"
_FEATURES_full = --features "deprecated derive cargo env unicode yaml regex unstable-replace unstable-grouped wrap_help"
_FEATURES_wasm = --features "deprecated derive cargo env unicode unstable-replace unstable-grouped"
_FEATURES_full = --features "deprecated derive cargo env unicode unstable-replace unstable-grouped wrap_help"
_FEATURES_next = ${_FEATURES_full} --features unstable-v4
_FEATURES_debug = ${_FEATURES_full} --features debug
_FEATURES_release = ${_FEATURES_full} --release

View file

@ -224,7 +224,7 @@ complete OPTIONS -F _clap_complete_NAME EXECUTABLES
Menu,
}
impl clap::ArgEnum for CompType {
impl clap::ValueEnum for CompType {
fn value_variants<'a>() -> &'a [Self] {
&[
Self::Normal,

View file

@ -128,13 +128,8 @@ pub fn flags<'help>(p: &Command<'help>) -> Vec<Arg<'help>> {
/// Get the possible values for completion
pub fn possible_values<'help>(a: &Arg<'help>) -> Option<Vec<clap::PossibleValue<'help>>> {
#![allow(deprecated)]
if !a.is_takes_value_set() {
None
} else if let Some(pvs) = a.get_possible_values() {
// Check old first in case the user explicitly set possible values and the derive inferred
// a `ValueParser` with some.
Some(pvs.to_vec())
} else {
a.get_value_parser()
.possible_values()

View file

@ -1,7 +1,7 @@
use std::fmt::Display;
use std::str::FromStr;
use clap::{ArgEnum, PossibleValue};
use clap::{PossibleValue, ValueEnum};
use crate::shells;
use crate::Generator;
@ -22,16 +22,6 @@ pub enum Shell {
Zsh,
}
impl Shell {
/// Deprecated, replaced with [`EnumValueParser`][clap::builder::EnumValueParser]
#[deprecated(since = "3.2.0", note = "Replaced with `EnumValueParser`")]
pub fn possible_values() -> impl Iterator<Item = PossibleValue<'static>> {
Shell::value_variants()
.iter()
.filter_map(ArgEnum::to_possible_value)
}
}
impl Display for Shell {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.to_possible_value()
@ -55,7 +45,7 @@ impl FromStr for Shell {
}
// Hand-rolled so it can work even when `derive` feature is disabled
impl ArgEnum for Shell {
impl ValueEnum for Shell {
fn value_variants<'a>() -> &'a [Self] {
&[
Shell::Bash,

View file

@ -56,14 +56,13 @@ pub fn gen_for_struct(
clippy::suspicious_else_formatting,
)]
#[deny(clippy::correctness)]
#[allow(deprecated)]
impl #impl_generics clap::CommandFactory for #struct_name #ty_generics #where_clause {
fn into_app<'b>() -> clap::Command<'b> {
fn command<'b>() -> clap::Command<'b> {
let #app_var = clap::Command::new(#name);
<Self as clap::Args>::augment_args(#app_var)
}
fn into_app_for_update<'b>() -> clap::Command<'b> {
fn command_for_update<'b>() -> clap::Command<'b> {
let #app_var = clap::Command::new(#name);
<Self as clap::Args>::augment_args_for_update(#app_var)
}
@ -103,14 +102,14 @@ pub fn gen_for_enum(enum_name: &Ident, generics: &Generics, attrs: &[Attribute])
)]
#[deny(clippy::correctness)]
impl #impl_generics clap::CommandFactory for #enum_name #ty_generics #where_clause {
fn into_app<'b>() -> clap::Command<'b> {
fn command<'b>() -> clap::Command<'b> {
#[allow(deprecated)]
let #app_var = clap::Command::new(#name)
.setting(clap::AppSettings::SubcommandRequiredElseHelp);
<Self as clap::Subcommand>::augment_subcommands(#app_var)
}
fn into_app_for_update<'b>() -> clap::Command<'b> {
fn command_for_update<'b>() -> clap::Command<'b> {
let #app_var = clap::Command::new(#name);
<Self as clap::Subcommand>::augment_subcommands_for_update(#app_var)
}

View file

@ -18,12 +18,11 @@ pub fn parser_enum(name: &Ident) {
pub fn into_app(name: &Ident) {
append_dummy(quote! {
#[allow(deprecated)]
impl clap::CommandFactory for #name {
fn into_app<'b>() -> clap::Command<'b> {
fn command<'b>() -> clap::Command<'b> {
unimplemented!()
}
fn into_app_for_update<'b>() -> clap::Command<'b> {
fn command_for_update<'b>() -> clap::Command<'b> {
unimplemented!()
}
}

View file

@ -1,4 +1,4 @@
See the documentation for [`Command::multicall`][crate::App::multicall] for rationale.
See the documentation for [`Command::multicall`][crate::Command::multicall] for rationale.
This example omits every command except true and false,
which are the most trivial to implement,

View file

@ -1,4 +1,4 @@
See the documentation for [`Command::multicall`][crate::App::multicall] for rationale.
See the documentation for [`Command::multicall`][crate::Command::multicall] for rationale.
This example omits the implementation of displaying address config

View file

@ -199,7 +199,7 @@
//!
//! clap reports most development errors as `debug_assert!`s. Rather than checking every
//! subcommand, you should have a test that calls
//! [`Command::debug_assert`][crate::App::debug_assert]:
//! [`Command::debug_assert`][crate::Command::debug_assert]:
//! ```rust,no_run
#![doc = include_str!("../../examples/tutorial_derive/05_01_assert.rs")]
//! ```

View file

@ -137,25 +137,25 @@
//! - e.g. `#[clap(arg_required_else_help(true))]` would translate to `cmd.arg_required_else_help(true)`
//!
//! **Magic attributes:**
//! - `name = <expr>`: [`Command::name`][crate::App::name]
//! - `name = <expr>`: [`Command::name`][crate::Command::name]
//! - When not present: [crate `name`](https://doc.rust-lang.org/cargo/reference/manifest.html#the-name-field) (if on [`Parser`][crate::Parser] container), variant name (if on [`Subcommand`][crate::Subcommand] variant)
//! - `version [= <expr>]`: [`Command::version`][crate::App::version]
//! - `version [= <expr>]`: [`Command::version`][crate::Command::version]
//! - When not present: no version set
//! - Without `<expr>`: defaults to [crate `version`](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field)
//! - `author [= <expr>]`: [`Command::author`][crate::App::author]
//! - `author [= <expr>]`: [`Command::author`][crate::Command::author]
//! - When not present: no author set
//! - Without `<expr>`: defaults to [crate `authors`](https://doc.rust-lang.org/cargo/reference/manifest.html#the-authors-field)
//! - `about [= <expr>]`: [`Command::about`][crate::App::about]
//! - `about [= <expr>]`: [`Command::about`][crate::Command::about]
//! - When not present: [Doc comment summary](#doc-comments)
//! - Without `<expr>`: [crate `description`](https://doc.rust-lang.org/cargo/reference/manifest.html#the-description-field) ([`Parser`][crate::Parser] container)
//! - **TIP:** When a doc comment is also present, you most likely want to add
//! `#[clap(long_about = None)]` to clear the doc comment so only [`about`][crate::App::about]
//! `#[clap(long_about = None)]` to clear the doc comment so only [`about`][crate::Command::about]
//! gets shown with both `-h` and `--help`.
//! - `long_about = <expr>`: [`Command::long_about`][crate::App::long_about]
//! - `long_about = <expr>`: [`Command::long_about`][crate::Command::long_about]
//! - When not present: [Doc comment](#doc-comments) if there is a blank line, else nothing
//! - `verbatim_doc_comment`: Minimizes pre-processing when converting doc comments to [`about`][crate::App::about] / [`long_about`][crate::App::long_about]
//! - `next_display_order`: [`Command::next_display_order`][crate::App::next_display_order]
//! - `next_help_heading`: [`Command::next_help_heading`][crate::App::next_help_heading]
//! - `verbatim_doc_comment`: Minimizes pre-processing when converting doc comments to [`about`][crate::Command::about] / [`long_about`][crate::Command::long_about]
//! - `next_display_order`: [`Command::next_display_order`][crate::Command::next_display_order]
//! - `next_help_heading`: [`Command::next_help_heading`][crate::Command::next_help_heading]
//! - When `flatten`ing [`Args`][crate::Args], this is scoped to just the args in this struct and any struct `flatten`ed into it
//! - `rename_all = <string_literal>`: Override default field / variant name case conversion for [`Command::name`][crate::Command::name] / [`Arg::id`][crate::Arg::id]
//! - When not present: `"kebab-case"`
@ -170,7 +170,7 @@
//! [`Subcommand`][crate::Subcommand])
//! - `subcommand`: Nest subcommands under the current set of subcommands (must implement
//! [`Subcommand`][crate::Subcommand])
//! - `external_subcommand`: [`Command::allow_external_subcommand(true)`][crate::App::allow_external_subcommands]
//! - `external_subcommand`: [`Command::allow_external_subcommand(true)`][crate::Command::allow_external_subcommands]
//! - Variant must be either `Variant(Vec<String>)` or `Variant(Vec<OsString>)`
//!
//! ### Arg Attributes
@ -216,7 +216,7 @@
//! [`Subcommand`][crate::Subcommand])
//! - When `Option<T>`, the subcommand becomes optional
//! - `from_global`: Read a [`Arg::global`][crate::Arg::global] argument (raw attribute), regardless of what subcommand you are in
//! - `parse(<kind> [= <function>])`: [`Arg::validator`][crate::Arg::validator] and [`ArgMatches::values_of_t`][crate::ArgMatches::values_of_t]
//! - `parse(<kind> [= <function>])`: `Arg::validator` and `ArgMatches::values_of_t`
//! - **Deprecated:**
//! - Use `value_parser(...)` for `from_str`, `try_from_str`, `from_os_str`, and `try_from_os_str`
//! - Use `action(ArgAction::Count` for `from_occurrences`
@ -305,7 +305,7 @@
//! ## Doc Comments
//!
//! In clap, help messages for the whole binary can be specified
//! via [`Command::about`][crate::App::about] and [`Command::long_about`][crate::App::long_about] while help messages
//! via [`Command::about`][crate::Command::about] and [`Command::long_about`][crate::Command::long_about] while help messages
//! for individual arguments can be specified via [`Arg::help`][crate::Arg::help] and [`Arg::long_help`][crate::Arg::long_help].
//!
//! `long_*` variants are used when user calls the program with
@ -488,7 +488,7 @@
//! [`CommandFactory::command`][crate::CommandFactory::command] (implemented when deriving
//! [`Parser`][crate::Parser])
//! - Proactively check for bad [`Command`][crate::Command] configurations by calling
//! [`Command::debug_assert`][crate::App::debug_assert] in a test
//! [`Command::debug_assert`][crate::Command::debug_assert] in a test
//! ([example](../tutorial_derive/05_01_assert.rs))
pub mod _tutorial;

View file

@ -14,7 +14,6 @@
//! * **derive**: Enables the custom derive (i.e. `#[derive(Parser)]`). Without this you must use one of the other methods of creating a `clap` CLI listed above.
//! * **cargo**: Turns on macros that read values from [`CARGO_*` environment variables](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates).
//! * **env**: Turns on the usage of environment variables during parsing.
//! * **regex**: Enables regex validators.
//! * **unicode**: Turns on support for unicode characters (including emoji) in arguments and help messages.
//! * **wrap_help**: Turns on the help text wrapping feature, based on the terminal size.
//!

View file

@ -198,7 +198,7 @@
//!
//! clap reports most development errors as `debug_assert!`s. Rather than checking every
//! subcommand, you should have a test that calls
//! [`Command::debug_assert`][crate::App::debug_assert]:
//! [`Command::debug_assert`][crate::Command::debug_assert]:
//! ```rust,no_run
#![doc = include_str!("../examples/tutorial_builder/05_01_assert.rs")]
//! ```

View file

@ -196,9 +196,9 @@ pub enum ArgAction {
/// );
/// ```
Count,
/// When encountered, display [`Command::print_help`][super::App::print_help]
/// When encountered, display [`Command::print_help`][super::Command::print_help]
///
/// Depending on the flag, [`Command::print_long_help`][super::App::print_long_help] may be shown
/// Depending on the flag, [`Command::print_long_help`][super::Command::print_long_help] may be shown
///
/// # Examples
///
@ -221,9 +221,9 @@ pub enum ArgAction {
/// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp);
/// ```
Help,
/// When encountered, display [`Command::version`][super::App::version]
/// When encountered, display [`Command::version`][super::Command::version]
///
/// Depending on the flag, [`Command::long_version`][super::App::long_version] may be shown
/// Depending on the flag, [`Command::long_version`][super::Command::long_version] may be shown
///
/// # Examples
///

View file

@ -2,8 +2,6 @@
// Std
use std::ops::BitOr;
#[cfg(feature = "yaml")]
use std::str::FromStr;
#[allow(unused)]
use crate::Arg;
@ -39,46 +37,6 @@ pub enum AppSettings {
)]
IgnoreErrors,
/// Deprecated, replace
/// ```rust,no_run
/// let cmd = clap::Command::new("cmd")
/// .global_setting(clap::AppSettings::WaitOnError)
/// .arg(clap::arg!(--flag));
/// let m = cmd.get_matches();
/// ```
/// with
/// ```rust
/// let cmd = clap::Command::new("cmd")
/// .arg(clap::arg!(--flag));
/// let m = match cmd.try_get_matches() {
/// Ok(m) => m,
/// Err(err) => {
/// if err.use_stderr() {
/// let _ = err.print();
///
/// eprintln!("\nPress [ENTER] / [RETURN] to continue...");
/// use std::io::BufRead;
/// let mut s = String::new();
/// let i = std::io::stdin();
/// i.lock().read_line(&mut s).unwrap();
///
/// std::process::exit(2);
/// } else {
/// let _ = err.print();
/// std::process::exit(0);
/// }
/// }
/// };
/// ```
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "See documentation for how to hand-implement this"
)
)]
WaitOnError,
/// Deprecated, replaced with [`Command::allow_hyphen_values`] and
/// [`Arg::is_allow_hyphen_values_set`]
#[cfg_attr(
@ -101,13 +59,6 @@ pub enum AppSettings {
)]
AllowNegativeNumbers,
/// Deprecated, replaced with [`Command::args_override_self`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.1.0", note = "Replaced with `Command::args_override_self`")
)]
AllArgsOverrideSelf,
/// Deprecated, replaced with [`Command::allow_missing_positional`] and
/// [`Command::is_allow_missing_positional_set`]
#[cfg_attr(
@ -400,41 +351,6 @@ pub enum AppSettings {
)]
NoAutoVersion,
/// Deprecated, replaced with [`Command::allow_hyphen_values`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `Command::allow_hyphen_values`")
)]
#[doc(hidden)]
AllowLeadingHyphen,
/// Deprecated, replaced with [`Command::allow_invalid_utf8_for_external_subcommands`] and [`Command::is_allow_invalid_utf8_for_external_subcommands_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Replaced with `Command::allow_invalid_utf8_for_external_subcommands` and `Command::is_allow_invalid_utf8_for_external_subcommands_set`"
)
)]
#[doc(hidden)]
StrictUtf8,
/// Deprecated, this is now the default
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "This is now the default")
)]
#[doc(hidden)]
UnifiedHelpMessage,
/// Deprecated, this is now the default
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "This is now the default")
)]
#[doc(hidden)]
ColoredHelp,
/// Deprecated, see [`Command::color`][crate::Command::color]
#[cfg_attr(
feature = "deprecated",
@ -459,60 +375,6 @@ pub enum AppSettings {
#[doc(hidden)]
ColorNever,
/// Deprecated, replaced with [`Command::disable_help_flag`] and [`Command::is_disable_help_flag_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Replaced with `Command::disable_help_flag` and `Command::is_disable_help_flag_set`"
)
)]
#[doc(hidden)]
DisableHelpFlags,
/// Deprecated, replaced with [`Command::disable_version_flag`] and
/// [`Command::is_disable_version_flag_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Replaced with `Command::disable_version_flag` and `Command::is_disable_version_flag_set`"
)
)]
#[doc(hidden)]
DisableVersion,
/// Deprecated, replaced with [`Command::propagate_version`] and [`Command::is_propagate_version_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Replaced with `Command::propagate_version` and `Command::is_propagate_version_set`"
)
)]
#[doc(hidden)]
GlobalVersion,
/// Deprecated, replaced with [`Command::hide_possible_values`] and
/// [`Arg::is_hide_possible_values_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Replaced with `Command::hide_possible_values` and `Arg::is_hide_possible_values_set`"
)
)]
#[doc(hidden)]
HidePossibleValuesInHelp,
/// Deprecated, this is now the default
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "This is now the default")
)]
#[doc(hidden)]
UnifiedHelp,
/// If the cmd is already built, used for caching.
#[doc(hidden)]
Built,
@ -560,7 +422,6 @@ bitflags! {
const VALID_ARG_FOUND = 1 << 35;
const INFER_SUBCOMMANDS = 1 << 36;
const CONTAINS_LAST = 1 << 37;
const ARGS_OVERRIDE_SELF = 1 << 38;
const HELP_REQUIRED = 1 << 39;
const SUBCOMMAND_PRECEDENCE_OVER_ARG = 1 << 40;
const DISABLE_HELP_FLAG = 1 << 41;
@ -581,22 +442,14 @@ impl_settings! { AppSettings, AppFlags,
=> Flags::ARGS_NEGATE_SCS,
AllowExternalSubcommands
=> Flags::ALLOW_UNK_SC,
StrictUtf8
=> Flags::NO_OP,
AllowInvalidUtf8ForExternalSubcommands
=> Flags::SC_UTF8_NONE,
AllowHyphenValues
=> Flags::LEADING_HYPHEN,
AllowLeadingHyphen
=> Flags::LEADING_HYPHEN,
AllowNegativeNumbers
=> Flags::ALLOW_NEG_NUMS,
AllowMissingPositional
=> Flags::ALLOW_MISSING_POS,
UnifiedHelpMessage
=> Flags::NO_OP,
ColoredHelp
=> Flags::NO_OP,
ColorAlways
=> Flags::COLOR_ALWAYS,
ColorAuto
@ -615,20 +468,12 @@ impl_settings! { AppSettings, AppFlags,
=> Flags::DISABLE_HELP_SC,
DisableHelpFlag
=> Flags::DISABLE_HELP_FLAG,
DisableHelpFlags
=> Flags::DISABLE_HELP_FLAG,
DisableVersionFlag
=> Flags::DISABLE_VERSION_FLAG,
DisableVersion
=> Flags::DISABLE_VERSION_FLAG,
PropagateVersion
=> Flags::PROPAGATE_VERSION,
GlobalVersion
=> Flags::PROPAGATE_VERSION,
HidePossibleValues
=> Flags::NO_POS_VALUES,
HidePossibleValuesInHelp
=> Flags::NO_POS_VALUES,
HelpExpected
=> Flags::HELP_REQUIRED,
Hidden
@ -651,214 +496,16 @@ impl_settings! { AppSettings, AppFlags,
=> Flags::USE_LONG_FORMAT_FOR_HELP_SC,
TrailingVarArg
=> Flags::TRAILING_VARARG,
UnifiedHelp => Flags::NO_OP,
NextLineHelp
=> Flags::NEXT_LINE_HELP,
IgnoreErrors
=> Flags::IGNORE_ERRORS,
WaitOnError
=> Flags::WAIT_ON_ERROR,
Built
=> Flags::BUILT,
BinNameBuilt
=> Flags::BIN_NAME_BUILT,
InferSubcommands
=> Flags::INFER_SUBCOMMANDS,
AllArgsOverrideSelf
=> Flags::ARGS_OVERRIDE_SELF,
InferLongArgs
=> Flags::INFER_LONG_ARGS
}
/// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case?
#[cfg(feature = "yaml")]
impl FromStr for AppSettings {
type Err = String;
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
#[allow(deprecated)]
#[allow(unreachable_patterns)]
match &*s.to_ascii_lowercase() {
"argrequiredelsehelp" => Ok(AppSettings::ArgRequiredElseHelp),
"subcommandprecedenceoverarg" => Ok(AppSettings::SubcommandPrecedenceOverArg),
"argsnegatesubcommands" => Ok(AppSettings::ArgsNegateSubcommands),
"allowexternalsubcommands" => Ok(AppSettings::AllowExternalSubcommands),
"strictutf8" => Ok(AppSettings::StrictUtf8),
"allowinvalidutf8forexternalsubcommands" => {
Ok(AppSettings::AllowInvalidUtf8ForExternalSubcommands)
}
"allowhyphenvalues" => Ok(AppSettings::AllowHyphenValues),
"allowleadinghyphen" => Ok(AppSettings::AllowLeadingHyphen),
"allownegativenumbers" => Ok(AppSettings::AllowNegativeNumbers),
"allowmissingpositional" => Ok(AppSettings::AllowMissingPositional),
"unifiedhelpmessage" => Ok(AppSettings::UnifiedHelpMessage),
"coloredhelp" => Ok(AppSettings::ColoredHelp),
"coloralways" => Ok(AppSettings::ColorAlways),
"colorauto" => Ok(AppSettings::ColorAuto),
"colornever" => Ok(AppSettings::ColorNever),
"dontdelimittrailingvalues" => Ok(AppSettings::DontDelimitTrailingValues),
"dontcollapseargsinusage" => Ok(AppSettings::DontCollapseArgsInUsage),
"derivedisplayorder" => Ok(AppSettings::DeriveDisplayOrder),
"disablecoloredhelp" => Ok(AppSettings::DisableColoredHelp),
"disablehelpsubcommand" => Ok(AppSettings::DisableHelpSubcommand),
"disablehelpflag" => Ok(AppSettings::DisableHelpFlag),
"disablehelpflags" => Ok(AppSettings::DisableHelpFlags),
"disableversionflag" => Ok(AppSettings::DisableVersionFlag),
"disableversion" => Ok(AppSettings::DisableVersion),
"propagateversion" => Ok(AppSettings::PropagateVersion),
"propagateversion" => Ok(AppSettings::GlobalVersion),
"hidepossiblevalues" => Ok(AppSettings::HidePossibleValues),
"hidepossiblevaluesinhelp" => Ok(AppSettings::HidePossibleValuesInHelp),
"helpexpected" => Ok(AppSettings::HelpExpected),
"hidden" => Ok(AppSettings::Hidden),
"noautohelp" => Ok(AppSettings::NoAutoHelp),
"noautoversion" => Ok(AppSettings::NoAutoVersion),
"nobinaryname" => Ok(AppSettings::NoBinaryName),
"subcommandsnegatereqs" => Ok(AppSettings::SubcommandsNegateReqs),
"subcommandrequired" => Ok(AppSettings::SubcommandRequired),
"subcommandrequiredelsehelp" => Ok(AppSettings::SubcommandRequiredElseHelp),
"uselongformatforhelpsubcommand" => Ok(AppSettings::UseLongFormatForHelpSubcommand),
"trailingvararg" => Ok(AppSettings::TrailingVarArg),
"unifiedhelp" => Ok(AppSettings::UnifiedHelp),
"nextlinehelp" => Ok(AppSettings::NextLineHelp),
"ignoreerrors" => Ok(AppSettings::IgnoreErrors),
"waitonerror" => Ok(AppSettings::WaitOnError),
"built" => Ok(AppSettings::Built),
"binnamebuilt" => Ok(AppSettings::BinNameBuilt),
"infersubcommands" => Ok(AppSettings::InferSubcommands),
"allargsoverrideself" => Ok(AppSettings::AllArgsOverrideSelf),
"inferlongargs" => Ok(AppSettings::InferLongArgs),
_ => Err(format!("unknown AppSetting: `{}`", s)),
}
}
}
#[cfg(test)]
mod test {
#[allow(clippy::cognitive_complexity)]
#[test]
#[cfg(feature = "yaml")]
fn app_settings_fromstr() {
use super::AppSettings;
assert_eq!(
"disablehelpflag".parse::<AppSettings>().unwrap(),
AppSettings::DisableHelpFlag
);
assert_eq!(
"argsnegatesubcommands".parse::<AppSettings>().unwrap(),
AppSettings::ArgsNegateSubcommands
);
assert_eq!(
"argrequiredelsehelp".parse::<AppSettings>().unwrap(),
AppSettings::ArgRequiredElseHelp
);
assert_eq!(
"subcommandprecedenceoverarg"
.parse::<AppSettings>()
.unwrap(),
AppSettings::SubcommandPrecedenceOverArg
);
assert_eq!(
"allowexternalsubcommands".parse::<AppSettings>().unwrap(),
AppSettings::AllowExternalSubcommands
);
assert_eq!(
"allowinvalidutf8forexternalsubcommands"
.parse::<AppSettings>()
.unwrap(),
AppSettings::AllowInvalidUtf8ForExternalSubcommands
);
assert_eq!(
"allowhyphenvalues".parse::<AppSettings>().unwrap(),
AppSettings::AllowHyphenValues
);
assert_eq!(
"allownegativenumbers".parse::<AppSettings>().unwrap(),
AppSettings::AllowNegativeNumbers
);
assert_eq!(
"disablehelpsubcommand".parse::<AppSettings>().unwrap(),
AppSettings::DisableHelpSubcommand
);
assert_eq!(
"disableversionflag".parse::<AppSettings>().unwrap(),
AppSettings::DisableVersionFlag
);
assert_eq!(
"dontcollapseargsinusage".parse::<AppSettings>().unwrap(),
AppSettings::DontCollapseArgsInUsage
);
assert_eq!(
"dontdelimittrailingvalues".parse::<AppSettings>().unwrap(),
AppSettings::DontDelimitTrailingValues
);
assert_eq!(
"derivedisplayorder".parse::<AppSettings>().unwrap(),
AppSettings::DeriveDisplayOrder
);
assert_eq!(
"disablecoloredhelp".parse::<AppSettings>().unwrap(),
AppSettings::DisableColoredHelp
);
assert_eq!(
"propagateversion".parse::<AppSettings>().unwrap(),
AppSettings::PropagateVersion
);
assert_eq!(
"hidden".parse::<AppSettings>().unwrap(),
AppSettings::Hidden
);
assert_eq!(
"hidepossiblevalues".parse::<AppSettings>().unwrap(),
AppSettings::HidePossibleValues
);
assert_eq!(
"helpexpected".parse::<AppSettings>().unwrap(),
AppSettings::HelpExpected
);
assert_eq!(
"nobinaryname".parse::<AppSettings>().unwrap(),
AppSettings::NoBinaryName
);
assert_eq!(
"nextlinehelp".parse::<AppSettings>().unwrap(),
AppSettings::NextLineHelp
);
assert_eq!(
"subcommandsnegatereqs".parse::<AppSettings>().unwrap(),
AppSettings::SubcommandsNegateReqs
);
assert_eq!(
"subcommandrequired".parse::<AppSettings>().unwrap(),
AppSettings::SubcommandRequired
);
assert_eq!(
"subcommandrequiredelsehelp".parse::<AppSettings>().unwrap(),
AppSettings::SubcommandRequiredElseHelp
);
assert_eq!(
"uselongformatforhelpsubcommand"
.parse::<AppSettings>()
.unwrap(),
AppSettings::UseLongFormatForHelpSubcommand
);
assert_eq!(
"trailingvararg".parse::<AppSettings>().unwrap(),
AppSettings::TrailingVarArg
);
assert_eq!(
"waitonerror".parse::<AppSettings>().unwrap(),
AppSettings::WaitOnError
);
assert_eq!("built".parse::<AppSettings>().unwrap(), AppSettings::Built);
assert_eq!(
"binnamebuilt".parse::<AppSettings>().unwrap(),
AppSettings::BinNameBuilt
);
assert_eq!(
"infersubcommands".parse::<AppSettings>().unwrap(),
AppSettings::InferSubcommands
);
assert!("hahahaha".parse::<AppSettings>().is_err());
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,6 @@
// Internal
use crate::util::{Id, Key};
#[cfg(feature = "yaml")]
use yaml_rust::Yaml;
/// Family of related [arguments].
///
/// By placing arguments in a logical group, you can create easier requirement and
@ -118,7 +115,7 @@ impl<'help> ArgGroup<'help> {
///
/// ```rust
/// # use clap::{Command, ArgGroup};
/// ArgGroup::default().name("config")
/// ArgGroup::default().id("config")
/// # ;
/// ```
#[must_use]
@ -128,15 +125,6 @@ impl<'help> ArgGroup<'help> {
self
}
/// Deprecated, replaced with [`ArgGroup::id`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.1.0", note = "Replaced with `ArgGroup::id`")
)]
pub fn name<S: Into<&'help str>>(self, n: S) -> Self {
self.id(n)
}
/// Adds an [argument] to this group by name
///
/// # Examples
@ -434,30 +422,6 @@ impl<'help> ArgGroup<'help> {
}
self
}
/// Deprecated, replaced with [`ArgGroup::new`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `ArgGroup::new`")
)]
#[doc(hidden)]
pub fn with_name<S: Into<&'help str>>(n: S) -> Self {
Self::new(n)
}
/// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case?
#[cfg(feature = "yaml")]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Maybe clap::Parser would fit your use case? (Issue #3087)"
)
)]
#[doc(hidden)]
pub fn from_yaml(yaml: &'help Yaml) -> Self {
Self::from(yaml)
}
}
impl<'help> From<&'_ ArgGroup<'help>> for ArgGroup<'help> {
@ -474,65 +438,23 @@ impl<'help> From<&'_ ArgGroup<'help>> for ArgGroup<'help> {
}
}
/// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case?
#[cfg(feature = "yaml")]
impl<'help> From<&'help Yaml> for ArgGroup<'help> {
/// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case?
fn from(y: &'help Yaml) -> Self {
let b = y.as_hash().expect("ArgGroup::from::<Yaml> expects a table");
// We WANT this to panic on error...so expect() is good.
let mut a = ArgGroup::default();
let group_settings = if b.len() == 1 {
let name_yaml = b.keys().next().expect("failed to get name");
let name_str = name_yaml
.as_str()
.expect("failed to convert arg YAML name to str");
a.name = name_str;
a.id = Id::from(&a.name);
b.get(name_yaml)
.expect("failed to get name_str")
.as_hash()
.expect("failed to convert to a hash")
} else {
b
};
for (k, v) in group_settings {
a = match k.as_str().unwrap() {
"required" => a.required(v.as_bool().unwrap()),
"multiple" => a.multiple(v.as_bool().unwrap()),
"args" => yaml_vec_or_str!(a, v, arg),
"arg" => {
if let Some(ys) = v.as_str() {
a = a.arg(ys);
}
a
}
"requires" => yaml_vec_or_str!(a, v, requires),
"conflicts_with" => yaml_vec_or_str!(a, v, conflicts_with),
"name" => {
if let Some(ys) = v.as_str() {
a = a.id(ys);
}
a
}
s => panic!(
"Unknown ArgGroup setting '{}' in YAML file for \
ArgGroup '{}'",
s, a.name
),
}
impl Clone for ArgGroup<'_> {
fn clone(&self) -> Self {
ArgGroup {
id: self.id.clone(),
name: self.name,
required: self.required,
args: self.args.clone(),
requires: self.requires.clone(),
conflicts: self.conflicts.clone(),
multiple: self.multiple,
}
a
}
}
#[cfg(test)]
mod test {
use super::ArgGroup;
#[cfg(feature = "yaml")]
use yaml_rust::YamlLoader;
#[test]
fn groups() {
@ -581,35 +503,6 @@ mod test {
assert_eq!(g2.conflicts, confs);
}
#[cfg(feature = "yaml")]
#[test]
fn test_yaml() {
let g_yaml = "name: test
args:
- a1
- a4
- a2
- a3
conflicts_with:
- c1
- c2
- c3
- c4
requires:
- r1
- r2
- r3
- r4";
let yaml = &YamlLoader::load_from_str(g_yaml).expect("failed to load YAML file")[0];
let g = ArgGroup::from(yaml);
let args = vec!["a1".into(), "a4".into(), "a2".into(), "a3".into()];
let reqs = vec!["r1".into(), "r2".into(), "r3".into(), "r4".into()];
let confs = vec!["c1".into(), "c2".into(), "c3".into(), "c4".into()];
assert_eq!(g.args, args);
assert_eq!(g.requires, reqs);
assert_eq!(g.conflicts, confs);
}
// This test will *fail to compile* if ArgGroup is not Send + Sync
#[test]
fn arg_group_send_sync() {
@ -617,17 +510,3 @@ requires:
foo(ArgGroup::new("test"))
}
}
impl Clone for ArgGroup<'_> {
fn clone(&self) -> Self {
ArgGroup {
id: self.id.clone(),
name: self.name,
required: self.required,
args: self.args.clone(),
requires: self.requires.clone(),
conflicts: self.conflicts.clone(),
multiple: self.multiple,
}
}
}

View file

@ -2,8 +2,6 @@
// Std
use std::ops::BitOr;
#[cfg(feature = "yaml")]
use std::str::FromStr;
// Third party
use bitflags::bitflags;
@ -11,9 +9,8 @@ use bitflags::bitflags;
#[allow(unused)]
use crate::Arg;
#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArgFlags(Flags);
pub(crate) struct ArgFlags(Flags);
impl Default for ArgFlags {
fn default() -> Self {
@ -31,239 +28,28 @@ impl Default for ArgFlags {
/// [`Arg::is_set`]: crate::Arg::is_set()
#[derive(Debug, PartialEq, Copy, Clone)]
#[non_exhaustive]
pub enum ArgSettings {
/// Deprecated, replaced with [`Arg::required`] and [`Arg::is_required_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::required` and `Arg::is_required_set`"
)
)]
pub(crate) enum ArgSettings {
Required,
/// Deprecated, replaced with [`Arg::multiple_values`] and [`Arg::is_multiple_values_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::multiple_values` and `Arg::`is_multiple_values_set`"
)
)]
MultipleValues,
/// Deprecated, replaced with [`Arg::action`] ([Issue #3772](https://github.com/clap-rs/clap/issues/3772))
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.1.0", note = "Replaced with `Arg::action` (Issue #3772)")
)]
MultipleOccurrences,
/// Deprecated, see [`ArgSettings::MultipleOccurrences`] (most likely what you want) and
/// [`ArgSettings::MultipleValues`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Split into `Arg::multiple_occurrences` (most likely what you want) and `Arg::multiple_values`"
)
)]
#[doc(hidden)]
Multiple,
/// Deprecated, replaced with [`Arg::value_parser(NonEmptyStringValueParser::new())`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::value_parser(NonEmptyStringValueParser::new())`"
)
)]
ForbidEmptyValues,
/// Deprecated, replaced with [`Arg::global`] and [`Arg::is_global_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::global` and `Arg::is_global_set`"
)
)]
Global,
/// Deprecated, replaced with [`Arg::hide`] and [`Arg::is_hide_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide` and `Arg::is_hide_set`"
)
)]
Hidden,
/// Deprecated, replaced with [`Arg::takes_value`] and [`Arg::is_takes_value_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::takes_value` and `Arg::is_takes_value_set`"
)
)]
TakesValue,
/// Deprecated, replaced with [`Arg::use_value_delimiter`] and
/// [`Arg::is_use_value_delimiter_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::use_value_delimiter` and `Arg::is_use_value_delimiter_set`"
)
)]
UseValueDelimiter,
/// Deprecated, replaced with [`Arg::next_line_help`] and [`Arg::is_next_line_help_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::next_line_help` and `Arg::is_next_line_help_set`"
)
)]
NextLineHelp,
/// Deprecated, replaced with [`Arg::require_value_delimiter`] and
/// [`Arg::is_require_value_delimiter_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::require_value_delimiter` and `Arg::is_require_value_delimiter_set`"
)
)]
RequireDelimiter,
/// Deprecated, replaced with [`Arg::hide_possible_values`] and
/// [`Arg::is_hide_possible_values_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_possible_values` and `Arg::is_hide_possible_values_set`"
)
)]
HidePossibleValues,
/// Deprecated, replaced with [`Arg::allow_hyphen_values`] and
/// [`Arg::is_allow_hyphen_values_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::allow_hyphen_values` and `Arg::is_allow_hyphen_values_set`"
)
)]
AllowHyphenValues,
/// Deprecated, replaced with [`Arg::allow_hyphen_values`] and
/// [`Arg::is_allow_hyphen_values_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Replaced with `Arg::allow_hyphen_values` and `Arg::is_allow_hyphen_values_set`"
)
)]
#[doc(hidden)]
AllowLeadingHyphen,
/// Deprecated, replaced with [`Arg::require_equals`] and [`Arg::is_require_equals_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::require_equals` and `Arg::is_require_equals_set`"
)
)]
RequireEquals,
/// Deprecated, replaced with [`Arg::last`] and [`Arg::is_last_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::last` and `Arg::is_last_set`"
)
)]
Last,
/// Deprecated, replaced with [`Arg::hide_default_value`] and [`Arg::is_hide_default_value_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_default_value` and `Arg::is_hide_default_value_set`"
)
)]
HideDefaultValue,
/// Deprecated, replaced with [`Arg::ignore_case`] and [`Arg::is_ignore_case_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::ignore_case` and `Arg::is_ignore_case_set`"
)
)]
IgnoreCase,
/// Deprecated, replaced with [`Arg::ignore_case`] and [`Arg::is_ignore_case_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Replaced with `Arg::ignore_case` and `Arg::is_ignore_case_set`"
)
)]
#[doc(hidden)]
CaseInsensitive,
/// Deprecated, replaced with [`Arg::hide_env`] and [`Arg::is_hide_env_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_env` and `Arg::is_hide_env_set`"
)
)]
#[cfg(feature = "env")]
HideEnv,
/// Deprecated, replaced with [`Arg::hide_env_values`] and [`Arg::is_hide_env_values_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_env_values` and `Arg::is_hide_env_values_set`"
)
)]
#[cfg(feature = "env")]
HideEnvValues,
/// Deprecated, replaced with [`Arg::hide_short_help`] and [`Arg::is_hide_short_help_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_short_help` and `Arg::is_hide_short_help_set`"
)
)]
HiddenShortHelp,
/// Deprecated, replaced with [`Arg::hide_long_help`] and [`Arg::is_hide_long_help_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_long_help` and `Arg::is_hide_long_help_set`"
)
)]
HiddenLongHelp,
/// Deprecated, replaced with [`Arg::allow_invalid_utf8`] and [`Arg::is_allow_invalid_utf8_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::allow_invalid_utf8` and `Arg::is_allow_invalid_utf8_set`"
)
)]
AllowInvalidUtf8,
/// Deprecated, replaced with [`Arg::exclusive`] and [`Arg::is_exclusive_set`]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `Arg::exclusive` and `Arg::is_exclusive_set`"
)
)]
Exclusive,
}
@ -271,7 +57,6 @@ bitflags! {
struct Flags: u32 {
const REQUIRED = 1;
const MULTIPLE_OCC = 1 << 1;
const NO_EMPTY_VALS = 1 << 2;
const GLOBAL = 1 << 3;
const HIDDEN = 1 << 4;
const TAKES_VAL = 1 << 5;
@ -293,7 +78,6 @@ bitflags! {
const MULTIPLE = Self::MULTIPLE_OCC.bits | Self::MULTIPLE_VALS.bits;
#[cfg(feature = "env")]
const HIDE_ENV = 1 << 21;
const UTF8_NONE = 1 << 22;
const EXCLUSIVE = 1 << 23;
const NO_OP = 0;
}
@ -303,8 +87,6 @@ impl_settings! { ArgSettings, ArgFlags,
Required => Flags::REQUIRED,
MultipleOccurrences => Flags::MULTIPLE_OCC,
MultipleValues => Flags::MULTIPLE_VALS,
Multiple => Flags::MULTIPLE,
ForbidEmptyValues => Flags::NO_EMPTY_VALS,
Global => Flags::GLOBAL,
Hidden => Flags::HIDDEN,
TakesValue => Flags::TAKES_VAL,
@ -313,11 +95,9 @@ impl_settings! { ArgSettings, ArgFlags,
RequireDelimiter => Flags::REQ_DELIM,
HidePossibleValues => Flags::HIDE_POS_VALS,
AllowHyphenValues => Flags::ALLOW_TAC_VALS,
AllowLeadingHyphen => Flags::ALLOW_TAC_VALS,
RequireEquals => Flags::REQUIRE_EQUALS,
Last => Flags::LAST,
IgnoreCase => Flags::CASE_INSENSITIVE,
CaseInsensitive => Flags::CASE_INSENSITIVE,
#[cfg(feature = "env")]
HideEnv => Flags::HIDE_ENV,
#[cfg(feature = "env")]
@ -325,132 +105,53 @@ impl_settings! { ArgSettings, ArgFlags,
HideDefaultValue => Flags::HIDE_DEFAULT_VAL,
HiddenShortHelp => Flags::HIDDEN_SHORT_H,
HiddenLongHelp => Flags::HIDDEN_LONG_H,
AllowInvalidUtf8 => Flags::UTF8_NONE,
Exclusive => Flags::EXCLUSIVE
}
/// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case?
#[cfg(feature = "yaml")]
impl FromStr for ArgSettings {
type Err = String;
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
#[allow(deprecated)]
#[allow(unreachable_patterns)]
match &*s.to_ascii_lowercase() {
"required" => Ok(ArgSettings::Required),
"multipleoccurrences" => Ok(ArgSettings::MultipleOccurrences),
"multiplevalues" => Ok(ArgSettings::MultipleValues),
"multiple" => Ok(ArgSettings::Multiple),
"forbidemptyvalues" => Ok(ArgSettings::ForbidEmptyValues),
"global" => Ok(ArgSettings::Global),
"hidden" => Ok(ArgSettings::Hidden),
"takesvalue" => Ok(ArgSettings::TakesValue),
"usevaluedelimiter" => Ok(ArgSettings::UseValueDelimiter),
"nextlinehelp" => Ok(ArgSettings::NextLineHelp),
"requiredelimiter" => Ok(ArgSettings::RequireDelimiter),
"hidepossiblevalues" => Ok(ArgSettings::HidePossibleValues),
"allowhyphenvalues" => Ok(ArgSettings::AllowHyphenValues),
"allowleadinghypyhen" => Ok(ArgSettings::AllowLeadingHyphen),
"requireequals" => Ok(ArgSettings::RequireEquals),
"last" => Ok(ArgSettings::Last),
"ignorecase" => Ok(ArgSettings::IgnoreCase),
"caseinsensitive" => Ok(ArgSettings::CaseInsensitive),
#[cfg(feature = "env")]
"hideenv" => Ok(ArgSettings::HideEnv),
#[cfg(feature = "env")]
"hideenvvalues" => Ok(ArgSettings::HideEnvValues),
"hidedefaultvalue" => Ok(ArgSettings::HideDefaultValue),
"hiddenshorthelp" => Ok(ArgSettings::HiddenShortHelp),
"hiddenlonghelp" => Ok(ArgSettings::HiddenLongHelp),
"allowinvalidutf8" => Ok(ArgSettings::AllowInvalidUtf8),
"exclusive" => Ok(ArgSettings::Exclusive),
_ => Err(format!("unknown AppSetting: `{}`", s)),
}
}
}
#[cfg(test)]
mod test {
#[test]
#[cfg(feature = "yaml")]
fn arg_settings_fromstr() {
use super::ArgSettings;
use super::*;
use crate::Arg;
assert_eq!(
"allowhyphenvalues".parse::<ArgSettings>().unwrap(),
ArgSettings::AllowHyphenValues
);
assert_eq!(
"forbidemptyvalues".parse::<ArgSettings>().unwrap(),
ArgSettings::ForbidEmptyValues
);
assert_eq!(
"hidepossiblevalues".parse::<ArgSettings>().unwrap(),
ArgSettings::HidePossibleValues
);
assert_eq!(
"hidden".parse::<ArgSettings>().unwrap(),
ArgSettings::Hidden
);
assert_eq!(
"nextlinehelp".parse::<ArgSettings>().unwrap(),
ArgSettings::NextLineHelp
);
assert_eq!(
"requiredelimiter".parse::<ArgSettings>().unwrap(),
ArgSettings::RequireDelimiter
);
assert_eq!(
"required".parse::<ArgSettings>().unwrap(),
ArgSettings::Required
);
assert_eq!(
"takesvalue".parse::<ArgSettings>().unwrap(),
ArgSettings::TakesValue
);
assert_eq!(
"usevaluedelimiter".parse::<ArgSettings>().unwrap(),
ArgSettings::UseValueDelimiter
);
assert_eq!(
"requireequals".parse::<ArgSettings>().unwrap(),
ArgSettings::RequireEquals
);
assert_eq!("last".parse::<ArgSettings>().unwrap(), ArgSettings::Last);
assert_eq!(
"hidedefaultvalue".parse::<ArgSettings>().unwrap(),
ArgSettings::HideDefaultValue
);
assert_eq!(
"ignorecase".parse::<ArgSettings>().unwrap(),
ArgSettings::IgnoreCase
);
#[cfg(feature = "env")]
assert_eq!(
"hideenv".parse::<ArgSettings>().unwrap(),
ArgSettings::HideEnv
);
#[cfg(feature = "env")]
assert_eq!(
"hideenvvalues".parse::<ArgSettings>().unwrap(),
ArgSettings::HideEnvValues
);
assert_eq!(
"hiddenshorthelp".parse::<ArgSettings>().unwrap(),
ArgSettings::HiddenShortHelp
);
assert_eq!(
"hiddenlonghelp".parse::<ArgSettings>().unwrap(),
ArgSettings::HiddenLongHelp
);
assert_eq!(
"allowinvalidutf8".parse::<ArgSettings>().unwrap(),
ArgSettings::AllowInvalidUtf8
);
assert_eq!(
"exclusive".parse::<ArgSettings>().unwrap(),
ArgSettings::Exclusive
);
assert!("hahahaha".parse::<ArgSettings>().is_err());
#[test]
fn setting() {
let m = Arg::new("setting").setting(ArgSettings::Required);
assert!(m.is_required_set());
}
#[test]
fn unset_setting() {
let m = Arg::new("unset_setting").setting(ArgSettings::Required);
assert!(m.is_required_set());
let m = m.unset_setting(ArgSettings::Required);
assert!(!m.is_required_set(), "{:#?}", m);
}
#[test]
fn setting_bitor() {
let m = Arg::new("setting_bitor")
.setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
assert!(m.is_required_set());
assert!(m.is_hide_set());
assert!(m.is_last_set());
}
#[test]
fn unset_setting_bitor() {
let m = Arg::new("unset_setting_bitor")
.setting(ArgSettings::Required)
.setting(ArgSettings::Hidden)
.setting(ArgSettings::Last);
assert!(m.is_required_set());
assert!(m.is_hide_set());
assert!(m.is_last_set());
let m = m.unset_setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
assert!(!m.is_required_set(), "{:#?}", m);
assert!(!m.is_hide_set(), "{:#?}", m);
assert!(!m.is_last_set(), "{:#?}", m);
}
}

File diff suppressed because it is too large Load diff

View file

@ -265,14 +265,6 @@ pub(crate) fn assert_app(cmd: &Command) {
arg.name
);
// validators
assert!(
arg.validator.is_none() || arg.validator_os.is_none(),
"Command {}: Argument '{}' has both `validator` and `validator_os` set which is not allowed",
cmd.get_name(),
arg.name
);
if arg.get_value_hint() == ValueHint::CommandWithArguments {
assert!(
arg.is_positional(),
@ -745,11 +737,6 @@ fn assert_arg_flags(arg: &Arg) {
checker!(is_hide_default_value_set requires is_takes_value_set);
checker!(is_multiple_values_set requires is_takes_value_set);
checker!(is_ignore_case_set requires is_takes_value_set);
{
#![allow(deprecated)]
checker!(is_forbid_empty_values_set requires is_takes_value_set);
checker!(is_allow_invalid_utf8_set requires is_takes_value_set);
}
}
fn assert_defaults<'d>(
@ -758,73 +745,6 @@ fn assert_defaults<'d>(
defaults: impl IntoIterator<Item = &'d std::ffi::OsStr>,
) {
for default_os in defaults {
if let Some(default_s) = default_os.to_str() {
if !arg.possible_vals.is_empty() {
if let Some(delim) = arg.get_value_delimiter() {
for part in default_s.split(delim) {
assert!(
arg.possible_vals.iter().any(|possible_val| {
possible_val.matches(part, arg.is_ignore_case_set())
}),
"Argument `{}`'s {}={} doesn't match possible values",
arg.name,
field,
part
)
}
} else {
assert!(
arg.possible_vals.iter().any(|possible_val| {
possible_val.matches(default_s, arg.is_ignore_case_set())
}),
"Argument `{}`'s {}={} doesn't match possible values",
arg.name,
field,
default_s
);
}
}
if let Some(validator) = arg.validator.as_ref() {
let mut validator = validator.lock().unwrap();
if let Some(delim) = arg.get_value_delimiter() {
for part in default_s.split(delim) {
if let Err(err) = validator(part) {
panic!(
"Argument `{}`'s {}={} failed validation: {}",
arg.name, field, part, err
);
}
}
} else if let Err(err) = validator(default_s) {
panic!(
"Argument `{}`'s {}={} failed validation: {}",
arg.name, field, default_s, err
);
}
}
}
if let Some(validator) = arg.validator_os.as_ref() {
let mut validator = validator.lock().unwrap();
if let Some(delim) = arg.get_value_delimiter() {
let default_os = RawOsStr::new(default_os);
for part in default_os.split(delim) {
if let Err(err) = validator(&part.to_os_str()) {
panic!(
"Argument `{}`'s {}={:?} failed validation: {}",
arg.name, field, part, err
);
}
}
} else if let Err(err) = validator(default_os) {
panic!(
"Argument `{}`'s {}={:?} failed validation: {}",
arg.name, field, default_os, err
);
}
}
let value_parser = arg.get_value_parser();
let assert_cmd = Command::new("assert");
if let Some(delim) = arg.get_value_delimiter() {

View file

@ -1,180 +0,0 @@
#[cfg(feature = "yaml")]
macro_rules! yaml_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) => {{
if let Some(vec) = $v.as_vec() {
for ys in vec {
if let Some(tup) = ys.as_vec() {
debug_assert_eq!(3, tup.len());
$a = $a.$c(
yaml_str!(tup[0]),
yaml_opt_str!(tup[1]),
yaml_opt_str!(tup[2]),
);
} 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_vec_or_str {
($a:ident, $v:ident, $c:ident) => {{
let maybe_vec = $v.as_vec();
if let Some(vec) = maybe_vec {
for ys in vec {
if let Some(s) = ys.as_str() {
$a = $a.$c(s);
} else {
panic!("Failed to convert YAML value {:?} to a string", ys);
}
}
} else {
if let Some(s) = $v.as_str() {
$a = $a.$c(s);
} else {
panic!(
"Failed to convert YAML value {:?} to either a vec or string",
$v
);
}
}
$a
}};
}
#[cfg(feature = "yaml")]
macro_rules! yaml_vec {
($a:ident, $v:ident, $c:ident) => {{
let maybe_vec = $v.as_vec();
if let Some(vec) = maybe_vec {
let content = vec.into_iter().map(|ys| {
if let Some(s) = ys.as_str() {
s
} else {
panic!("Failed to convert YAML value {:?} to a string", ys);
}
});
$a = $a.$c(content)
} else {
panic!("Failed to convert YAML value {:?} to a vec", $v);
}
$a
}};
}
#[cfg(feature = "yaml")]
macro_rules! yaml_opt_str {
($v:expr) => {{
if !$v.is_null() {
Some(
$v.as_str()
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v)),
)
} else {
None
}
}};
}
#[cfg(feature = "yaml")]
macro_rules! yaml_char {
($v:expr) => {{
$v.as_str()
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v))
.chars()
.next()
.unwrap_or_else(|| panic!("Expected char"))
}};
}
#[cfg(feature = "yaml")]
macro_rules! yaml_str {
($v:expr) => {{
$v.as_str()
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v))
}};
}
#[cfg(feature = "yaml")]
macro_rules! yaml_to_char {
($a:ident, $v:ident, $c:ident) => {{
$a.$c(yaml_char!($v))
}};
}
#[cfg(feature = "yaml")]
macro_rules! yaml_to_str {
($a:ident, $v:ident, $c:ident) => {{
$a.$c(yaml_str!($v))
}};
}
#[cfg(feature = "yaml")]
macro_rules! yaml_to_bool {
($a:ident, $v:ident, $c:ident) => {{
$a.$c($v
.as_bool()
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v)))
}};
}
#[cfg(feature = "yaml")]
macro_rules! yaml_to_usize {
($a:ident, $v:ident, $c:ident) => {{
$a.$c($v
.as_i64()
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v))
as usize)
}};
}
#[cfg(feature = "yaml")]
macro_rules! yaml_to_setting {
($a:ident, $v:ident, $c:ident, $s:ident, $t:literal, $n:expr) => {{
if let Some(v) = $v.as_vec() {
for ys in v {
if let Some(s) = ys.as_str() {
$a = $a.$c(s.parse::<$s>().unwrap_or_else(|_| {
panic!("Unknown {} '{}' found in YAML file for {}", $t, s, $n)
}));
} else {
panic!(
"Failed to convert YAML {:?} value to an array of strings",
$v
);
}
}
} else if let Some(v) = $v.as_str() {
$a = $a.$c(v
.parse::<$s>()
.unwrap_or_else(|_| panic!("Unknown {} '{}' found in YAML file for {}", $t, v, $n)))
} else {
panic!("Failed to convert YAML {:?} value to a string", $v);
}
$a
}};
}

View file

@ -1,8 +1,5 @@
//! Define [`Command`] line [arguments][`Arg`]
#[macro_use]
mod macros;
mod action;
mod app_settings;
mod arg;
@ -11,13 +8,9 @@ mod arg_predicate;
mod arg_settings;
mod command;
mod possible_value;
mod usage_parser;
mod value_hint;
mod value_parser;
#[cfg(feature = "regex")]
mod regex;
#[cfg(debug_assertions)]
mod debug_asserts;
@ -28,7 +21,6 @@ pub use action::ArgAction;
pub use app_settings::{AppFlags, AppSettings};
pub use arg::Arg;
pub use arg_group::ArgGroup;
pub use arg_settings::{ArgFlags, ArgSettings};
pub use command::Command;
pub use possible_value::PossibleValue;
pub use value_hint::ValueHint;
@ -50,12 +42,7 @@ pub use value_parser::NonEmptyStringValueParser;
pub use value_parser::OsStringValueParser;
pub use value_parser::PathBufValueParser;
#[allow(deprecated)]
pub use command::App;
#[cfg(feature = "regex")]
pub use self::regex::RegexRef;
pub(crate) use action::CountType;
pub(crate) use arg::display_arg_val;
pub(crate) use arg_predicate::ArgPredicate;
pub(crate) use arg_settings::{ArgFlags, ArgSettings};

View file

@ -50,7 +50,7 @@ impl<'help> PossibleValue<'help> {
/// # ;
/// ```
/// [hidden]: PossibleValue::hide
/// [possible value]: crate::Arg::possible_values
/// [possible value]: crate::builder::PossibleValuesParser
/// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values()
pub fn new(name: &'help str) -> Self {
PossibleValue {
@ -162,16 +162,6 @@ impl<'help> PossibleValue<'help> {
}
}
/// Deprecated, replaced with [`PossibleValue::is_hide_set`]
#[inline]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.1.0", note = "Replaced with `PossibleValue::is_hide_set`")
)]
pub fn is_hidden(&self) -> bool {
self.is_hide_set()
}
/// Report if [`PossibleValue::hide`] is set
#[inline]
pub fn is_hide_set(&self) -> bool {

View file

@ -1,88 +0,0 @@
use ::regex::{Error, Regex, RegexSet};
use core::{convert::TryFrom, ops::Deref, str::FromStr};
use std::borrow::Cow;
/// Contains either a regular expression or a set of them or a reference to one.
///
/// See [Arg::validator_regex(][crate::Arg::validator_regex] to set this on an argument.
#[derive(Debug, Clone)]
pub enum RegexRef<'a> {
/// Used if the underlying is a regex set
RegexSet(Cow<'a, RegexSet>),
/// Used if the underlying is a regex
Regex(Cow<'a, Regex>),
}
impl<'a> RegexRef<'a> {
pub(crate) fn is_match(&self, text: &str) -> bool {
match self {
Self::Regex(r) => r.deref().is_match(text),
Self::RegexSet(r) => r.deref().is_match(text),
}
}
}
impl<'a> From<&'a Regex> for RegexRef<'a> {
fn from(r: &'a Regex) -> Self {
Self::Regex(Cow::Borrowed(r))
}
}
impl<'a> From<Regex> for RegexRef<'a> {
fn from(r: Regex) -> Self {
Self::Regex(Cow::Owned(r))
}
}
impl<'a> From<&'a RegexSet> for RegexRef<'a> {
fn from(r: &'a RegexSet) -> Self {
Self::RegexSet(Cow::Borrowed(r))
}
}
impl<'a> From<RegexSet> for RegexRef<'a> {
fn from(r: RegexSet) -> Self {
Self::RegexSet(Cow::Owned(r))
}
}
impl<'a> TryFrom<&'a str> for RegexRef<'a> {
type Error = <Self as FromStr>::Err;
fn try_from(r: &'a str) -> Result<Self, Self::Error> {
Self::from_str(r)
}
}
impl<'a> FromStr for RegexRef<'a> {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Regex::from_str(s).map(|v| Self::Regex(Cow::Owned(v)))
}
}
#[cfg(test)]
mod tests {
use super::*;
use core::convert::TryInto;
#[test]
fn test_try_from_with_valid_string() {
let t: Result<RegexRef, _> = "^Hello, World$".try_into();
assert!(t.is_ok())
}
#[test]
fn test_try_from_with_invalid_string() {
let t: Result<RegexRef, _> = "^Hello, World)$".try_into();
assert!(t.is_err());
}
#[test]
fn from_str() {
let t: Result<RegexRef, _> = RegexRef::from_str("^Hello, World");
assert!(t.is_ok());
}
}

File diff suppressed because it is too large Load diff

View file

@ -36,10 +36,10 @@ use std::ffi::OsString;
/// #[clap(name = "demo")]
/// struct Context {
/// /// More verbose output
/// #[clap(long)]
/// #[clap(long, value_parser)]
/// verbose: bool,
/// /// An optional name
/// #[clap(short, long)]
/// #[clap(short, long, value_parser)]
/// name: Option<String>,
/// }
/// ```
@ -153,95 +153,6 @@ pub trait Parser: FromArgMatches + CommandFactory + Sized {
<Self as FromArgMatches>::update_from_arg_matches_mut(self, &mut matches)
.map_err(format_error::<Self>)
}
/// Deprecated, `StructOpt::clap` replaced with [`CommandFactory::command`] (derive as part of
/// [`Parser`])
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "`StructOpt::clap` is replaced with `CommandFactory::command` (derived as part of `Parser`)"
)
)]
#[doc(hidden)]
fn clap<'help>() -> Command<'help> {
<Self as CommandFactory>::command()
}
/// Deprecated, `StructOpt::from_clap` replaced with [`FromArgMatches::from_arg_matches_mut`] (derive as part of
/// [`Parser`])
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "`StructOpt::from_clap` is replaced with `FromArgMatches::from_arg_matches_mut` (derived as part of `Parser`)"
)
)]
#[doc(hidden)]
fn from_clap(matches: &ArgMatches) -> Self {
<Self as FromArgMatches>::from_arg_matches(matches).unwrap()
}
/// Deprecated, `StructOpt::from_args` replaced with `Parser::parse` (note the change in derives)
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "`StructOpt::from_args` is replaced with `Parser::parse` (note the change in derives)"
)
)]
#[doc(hidden)]
fn from_args() -> Self {
Self::parse()
}
/// Deprecated, `StructOpt::from_args_safe` replaced with `Parser::try_parse` (note the change in derives)
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "`StructOpt::from_args_safe` is replaced with `Parser::try_parse` (note the change in derives)"
)
)]
#[doc(hidden)]
fn from_args_safe() -> Result<Self, Error> {
Self::try_parse()
}
/// Deprecated, `StructOpt::from_iter` replaced with `Parser::parse_from` (note the change in derives)
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "`StructOpt::from_iter` is replaced with `Parser::parse_from` (note the change in derives)"
)
)]
#[doc(hidden)]
fn from_iter<I, T>(itr: I) -> Self
where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
{
Self::parse_from(itr)
}
/// Deprecated, `StructOpt::from_iter_safe` replaced with `Parser::try_parse_from` (note the
/// change in derives)
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "`StructOpt::from_iter_safe` is replaced with `Parser::try_parse_from` (note the change in derives)"
)
)]
#[doc(hidden)]
fn from_iter_safe<I, T>(itr: I) -> Result<Self, Error>
where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
{
Self::try_parse_from(itr)
}
}
/// Create a [`Command`] relevant for a user-defined container.
@ -251,32 +162,11 @@ pub trait CommandFactory: Sized {
/// Build a [`Command`] that can instantiate `Self`.
///
/// See [`FromArgMatches::from_arg_matches_mut`] for instantiating `Self`.
fn command<'help>() -> Command<'help> {
#[allow(deprecated)]
Self::into_app()
}
/// Deprecated, replaced with `CommandFactory::command`
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.1.0", note = "Replaced with `CommandFactory::command")
)]
fn into_app<'help>() -> Command<'help>;
fn command<'help>() -> Command<'help>;
/// Build a [`Command`] that can update `self`.
///
/// See [`FromArgMatches::update_from_arg_matches_mut`] for updating `self`.
fn command_for_update<'help>() -> Command<'help> {
#[allow(deprecated)]
Self::into_app_for_update()
}
/// Deprecated, replaced with `CommandFactory::command_for_update`
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.1.0",
note = "Replaced with `CommandFactory::command_for_update"
)
)]
fn into_app_for_update<'help>() -> Command<'help>;
fn command_for_update<'help>() -> Command<'help>;
}
/// Converts an instance of [`ArgMatches`] to a user-defined container.
@ -451,7 +341,7 @@ pub trait Subcommand: FromArgMatches + Sized {
///
/// When deriving [`Parser`], a field whose type implements `ValueEnum` can have the attribute
/// `#[clap(value_enum)]` which will
/// - Call [`Arg::possible_values`][crate::Arg::possible_values]
/// - Call [EnumValueParser`][crate::builder::EnumValueParser]`
/// - Allowing using the `#[clap(default_value_t)]` attribute without implementing `Display`.
///
/// See the [derive reference](crate::_derive) for attributes and best practices.
@ -464,7 +354,7 @@ pub trait Subcommand: FromArgMatches + Sized {
#[cfg_attr(feature = "derive", doc = " ```")]
/// #[derive(clap::Parser)]
/// struct Args {
/// #[clap(value_enum)]
/// #[clap(value_enum, value_parser)]
/// level: Level,
/// }
///
@ -525,13 +415,12 @@ impl<T: Parser> Parser for Box<T> {
}
}
#[allow(deprecated)]
impl<T: CommandFactory> CommandFactory for Box<T> {
fn into_app<'help>() -> Command<'help> {
<T as CommandFactory>::into_app()
fn command<'help>() -> Command<'help> {
<T as CommandFactory>::command()
}
fn into_app_for_update<'help>() -> Command<'help> {
<T as CommandFactory>::into_app_for_update()
fn command_for_update<'help>() -> Command<'help> {
<T as CommandFactory>::command_for_update()
}
}

View file

@ -18,10 +18,6 @@ pub enum ContextKind {
ExpectedNumValues,
/// Minimum number of allowed values
MinValues,
/// Number of occurrences present
ActualNumOccurrences,
/// Maximum number of allowed occurrences
MaxOccurrences,
/// Potential fix for the user
SuggestedCommand,
/// Potential fix for the user

View file

@ -93,7 +93,7 @@ pub enum ErrorKind {
/// let res = Command::new("prog")
/// .arg(Arg::new("color")
/// .takes_value(true)
/// .forbid_empty_values(true)
/// .value_parser(clap::builder::NonEmptyStringValueParser::new())
/// .long("color"))
/// .try_get_matches_from(vec!["prog", "--color="]);
/// assert!(res.is_err());
@ -123,7 +123,7 @@ pub enum ErrorKind {
/// # Examples
///
/// ```rust
/// # use clap::{Command, Arg, ErrorKind};
/// # use clap::{Command, Arg, ErrorKind, value_parser};
/// fn is_numeric(val: &str) -> Result<(), String> {
/// match val.parse::<i64>() {
/// Ok(..) => Ok(()),
@ -133,7 +133,7 @@ pub enum ErrorKind {
///
/// let result = Command::new("prog")
/// .arg(Arg::new("num")
/// .validator(is_numeric))
/// .value_parser(value_parser!(u8)))
/// .try_get_matches_from(vec!["prog", "NotANumber"]);
/// assert!(result.is_err());
/// assert_eq!(result.unwrap_err().kind(), ErrorKind::ValueValidation);
@ -175,24 +175,6 @@ pub enum ErrorKind {
/// [`Arg::min_values`]: crate::Arg::min_values()
TooFewValues,
/// Occurs when a user provides more occurrences for an argument than were defined by setting
/// [`Arg::max_occurrences`].
///
/// # Examples
///
/// ```rust
/// # use clap::{Command, Arg, ErrorKind};
/// let result = Command::new("prog")
/// .arg(Arg::new("verbosity")
/// .short('v')
/// .max_occurrences(2))
/// .try_get_matches_from(vec!["prog", "-vvv"]);
/// assert!(result.is_err());
/// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyOccurrences);
/// ```
/// [`Arg::max_occurrences`]: crate::Arg::max_occurrences()
TooManyOccurrences,
/// Occurs when the user provides a different number of values for an argument than what's
/// been defined by setting [`Arg::number_of_values`] or than was implicitly set by
/// [`Arg::value_names`].
@ -289,7 +271,7 @@ pub enum ErrorKind {
/// Occurs when the user provides a value containing invalid UTF-8.
///
/// To allow arbitrary data
/// - Set [`Arg::allow_invalid_utf8`] for argument values
/// - Set [`Arg::value_parser(value_parser!(OsString))`] for argument values
/// - Set [`Command::allow_invalid_utf8_for_external_subcommands`] for external-subcommand
/// values
///
@ -374,13 +356,6 @@ pub enum ErrorKind {
/// ```
DisplayVersion,
/// Occurs when using the [`ArgMatches::value_of_t`] and friends to convert an argument value
/// into type `T`, but the argument you requested wasn't used. I.e. you asked for an argument
/// with name `config` to be converted, but `config` wasn't used by the user.
///
/// [`ArgMatches::value_of_t`]: crate::ArgMatches::value_of_t()
ArgumentNotFound,
/// Represents an [I/O error].
/// Can occur when writing to `stderr` or `stdout` or reading a configuration file.
///
@ -410,7 +385,6 @@ impl ErrorKind {
Self::ValueValidation => Some("Invalid value for one of the arguments"),
Self::TooManyValues => Some("An argument received an unexpected value"),
Self::TooFewValues => Some("An argument requires more values"),
Self::TooManyOccurrences => Some("An argument occurred too many times"),
Self::WrongNumberOfValues => Some("An argument received too many or too few values"),
Self::ArgumentConflict => {
Some("An argument cannot be used with one or more of the other specified arguments")
@ -426,7 +400,6 @@ impl ErrorKind {
Self::DisplayHelp => None,
Self::DisplayHelpOnMissingArgumentOrSubcommand => None,
Self::DisplayVersion => None,
Self::ArgumentNotFound => Some("An argument wasn't found"),
Self::Io => None,
Self::Format => None,
}

View file

@ -1,5 +1,4 @@
//! Error reporting
#![allow(deprecated)]
// Std
use std::{
@ -7,7 +6,7 @@ use std::{
convert::From,
error,
fmt::{self, Debug, Display, Formatter},
io::{self, BufRead},
io::{self},
result::Result as StdResult,
};
@ -16,7 +15,6 @@ use crate::output::fmt::Colorizer;
use crate::output::fmt::Stream;
use crate::parser::features::suggestions;
use crate::util::{color::ColorChoice, safe_exit, SUCCESS_CODE, USAGE_CODE};
use crate::AppSettings;
use crate::Command;
mod context;
@ -39,18 +37,6 @@ pub type Result<T, E = Error> = StdResult<T, E>;
#[derive(Debug)]
pub struct Error {
inner: Box<ErrorInner>,
/// Deprecated, replaced with [`Error::kind()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.1.0", note = "Replaced with `Error::kind()`")
)]
pub kind: ErrorKind,
/// Deprecated, replaced with [`Error::context()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.1.0", note = "Replaced with `Error::context()`")
)]
pub info: Vec<String>,
}
#[derive(Debug)]
@ -61,7 +47,6 @@ struct ErrorInner {
source: Option<Box<dyn error::Error + Send + Sync>>,
help_flag: Option<&'static str>,
color_when: ColorChoice,
wait_on_exit: bool,
backtrace: Option<Backtrace>,
}
@ -121,13 +106,6 @@ impl Error {
// Swallow broken pipe errors
let _ = self.print();
if self.inner.wait_on_exit {
wlnerr!("\nPress [ENTER] / [RETURN] to continue...");
let mut s = String::new();
let i = io::stdin();
i.lock().read_line(&mut s).unwrap();
}
safe_exit(USAGE_CODE);
}
@ -156,18 +134,6 @@ impl Error {
self.formatted().print()
}
/// Deprecated, replaced with [`Command::error`]
///
/// [`Command::error`]: crate::Command::error
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `Command::error`")
)]
#[doc(hidden)]
pub fn with_description(description: String, kind: ErrorKind) -> Self {
Error::raw(kind, description)
}
fn new(kind: ErrorKind) -> Self {
Self {
inner: Box::new(ErrorInner {
@ -177,25 +143,18 @@ impl Error {
source: None,
help_flag: None,
color_when: ColorChoice::Never,
wait_on_exit: false,
backtrace: Backtrace::new(),
}),
kind,
info: vec![],
}
}
#[inline(never)]
fn for_app(kind: ErrorKind, cmd: &Command, colorizer: Colorizer, info: Vec<String>) -> Self {
Self::new(kind)
.set_message(colorizer)
.with_cmd(cmd)
.set_info(info)
fn for_app(kind: ErrorKind, cmd: &Command, colorizer: Colorizer) -> Self {
Self::new(kind).set_message(colorizer).with_cmd(cmd)
}
pub(crate) fn with_cmd(self, cmd: &Command) -> Self {
self.set_wait_on_exit(cmd.is_set(AppSettings::WaitOnError))
.set_color(cmd.get_color())
self.set_color(cmd.get_color())
.set_help_flag(get_help_flag(cmd))
}
@ -204,11 +163,6 @@ impl Error {
self
}
pub(crate) fn set_info(mut self, info: Vec<String>) -> Self {
self.info = info;
self
}
pub(crate) fn set_source(mut self, source: Box<dyn error::Error + Send + Sync>) -> Self {
self.inner.source = Some(source);
self
@ -224,11 +178,6 @@ impl Error {
self
}
pub(crate) fn set_wait_on_exit(mut self, yes: bool) -> Self {
self.inner.wait_on_exit = yes;
self
}
/// Does not verify if `ContextKind` is already present
#[inline(never)]
pub(crate) fn insert_context_unchecked(
@ -259,7 +208,7 @@ impl Error {
}
pub(crate) fn display_help(cmd: &Command, colorizer: Colorizer) -> Self {
Self::for_app(ErrorKind::DisplayHelp, cmd, colorizer, vec![])
Self::for_app(ErrorKind::DisplayHelp, cmd, colorizer)
}
pub(crate) fn display_help_error(cmd: &Command, colorizer: Colorizer) -> Self {
@ -267,12 +216,11 @@ impl Error {
ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand,
cmd,
colorizer,
vec![],
)
}
pub(crate) fn display_version(cmd: &Command, colorizer: Colorizer) -> Self {
Self::for_app(ErrorKind::DisplayVersion, cmd, colorizer, vec![])
Self::for_app(ErrorKind::DisplayVersion, cmd, colorizer)
}
pub(crate) fn argument_conflict(
@ -281,7 +229,6 @@ impl Error {
mut others: Vec<String>,
usage: String,
) -> Self {
let info = others.clone();
let others = match others.len() {
0 => ContextValue::None,
1 => ContextValue::String(others.pop().unwrap()),
@ -289,7 +236,6 @@ impl Error {
};
Self::new(ErrorKind::ArgumentConflict)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
(ContextKind::PriorArg, others),
@ -298,10 +244,8 @@ impl Error {
}
pub(crate) fn empty_value(cmd: &Command, good_vals: &[&str], arg: String) -> Self {
let info = vec![arg.clone()];
let mut err = Self::new(ErrorKind::EmptyValue)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([(ContextKind::InvalidArg, ContextValue::String(arg))]);
if !good_vals.is_empty() {
err = err.insert_context_unchecked(
@ -313,10 +257,8 @@ impl Error {
}
pub(crate) fn no_equals(cmd: &Command, arg: String, usage: String) -> Self {
let info = vec![arg.clone()];
Self::new(ErrorKind::NoEquals)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
(ContextKind::Usage, ContextValue::String(usage)),
@ -329,13 +271,9 @@ impl Error {
good_vals: &[&str],
arg: String,
) -> Self {
let mut info = vec![arg.clone(), bad_val.clone()];
info.extend(good_vals.iter().map(|s| (*s).to_owned()));
let suggestion = suggestions::did_you_mean(&bad_val, good_vals.iter()).pop();
let mut err = Self::new(ErrorKind::InvalidValue)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
(ContextKind::InvalidValue, ContextValue::String(bad_val)),
@ -360,11 +298,9 @@ impl Error {
name: String,
usage: String,
) -> Self {
let info = vec![subcmd.clone()];
let suggestion = format!("{} -- {}", name, subcmd);
Self::new(ErrorKind::InvalidSubcommand)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidSubcommand, ContextValue::String(subcmd)),
(
@ -380,10 +316,8 @@ impl Error {
}
pub(crate) fn unrecognized_subcommand(cmd: &Command, subcmd: String, usage: String) -> Self {
let info = vec![subcmd.clone()];
Self::new(ErrorKind::UnrecognizedSubcommand)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidSubcommand, ContextValue::String(subcmd)),
(ContextKind::Usage, ContextValue::String(usage)),
@ -395,10 +329,8 @@ impl Error {
required: Vec<String>,
usage: String,
) -> Self {
let info = required.clone();
Self::new(ErrorKind::MissingRequiredArgument)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::Strings(required)),
(ContextKind::Usage, ContextValue::String(usage)),
@ -406,10 +338,8 @@ impl Error {
}
pub(crate) fn missing_subcommand(cmd: &Command, name: String, usage: String) -> Self {
let info = vec![];
Self::new(ErrorKind::MissingSubcommand)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidSubcommand, ContextValue::String(name)),
(ContextKind::Usage, ContextValue::String(usage)),
@ -417,43 +347,14 @@ impl Error {
}
pub(crate) fn invalid_utf8(cmd: &Command, usage: String) -> Self {
let info = vec![];
Self::new(ErrorKind::InvalidUtf8)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([(ContextKind::Usage, ContextValue::String(usage))])
}
pub(crate) fn too_many_occurrences(
cmd: &Command,
arg: String,
max_occurs: usize,
curr_occurs: usize,
usage: String,
) -> Self {
let info = vec![arg.clone(), curr_occurs.to_string(), max_occurs.to_string()];
Self::new(ErrorKind::TooManyOccurrences)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
(
ContextKind::MaxOccurrences,
ContextValue::Number(max_occurs as isize),
),
(
ContextKind::ActualNumValues,
ContextValue::Number(curr_occurs as isize),
),
(ContextKind::Usage, ContextValue::String(usage)),
])
}
pub(crate) fn too_many_values(cmd: &Command, val: String, arg: String, usage: String) -> Self {
let info = vec![arg.clone(), val.clone()];
Self::new(ErrorKind::TooManyValues)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
(ContextKind::InvalidValue, ContextValue::String(val)),
@ -468,10 +369,8 @@ impl Error {
curr_vals: usize,
usage: String,
) -> Self {
let info = vec![arg.clone(), curr_vals.to_string(), min_vals.to_string()];
Self::new(ErrorKind::TooFewValues)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
(
@ -491,9 +390,7 @@ impl Error {
val: String,
err: Box<dyn error::Error + Send + Sync>,
) -> Self {
let info = vec![arg.clone(), val.to_string(), err.to_string()];
Self::new(ErrorKind::ValueValidation)
.set_info(info)
.set_source(err)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
@ -508,10 +405,8 @@ impl Error {
curr_vals: usize,
usage: String,
) -> Self {
let info = vec![arg.clone(), curr_vals.to_string(), num_vals.to_string()];
Self::new(ErrorKind::WrongNumberOfValues)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
(
@ -527,10 +422,8 @@ impl Error {
}
pub(crate) fn unexpected_multiple_usage(cmd: &Command, arg: String, usage: String) -> Self {
let info = vec![arg.clone()];
Self::new(ErrorKind::UnexpectedMultipleUsage)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
(ContextKind::Usage, ContextValue::String(usage)),
@ -543,10 +436,8 @@ impl Error {
did_you_mean: Option<(String, Option<String>)>,
usage: String,
) -> Self {
let info = vec![arg.clone()];
let mut err = Self::new(ErrorKind::UnknownArgument)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
(ContextKind::Usage, ContextValue::String(usage)),
@ -567,10 +458,8 @@ impl Error {
}
pub(crate) fn unnecessary_double_dash(cmd: &Command, arg: String, usage: String) -> Self {
let info = vec![arg.clone()];
Self::new(ErrorKind::UnknownArgument)
.with_cmd(cmd)
.set_info(info)
.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
(ContextKind::TrailingArg, ContextValue::Bool(true)),
@ -578,13 +467,6 @@ impl Error {
])
}
pub(crate) fn argument_not_found_auto(arg: String) -> Self {
let info = vec![arg.clone()];
Self::new(ErrorKind::ArgumentNotFound)
.set_info(info)
.extend_context_unchecked([(ContextKind::InvalidArg, ContextValue::String(arg))])
}
fn formatted(&self) -> Cow<'_, Colorizer> {
if let Some(message) = self.inner.message.as_ref() {
message.formatted()
@ -784,29 +666,6 @@ impl Error {
}
}
ErrorKind::InvalidUtf8 => false,
ErrorKind::TooManyOccurrences => {
let invalid_arg = self.get_context(ContextKind::InvalidArg);
let actual_num_occurs = self.get_context(ContextKind::ActualNumOccurrences);
let max_occurs = self.get_context(ContextKind::MaxOccurrences);
if let (
Some(ContextValue::String(invalid_arg)),
Some(ContextValue::Number(actual_num_occurs)),
Some(ContextValue::Number(max_occurs)),
) = (invalid_arg, actual_num_occurs, max_occurs)
{
let were_provided = Error::singular_or_plural(*actual_num_occurs as usize);
c.none("The argument '");
c.warning(invalid_arg);
c.none("' allows at most ");
c.warning(max_occurs.to_string());
c.none(" occurrences but ");
c.warning(actual_num_occurs.to_string());
c.none(were_provided);
true
} else {
false
}
}
ErrorKind::TooManyValues => {
let invalid_arg = self.get_context(ContextKind::InvalidArg);
let invalid_value = self.get_context(ContextKind::InvalidValue);
@ -956,17 +815,6 @@ impl Error {
false
}
}
ErrorKind::ArgumentNotFound => {
let invalid_arg = self.get_context(ContextKind::InvalidArg);
if let Some(ContextValue::String(invalid_arg)) = invalid_arg {
c.none("The argument '");
c.warning(invalid_arg.to_string());
c.none("' wasn't found");
true
} else {
false
}
}
ErrorKind::DisplayHelp
| ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand
| ErrorKind::DisplayVersion

View file

@ -109,48 +109,15 @@ pub(crate) use crate::util::color::ColorChoice;
pub use crate::derive::{Args, CommandFactory, FromArgMatches, Parser, Subcommand, ValueEnum};
#[allow(deprecated)]
pub use crate::builder::App;
pub use crate::builder::{AppFlags, AppSettings, ArgFlags, ArgSettings, PossibleValue, ValueHint};
pub use crate::builder::{AppFlags, AppSettings, PossibleValue, ValueHint};
pub use crate::error::{ErrorKind, Result};
#[allow(deprecated)]
pub use crate::parser::{Indices, OsValues, ValueSource, Values};
#[cfg(feature = "yaml")]
#[doc(hidden)]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Deprecated in Issue #3087, maybe clap::Parser would fit your use case?"
)
)]
#[doc(hidden)]
pub use yaml_rust::YamlLoader;
pub use crate::parser::{Indices, ValueSource};
#[cfg(feature = "derive")]
#[doc(hidden)]
pub use clap_derive::{self, *};
/// Deprecated, replaced with [`CommandFactory`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `CommandFactory`")
)]
pub use CommandFactory as IntoApp;
/// Deprecated, replaced with [`Parser`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `Parser`")
)]
#[doc(hidden)]
pub use Parser as StructOpt;
/// Deprecated, replaced with [`ValueEnum`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ValueEnum`")
)]
pub use ValueEnum as ArgEnum;
#[cfg(feature = "unstable-doc")]
pub mod _cookbook;
#[cfg(feature = "unstable-doc")]
@ -175,9 +142,6 @@ mod macros;
mod derive;
#[cfg(feature = "regex")]
pub use crate::builder::RegexRef;
pub mod builder;
pub mod error;
pub mod parser;
@ -189,44 +153,3 @@ mod util;
const INTERNAL_ERROR_MSG: &str = "Fatal internal error. Please consider filing a bug \
report at https://github.com/clap-rs/clap/issues";
const INVALID_UTF8: &str = "unexpected invalid UTF-8 code point";
/// Deprecated, replaced with [`Command::new`], unless you were looking for [Subcommand]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Replaced with `Command::new` unless you intended the `Subcommand` trait"
)
)]
#[doc(hidden)]
#[derive(Debug, Copy, Clone)]
pub struct SubCommand {}
#[allow(deprecated)]
impl SubCommand {
/// Deprecated, replaced with [`Command::new`].
/// Did you mean Subcommand (lower-case c)?
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `Command::new`")
)]
#[doc(hidden)]
pub fn with_name<'help>(name: &str) -> App<'help> {
Command::new(name)
}
/// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case?
#[cfg(feature = "yaml")]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Deprecated in Issue #3087, maybe clap::Parser would fit your use case?"
)
)]
#[doc(hidden)]
pub fn from_yaml(yaml: &yaml_rust::Yaml) -> App {
#![allow(deprecated)]
Command::from_yaml(yaml)
}
}

View file

@ -1,207 +1,3 @@
/// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case?
#[cfg(feature = "yaml")]
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Deprecated in Issue #3087, maybe clap::Parser would fit your use case?"
)
)]
#[doc(hidden)]
#[macro_export]
macro_rules! load_yaml {
($yaml:expr) => {
&$crate::YamlLoader::load_from_str(include_str!($yaml)).expect("failed to load YAML file")
[0]
};
}
/// Deprecated, replaced with [`ArgMatches::value_of_t`][crate::ArgMatches::value_of_t]
#[macro_export]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::get_one`")
)]
#[doc(hidden)]
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]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::get_one`")
)]
#[doc(hidden)]
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]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::get_many`")
)]
#[doc(hidden)]
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]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::get_many`")
)]
#[doc(hidden)]
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)
};
}
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `ValueEnum`")
)]
#[doc(hidden)]
#[macro_export]
macro_rules! _clap_count_exprs {
() => { 0 };
($e:expr) => { 1 };
($e:expr, $($es:expr),+) => { 1 + $crate::_clap_count_exprs!($($es),*) };
}
/// Deprecated, replaced with [`ArgEnum`][crate::ArgEnum]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.0.0", note = "Replaced with `ValueEnum`")
)]
#[doc(hidden)]
#[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`
///
@ -359,46 +155,6 @@ macro_rules! command {
}};
}
/// Deprecated, replaced with [`clap::command!`][crate::command]
#[cfg(feature = "cargo")]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.1.0", note = "Replaced with `clap::command!")
)]
#[macro_export]
macro_rules! app_from_crate {
() => {{
let mut cmd = $crate::Command::new($crate::crate_name!()).version($crate::crate_version!());
let author = $crate::crate_authors!(", ");
if !author.is_empty() {
cmd = cmd.author(author)
}
let about = $crate::crate_description!();
if !about.is_empty() {
cmd = cmd.about(about)
}
cmd
}};
($sep:expr) => {{
let mut cmd = $crate::Command::new($crate::crate_name!()).version($crate::crate_version!());
let author = $crate::crate_authors!($sep);
if !author.is_empty() {
cmd = cmd.author(author)
}
let about = $crate::crate_description!();
if !about.is_empty() {
cmd = cmd.about(about)
}
cmd
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! arg_impl {
@ -706,7 +462,7 @@ macro_rules! arg_impl {
/// 2. Long
/// 3. Value Name
///
/// See [`Arg::name`][crate::Arg::name].
/// See [`Arg::id`][crate::Arg::id].
///
/// ### Short
///
@ -773,168 +529,6 @@ macro_rules! arg {
}};
}
/// Deprecated, replaced with [`clap::Parser`][crate::Parser] and [`clap::arg!`][crate::arg] (Issue clap-rs/clap#2835)
#[cfg_attr(
feature = "deprecated",
deprecated(
since = "3.0.0",
note = "Replaced with `clap::Parser` for a declarative API (Issue clap-rs/clap#2835)"
)
)]
#[doc(hidden)]
#[macro_export]
macro_rules! clap_app {
(@app ($builder:expr)) => { $builder };
(@app ($builder:expr) (@arg ($name:expr): $($tail:tt)*) $($tt:tt)*) => {
$crate::clap_app!{ @app
($builder.arg(
$crate::clap_app!{ @arg ($crate::Arg::new($name)) (-) $($tail)* }))
$($tt)*
}
};
(@app ($builder:expr) (@arg $name:ident: $($tail:tt)*) $($tt:tt)*) => {
$crate::clap_app!{ @app
($builder.arg(
$crate::clap_app!{ @arg ($crate::Arg::new(stringify!($name))) (-) $($tail)* }))
$($tt)*
}
};
(@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
(@app ($builder:expr) (@attributes $($attr:tt)*) $($tt:tt)*) => {
$crate::clap_app!{ @app ($crate::clap_app!{ @arg ($builder) $($attr)* }) $($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))) $($tail)* })
$($tt)*
}
};
(@app ($builder:expr) (@group $name:ident !$ident:ident => $($tail:tt)*) $($tt:tt)*) => {
$crate::clap_app!{ @app
($crate::clap_app!{ @group ($builder, $crate::ArgGroup::new(stringify!($name)).$ident(false)) $($tail)* })
$($tt)*
}
};
(@app ($builder:expr) (@group $name:ident +$ident:ident => $($tail:tt)*) $($tt:tt)*) => {
$crate::clap_app!{ @app
($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(
$crate::clap_app!{ @app ($crate::Command::new(stringify!($name))) $($tail)* }
))
$($tt)*
}
};
// 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
(@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, $crate::clap_app!{ @arg ($group) (-) $($attr)* }) $($tt)* }
};
(@group ($builder:expr, $group:expr) (@arg $name:ident: $($tail:tt)*) $($tt:tt)*) => {
$crate::clap_app!{ @group
($crate::clap_app!{ @app ($builder) (@arg $name: $($tail)*) },
$group.arg(stringify!($name)))
$($tt)*
}
};
// No more tokens to munch
(@arg ($arg:expr) $modes:tt) => { $arg };
// 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:ident $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg.long(stringify!($long))) $modes $($tail)* }
};
(@arg ($arg:expr) $modes:tt -$short:ident $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg.short(stringify!($short).chars().next().unwrap())) $modes $($tail)* }
};
(@arg ($arg:expr) (-) <$var:ident> $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) +takes_value +required $($tail)* }
};
(@arg ($arg:expr) (+) <$var:ident> $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) $($tail)* }
};
(@arg ($arg:expr) (-) [$var:ident] $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) +takes_value $($tail)* }
};
(@arg ($arg:expr) (+) [$var:ident] $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) $($tail)* }
};
(@arg ($arg:expr) $modes:tt ... $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg) $modes +multiple +takes_value $($tail)* }
};
// 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)
(@arg ($arg:expr) $modes:tt !$ident:ident $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg.$ident(false)) $modes $($tail)* }
};
// +foo -> .foo(true)
(@arg ($arg:expr) $modes:tt +$ident:ident $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg.$ident(true)) $modes $($tail)* }
};
// 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
(@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: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")`
(@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",)`
(@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:ident => $($tail:tt)*) => {
$crate::clap_app!{ @app ($crate::Command::new(stringify!($name))) $($tail)* }
};
// Start the magic
(($name:expr) => $($tail:tt)*) => {{
$crate::clap_app!{ @app ($crate::Command::new($name)) $($tail)*}
}};
($name:ident => $($tail:tt)*) => {{
$crate::clap_app!{ @app ($crate::Command::new(stringify!($name))) $($tail)*}
}};
}
macro_rules! impl_settings {
($settings:ident, $flags:ident,
$(
@ -1031,14 +625,6 @@ macro_rules! impl_settings {
}
}
// Convenience for writing to stderr thanks to https://github.com/BurntSushi
macro_rules! wlnerr {
($($arg:tt)*) => ({
use std::io::{Write, stderr};
writeln!(&mut stderr(), $($arg)*).ok();
})
}
#[cfg(feature = "debug")]
macro_rules! debug {
($($arg:tt)*) => ({

View file

@ -481,7 +481,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
if let Some(arg) = arg {
const DASH_SPACE: usize = "- ".len();
const COLON_SPACE: usize = ": ".len();
let possible_vals = arg.get_possible_values2();
let possible_vals = arg.get_possible_values();
if self.use_long
&& !arg.is_hide_possible_values_set()
&& possible_vals.iter().any(PossibleValue::should_show_help)
@ -660,7 +660,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
}
let possible_vals = a.get_possible_values2();
let possible_vals = a.get_possible_values();
if !(a.is_hide_possible_values_set()
|| possible_vals.is_empty()
|| cfg!(feature = "unstable-v4")

View file

@ -1,11 +1,9 @@
// Std
use std::any::Any;
use std::borrow::Cow;
use std::ffi::{OsStr, OsString};
use std::fmt::{Debug, Display};
use std::fmt::Debug;
use std::iter::{Cloned, Flatten, Map};
use std::slice::Iter;
use std::str::FromStr;
// Third Party
use indexmap::IndexMap;
@ -17,7 +15,6 @@ use crate::parser::MatchedArg;
use crate::parser::MatchesError;
use crate::parser::ValueSource;
use crate::util::{Id, Key};
use crate::Error;
use crate::INTERNAL_ERROR_MSG;
/// Container for parse results.
@ -341,62 +338,6 @@ impl ArgMatches {
!self.args.is_empty()
}
/// Deprecated, replaced with [`ArgMatches::get_one()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")
)]
#[cfg_attr(debug_assertions, track_caller)]
pub fn value_of<T: Key>(&self, id: T) -> Option<&str> {
let id = Id::from(id);
let arg = self.get_arg(&id)?;
let v = unwrap_string_arg(&id, arg.first()?);
Some(v)
}
/// Deprecated, replaced with [`ArgMatches::get_one()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")
)]
#[cfg_attr(debug_assertions, track_caller)]
pub fn value_of_lossy<T: Key>(&self, id: T) -> Option<Cow<'_, str>> {
let id = Id::from(id);
let arg = self.get_arg(&id)?;
let v = unwrap_os_string_arg(&id, arg.first()?);
Some(v.to_string_lossy())
}
/// Deprecated, replaced with [`ArgMatches::get_one()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")
)]
#[cfg_attr(debug_assertions, track_caller)]
pub fn value_of_os<T: Key>(&self, id: T) -> Option<&OsStr> {
let id = Id::from(id);
let arg = self.get_arg(&id)?;
let v = unwrap_os_string_arg(&id, arg.first()?);
Some(v)
}
/// Deprecated, replaced with [`ArgMatches::get_many()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
)]
#[cfg_attr(debug_assertions, track_caller)]
pub fn values_of<T: Key>(&self, id: T) -> Option<Values> {
#![allow(deprecated)]
let id = Id::from(id);
let arg = self.get_arg(&id)?;
let v = Values {
iter: arg.vals_flatten().map(unwrap_string),
len: arg.num_vals(),
};
Some(v)
}
/// Get an [`Iterator`] over groups of values of a specific option.
///
/// specifically grouped by the occurrences of the options.
@ -442,119 +383,6 @@ impl ArgMatches {
Some(v)
}
/// Deprecated, replaced with [`ArgMatches::get_many()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
)]
#[cfg_attr(debug_assertions, track_caller)]
pub fn values_of_lossy<T: Key>(&self, id: T) -> Option<Vec<String>> {
let id = Id::from(id);
let arg = self.get_arg(&id)?;
let v = arg
.vals_flatten()
.map(|v| unwrap_os_string_arg(&id, v).to_string_lossy().into_owned())
.collect();
Some(v)
}
/// Deprecated, replaced with [`ArgMatches::get_many()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
)]
#[cfg_attr(debug_assertions, track_caller)]
pub fn values_of_os<T: Key>(&self, id: T) -> Option<OsValues> {
#![allow(deprecated)]
let id = Id::from(id);
let arg = self.get_arg(&id)?;
let v = OsValues {
iter: arg.vals_flatten().map(unwrap_os_string),
len: arg.num_vals(),
};
Some(v)
}
/// Deprecated, replaced with [`ArgMatches::get_one()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")
)]
#[cfg_attr(debug_assertions, track_caller)]
pub fn value_of_t<R>(&self, name: &str) -> Result<R, Error>
where
R: FromStr,
<R as FromStr>::Err: Display,
{
#![allow(deprecated)]
let v = self
.value_of(name)
.ok_or_else(|| Error::argument_not_found_auto(name.to_string()))?;
v.parse::<R>().map_err(|e| {
let message = format!(
"The argument '{}' isn't a valid value for '{}': {}",
v, name, e
);
Error::value_validation(name.to_string(), v.to_string(), message.into())
})
}
/// Deprecated, replaced with [`ArgMatches::get_one()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")
)]
#[cfg_attr(debug_assertions, track_caller)]
pub fn value_of_t_or_exit<R>(&self, name: &str) -> R
where
R: FromStr,
<R as FromStr>::Err: Display,
{
#![allow(deprecated)]
self.value_of_t(name).unwrap_or_else(|e| e.exit())
}
/// Deprecated, replaced with [`ArgMatches::get_many()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
)]
#[cfg_attr(debug_assertions, track_caller)]
pub fn values_of_t<R>(&self, name: &str) -> Result<Vec<R>, Error>
where
R: FromStr,
<R as FromStr>::Err: Display,
{
#![allow(deprecated)]
let v = self
.values_of(name)
.ok_or_else(|| Error::argument_not_found_auto(name.to_string()))?;
v.map(|v| {
v.parse::<R>().map_err(|e| {
let message = format!("The argument '{}' isn't a valid value: {}", v, e);
Error::value_validation(name.to_string(), v.to_string(), message.into())
})
})
.collect()
}
/// Deprecated, replaced with [`ArgMatches::get_many()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
)]
#[cfg_attr(debug_assertions, track_caller)]
pub fn values_of_t_or_exit<R>(&self, name: &str) -> Vec<R>
where
R: FromStr,
<R as FromStr>::Err: Display,
{
#![allow(deprecated)]
self.values_of_t(name).unwrap_or_else(|e| e.exit())
}
/// Deprecated, replaced with [`ArgAction::SetTrue`][crate::ArgAction] or
/// [`ArgMatches::contains_id`].
#[cfg_attr(
@ -1499,52 +1327,6 @@ impl Default for RawValues<'_> {
// commit: be5e1fa3c26e351761b33010ddbdaf5f05dbcc33
// license: MIT - Copyright (c) 2015 The Rust Project Developers
/// Deprecated, replaced with [`ArgMatches::get_many()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
)]
#[derive(Clone, Debug)]
pub struct Values<'a> {
#[allow(clippy::type_complexity)]
iter: Map<Flatten<Iter<'a, Vec<AnyValue>>>, for<'r> fn(&'r AnyValue) -> &'r str>,
len: usize,
}
#[allow(deprecated)]
impl<'a> Iterator for Values<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
#[allow(deprecated)]
impl<'a> DoubleEndedIterator for Values<'a> {
fn next_back(&mut self) -> Option<&'a str> {
self.iter.next_back()
}
}
#[allow(deprecated)]
impl<'a> ExactSizeIterator for Values<'a> {}
/// Creates an empty iterator.
#[allow(deprecated)]
impl<'a> Default for Values<'a> {
fn default() -> Self {
static EMPTY: [Vec<AnyValue>; 0] = [];
Values {
iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
len: 0,
}
}
}
#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub struct GroupedValues<'a> {
@ -1584,52 +1366,6 @@ impl<'a> Default for GroupedValues<'a> {
}
}
/// Deprecated, replaced with [`ArgMatches::get_many()`]
#[cfg_attr(
feature = "deprecated",
deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
)]
#[derive(Clone, Debug)]
pub struct OsValues<'a> {
#[allow(clippy::type_complexity)]
iter: Map<Flatten<Iter<'a, Vec<AnyValue>>>, fn(&AnyValue) -> &OsStr>,
len: usize,
}
#[allow(deprecated)]
impl<'a> Iterator for OsValues<'a> {
type Item = &'a OsStr;
fn next(&mut self) -> Option<&'a OsStr> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
#[allow(deprecated)]
impl<'a> DoubleEndedIterator for OsValues<'a> {
fn next_back(&mut self) -> Option<&'a OsStr> {
self.iter.next_back()
}
}
#[allow(deprecated)]
impl<'a> ExactSizeIterator for OsValues<'a> {}
/// Creates an empty iterator.
#[allow(deprecated)]
impl Default for OsValues<'_> {
fn default() -> Self {
static EMPTY: [Vec<AnyValue>; 0] = [];
OsValues {
iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
len: 0,
}
}
}
/// Iterate over indices for where an argument appeared when parsing, via [`ArgMatches::indices_of`]
///
/// # Examples
@ -1687,6 +1423,7 @@ impl<'a> Default for Indices<'a> {
}
}
#[cfg(feature = "unstable-grouped")]
#[cfg_attr(debug_assertions, track_caller)]
#[inline]
fn unwrap_string(value: &AnyValue) -> &str {
@ -1698,45 +1435,6 @@ fn unwrap_string(value: &AnyValue) -> &str {
}
}
#[cfg_attr(debug_assertions, track_caller)]
#[inline]
fn unwrap_string_arg<'v>(id: &Id, value: &'v AnyValue) -> &'v str {
match value.downcast_ref::<String>() {
Some(value) => value,
None => {
panic!(
"Must use `_os` lookups with `Arg::allow_invalid_utf8` at `{:?}`",
id
)
}
}
}
#[cfg_attr(debug_assertions, track_caller)]
#[inline]
fn unwrap_os_string(value: &AnyValue) -> &OsStr {
match value.downcast_ref::<OsString>() {
Some(value) => value,
None => {
panic!("Must use `Arg::allow_invalid_utf8` with `_os` lookups",)
}
}
}
#[cfg_attr(debug_assertions, track_caller)]
#[inline]
fn unwrap_os_string_arg<'v>(id: &Id, value: &'v AnyValue) -> &'v OsStr {
match value.downcast_ref::<OsString>() {
Some(value) => value,
None => {
panic!(
"Must use `Arg::allow_invalid_utf8` with `_os` lookups at `{:?}`",
id
)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
@ -1746,20 +1444,6 @@ mod tests {
static_assertions::assert_impl_all!(ArgMatches: Send, Sync, Unpin);
}
#[test]
fn test_default_values() {
#![allow(deprecated)]
let mut values: Values = Values::default();
assert_eq!(values.next(), None);
}
#[test]
fn test_default_osvalues() {
#![allow(deprecated)]
let mut values: OsValues = OsValues::default();
assert_eq!(values.next(), None);
}
#[test]
fn test_default_raw_values() {
let mut values: RawValues = Default::default();

View file

@ -12,6 +12,3 @@ pub use value_source::ValueSource;
pub(crate) use any_value::AnyValue;
pub(crate) use arg_matches::SubCommand;
pub(crate) use matched_arg::MatchedArg;
#[allow(deprecated)]
pub use arg_matches::{OsValues, Values};

View file

@ -22,6 +22,3 @@ pub use self::matches::RawValues;
pub use self::matches::ValuesRef;
pub use self::matches::{ArgMatches, Indices, ValueSource};
pub use error::MatchesError;
#[allow(deprecated)]
pub use self::matches::{OsValues, Values};

View file

@ -88,82 +88,6 @@ impl<'help, 'cmd> Validator<'help, 'cmd> {
Ok(())
}
fn validate_arg_values(&self, arg: &Arg, ma: &MatchedArg) -> ClapResult<()> {
debug!("Validator::validate_arg_values: arg={:?}", arg.name);
for val in ma.raw_vals_flatten() {
if !arg.possible_vals.is_empty() {
debug!(
"Validator::validate_arg_values: possible_vals={:?}",
arg.possible_vals
);
let val_str = val.to_string_lossy();
let ok = arg
.possible_vals
.iter()
.any(|pv| pv.matches(&val_str, arg.is_ignore_case_set()));
if !ok {
return Err(Error::invalid_value(
self.cmd,
val_str.into_owned(),
&arg.possible_vals
.iter()
.filter(|pv| !pv.is_hide_set())
.map(PossibleValue::get_name)
.collect::<Vec<_>>(),
arg.to_string(),
));
}
}
{
#![allow(deprecated)]
if arg.is_forbid_empty_values_set() && val.is_empty() {
debug!("Validator::validate_arg_values: illegal empty val found");
return Err(Error::empty_value(
self.cmd,
&get_possible_values(arg)
.iter()
.filter(|pv| !pv.is_hide_set())
.map(PossibleValue::get_name)
.collect::<Vec<_>>(),
arg.to_string(),
));
}
}
if let Some(ref vtor) = arg.validator {
debug!("Validator::validate_arg_values: checking validator...");
let mut vtor = vtor.lock().unwrap();
if let Err(e) = vtor(&*val.to_string_lossy()) {
debug!("error");
return Err(Error::value_validation(
arg.to_string(),
val.to_string_lossy().into_owned(),
e,
)
.with_cmd(self.cmd));
} else {
debug!("good");
}
}
if let Some(ref vtor) = arg.validator_os {
debug!("Validator::validate_arg_values: checking validator_os...");
let mut vtor = vtor.lock().unwrap();
if let Err(e) = vtor(val) {
debug!("error");
return Err(Error::value_validation(
arg.to_string(),
val.to_string_lossy().into(),
e,
)
.with_cmd(self.cmd));
} else {
debug!("good");
}
}
}
Ok(())
}
fn validate_conflicts(
&mut self,
matcher: &ArgMatcher,
@ -322,7 +246,6 @@ impl<'help, 'cmd> Validator<'help, 'cmd> {
);
if let Some(arg) = self.cmd.find(name) {
self.validate_arg_num_vals(arg, ma)?;
self.validate_arg_values(arg, ma)?;
self.validate_arg_num_occurs(arg, ma)?;
}
Ok(())
@ -348,24 +271,6 @@ impl<'help, 'cmd> Validator<'help, 'cmd> {
.create_usage_with_title(&[]),
));
}
if let Some(max_occurs) = a.max_occurs {
debug!(
"Validator::validate_arg_num_occurs: max_occurs set...{}",
max_occurs
);
let occurs = ma.get_occurrences() as usize;
if occurs > max_occurs {
return Err(Error::too_many_occurrences(
self.cmd,
a.to_string(),
max_occurs,
occurs,
Usage::new(self.cmd)
.required(&self.required)
.create_usage_with_title(&[]),
));
}
}
Ok(())
}
@ -676,13 +581,8 @@ impl Conflicts {
}
fn get_possible_values<'help>(a: &Arg<'help>) -> Vec<PossibleValue<'help>> {
#![allow(deprecated)]
if !a.is_takes_value_set() {
vec![]
} else if let Some(pvs) = a.get_possible_values() {
// Check old first in case the user explicitly set possible values and the derive inferred
// a `ValueParser` with some.
pvs.to_vec()
} else {
a.get_value_parser()
.possible_values()

View file

@ -1,28 +0,0 @@
#![cfg(feature = "cargo")]
#![allow(deprecated)]
use clap::{app_from_crate, error::ErrorKind};
static EVERYTHING: &str = "clap {{version}}
A simple to use, efficient, and full-featured Command Line Argument Parser
USAGE:
clap
OPTIONS:
-h, --help Print help information
-V, --version Print version information
";
#[test]
fn app_from_crate() {
let res = app_from_crate!().try_get_matches_from(vec!["clap", "--help"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayHelp);
assert_eq!(
err.to_string(),
EVERYTHING.replace("{{version}}", env!("CARGO_PKG_VERSION"))
);
}

View file

@ -81,72 +81,6 @@ SUBCOMMANDS:
info
";
#[test]
fn setting() {
#![allow(deprecated)]
let m = Command::new("setting").args_override_self(true);
assert!(m.is_set(AppSettings::AllArgsOverrideSelf));
}
#[test]
fn global_setting() {
#![allow(deprecated)]
let m = Command::new("global_setting").args_override_self(true);
assert!(m.is_set(AppSettings::AllArgsOverrideSelf));
}
#[test]
fn unset_setting() {
#![allow(deprecated)]
let m = Command::new("unset_setting").args_override_self(true);
assert!(m.is_set(AppSettings::AllArgsOverrideSelf));
let m = m.args_override_self(false);
assert!(!m.is_set(AppSettings::AllArgsOverrideSelf), "{:#?}", m);
}
#[test]
fn unset_global_setting() {
#![allow(deprecated)]
let m = Command::new("unset_global_setting").args_override_self(true);
assert!(m.is_set(AppSettings::AllArgsOverrideSelf));
let m = m.args_override_self(false);
assert!(!m.is_set(AppSettings::AllArgsOverrideSelf), "{:#?}", m);
}
#[test]
fn setting_bitor() {
#![allow(deprecated)]
let m = Command::new("setting_bitor").setting(
AppSettings::InferSubcommands | AppSettings::Hidden | AppSettings::DisableHelpSubcommand,
);
assert!(m.is_set(AppSettings::InferSubcommands));
assert!(m.is_set(AppSettings::Hidden));
assert!(m.is_set(AppSettings::DisableHelpSubcommand));
}
#[test]
fn unset_setting_bitor() {
#![allow(deprecated)]
let m = Command::new("unset_setting_bitor")
.setting(AppSettings::InferSubcommands)
.setting(AppSettings::Hidden)
.setting(AppSettings::DisableHelpSubcommand);
assert!(m.is_set(AppSettings::InferSubcommands));
assert!(m.is_set(AppSettings::Hidden));
assert!(m.is_set(AppSettings::DisableHelpSubcommand));
let m = m.unset_setting(
AppSettings::InferSubcommands | AppSettings::Hidden | AppSettings::DisableHelpSubcommand,
);
assert!(!m.is_set(AppSettings::InferSubcommands), "{:#?}", m);
assert!(!m.is_set(AppSettings::Hidden), "{:#?}", m);
assert!(!m.is_set(AppSettings::DisableHelpSubcommand), "{:#?}", m);
}
#[test]
fn sub_command_negate_required() {
Command::new("sub_command_negate")

View file

@ -1,44 +0,0 @@
#![allow(deprecated)]
use clap::{Arg, ArgSettings};
#[test]
fn setting() {
let m = Arg::new("setting").setting(ArgSettings::Required);
assert!(m.is_required_set());
}
#[test]
fn unset_setting() {
let m = Arg::new("unset_setting").setting(ArgSettings::Required);
assert!(m.is_required_set());
let m = m.unset_setting(ArgSettings::Required);
assert!(!m.is_required_set(), "{:#?}", m);
}
#[test]
fn setting_bitor() {
let m = Arg::new("setting_bitor")
.setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
assert!(m.is_required_set());
assert!(m.is_hide_set());
assert!(m.is_last_set());
}
#[test]
fn unset_setting_bitor() {
let m = Arg::new("unset_setting_bitor")
.setting(ArgSettings::Required)
.setting(ArgSettings::Hidden)
.setting(ArgSettings::Last);
assert!(m.is_required_set());
assert!(m.is_hide_set());
assert!(m.is_last_set());
let m = m.unset_setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
assert!(!m.is_required_set(), "{:#?}", m);
assert!(!m.is_hide_set(), "{:#?}", m);
assert!(!m.is_last_set(), "{:#?}", m);
}

View file

@ -250,29 +250,6 @@ fn issue_1374() {
assert_eq!(vs.collect::<Vec<_>>(), vec!["a", "b", "c", "d"]);
}
#[test]
fn issue_2171_deprecated() {
#![allow(deprecated)]
let schema = Command::new("ripgrep#1701 reproducer")
.args_override_self(true)
.arg(Arg::new("pretty").short('p').long("pretty"))
.arg(Arg::new("search_zip").short('z').long("search-zip"));
let test_args = &[
vec!["reproducer", "-pz", "-p"],
vec!["reproducer", "-pzp"],
vec!["reproducer", "-zpp"],
vec!["reproducer", "-pp", "-z"],
vec!["reproducer", "-p", "-p", "-z"],
vec!["reproducer", "-p", "-pz"],
vec!["reproducer", "-ppz"],
];
for argv in test_args {
let _ = schema.clone().try_get_matches_from(argv).unwrap();
}
}
#[test]
fn issue_2171() {
let schema = Command::new("ripgrep#1701 reproducer")

View file

@ -1,505 +0,0 @@
#![allow(clippy::bool_assert_comparison)]
use clap::Arg;
use clap::ArgAction;
use clap::Command;
#[test]
fn set() {
let cmd = Command::new("test").arg(Arg::new("mammal").long("mammal").action(ArgAction::Set));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(matches.get_one::<String>("mammal"), None);
assert_eq!(matches.is_present("mammal"), false);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), None);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal", "dog"])
.unwrap();
assert_eq!(matches.get_one::<String>("mammal").unwrap(), "dog");
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(2));
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal", "dog", "--mammal", "cat"])
.unwrap();
assert_eq!(matches.get_one::<String>("mammal").unwrap(), "cat");
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(4));
}
#[test]
fn append() {
let cmd = Command::new("test").arg(Arg::new("mammal").long("mammal").action(ArgAction::Append));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(matches.get_one::<String>("mammal"), None);
assert_eq!(matches.is_present("mammal"), false);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), None);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal", "dog"])
.unwrap();
assert_eq!(matches.get_one::<String>("mammal").unwrap(), "dog");
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(
matches.indices_of("mammal").unwrap().collect::<Vec<_>>(),
vec![2]
);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal", "dog", "--mammal", "cat"])
.unwrap();
assert_eq!(
matches
.get_many::<String>("mammal")
.unwrap()
.map(|s| s.as_str())
.collect::<Vec<_>>(),
vec!["dog", "cat"]
);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(
matches.indices_of("mammal").unwrap().collect::<Vec<_>>(),
vec![2, 4]
);
}
#[test]
fn set_true() {
let cmd =
Command::new("test").arg(Arg::new("mammal").long("mammal").action(ArgAction::SetTrue));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(2));
}
#[test]
fn set_true_with_explicit_default_value() {
let cmd = Command::new("test").arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::SetTrue)
.default_value("false"),
);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
}
#[test]
fn set_true_with_default_value_if_present() {
let cmd = Command::new("test")
.arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::SetTrue)
.default_value_if("dog", None, Some("true")),
)
.arg(Arg::new("dog").long("dog").action(ArgAction::SetTrue));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
let matches = cmd.clone().try_get_matches_from(["test", "--dog"]).unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
}
#[test]
fn set_true_with_default_value_if_value() {
let cmd = Command::new("test")
.arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::SetTrue)
.default_value_if("dog", Some("true"), Some("true")),
)
.arg(Arg::new("dog").long("dog").action(ArgAction::SetTrue));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
let matches = cmd.clone().try_get_matches_from(["test", "--dog"]).unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
}
#[test]
fn set_true_with_required_if_eq() {
let cmd = Command::new("test")
.arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::SetTrue)
.required_if_eq("dog", "true"),
)
.arg(Arg::new("dog").long("dog").action(ArgAction::SetTrue));
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
cmd.clone()
.try_get_matches_from(["test", "--dog"])
.unwrap_err();
let matches = cmd
.clone()
.try_get_matches_from(["test", "--dog", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
}
#[test]
fn set_false() {
let cmd = Command::new("test").arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::SetFalse),
);
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(2));
}
#[test]
fn set_false_with_explicit_default_value() {
let cmd = Command::new("test").arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::SetFalse)
.default_value("true"),
);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
}
#[test]
fn set_false_with_default_value_if_present() {
let cmd = Command::new("test")
.arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::SetFalse)
.default_value_if("dog", None, Some("false")),
)
.arg(Arg::new("dog").long("dog").action(ArgAction::SetFalse));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
let matches = cmd.clone().try_get_matches_from(["test", "--dog"]).unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
}
#[test]
fn set_false_with_default_value_if_value() {
let cmd = Command::new("test")
.arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::SetFalse)
.default_value_if("dog", Some("false"), Some("false")),
)
.arg(Arg::new("dog").long("dog").action(ArgAction::SetFalse));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), true);
let matches = cmd.clone().try_get_matches_from(["test", "--dog"]).unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), false);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<bool>("dog").unwrap(), true);
assert_eq!(*matches.get_one::<bool>("mammal").unwrap(), false);
}
#[test]
fn count() {
let cmd = Command::new("test").arg(Arg::new("mammal").long("mammal").action(ArgAction::Count));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 0);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 1);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 2);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(2));
}
#[test]
fn count_with_explicit_default_value() {
let cmd = Command::new("test").arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::Count)
.default_value("10"),
);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 1);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 10);
assert_eq!(matches.is_present("mammal"), true);
#[allow(deprecated)]
{
assert_eq!(matches.occurrences_of("mammal"), 0);
}
assert_eq!(matches.index_of("mammal"), Some(1));
}
#[test]
fn count_with_default_value_if_present() {
let cmd = Command::new("test")
.arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::Count)
.default_value_if("dog", None, Some("10")),
)
.arg(Arg::new("dog").long("dog").action(ArgAction::Count));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<u8>("dog").unwrap(), 0);
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 0);
let matches = cmd.clone().try_get_matches_from(["test", "--dog"]).unwrap();
assert_eq!(*matches.get_one::<u8>("dog").unwrap(), 1);
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 10);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<u8>("dog").unwrap(), 0);
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 1);
}
#[test]
fn count_with_default_value_if_value() {
let cmd = Command::new("test")
.arg(
Arg::new("mammal")
.long("mammal")
.action(ArgAction::Count)
.default_value_if("dog", Some("2"), Some("10")),
)
.arg(Arg::new("dog").long("dog").action(ArgAction::Count));
let matches = cmd.clone().try_get_matches_from(["test"]).unwrap();
assert_eq!(*matches.get_one::<u8>("dog").unwrap(), 0);
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 0);
let matches = cmd.clone().try_get_matches_from(["test", "--dog"]).unwrap();
assert_eq!(*matches.get_one::<u8>("dog").unwrap(), 1);
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 0);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--dog", "--dog"])
.unwrap();
assert_eq!(*matches.get_one::<u8>("dog").unwrap(), 2);
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 10);
let matches = cmd
.clone()
.try_get_matches_from(["test", "--mammal"])
.unwrap();
assert_eq!(*matches.get_one::<u8>("dog").unwrap(), 0);
assert_eq!(*matches.get_one::<u8>("mammal").unwrap(), 1);
}

View file

@ -1,28 +0,0 @@
#![cfg(feature = "cargo")]
#![allow(deprecated)]
use clap::{app_from_crate, error::ErrorKind};
static EVERYTHING: &str = "clap {{version}}
A simple to use, efficient, and full-featured Command Line Argument Parser
USAGE:
clap
OPTIONS:
-h, --help Print help information
-V, --version Print version information
";
#[test]
fn app_from_crate() {
let res = app_from_crate!().try_get_matches_from(vec!["clap", "--help"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayHelp);
assert_eq!(
err.to_string(),
EVERYTHING.replace("{{version}}", env!("CARGO_PKG_VERSION"))
);
}

File diff suppressed because it is too large Load diff

View file

@ -1,196 +0,0 @@
use super::utils;
use clap::{arg, Arg, Command};
static SC_VISIBLE_ALIAS_HELP: &str = "ct-test 1.2
Some help
USAGE:
ct test [OPTIONS]
OPTIONS:
-f, --flag [aliases: v_flg, flag2, flg3]
-h, --help Print help information
-o, --opt <opt> [aliases: visible]
-V, --version Print version information
";
static SC_INVISIBLE_ALIAS_HELP: &str = "ct-test 1.2
Some help
USAGE:
ct test [OPTIONS]
OPTIONS:
-f, --flag
-h, --help Print help information
-o, --opt <opt>
-V, --version Print version information
";
#[test]
fn single_alias_of_option() {
let a = Command::new("single_alias")
.arg(
Arg::new("alias")
.long("alias")
.takes_value(true)
.help("single alias")
.alias("new-opt"),
)
.try_get_matches_from(vec!["", "--new-opt", "cool"]);
assert!(a.is_ok(), "{}", a.unwrap_err());
let a = a.unwrap();
assert!(a.is_present("alias"));
assert_eq!(a.value_of("alias").unwrap(), "cool");
}
#[test]
fn multiple_aliases_of_option() {
let a = Command::new("multiple_aliases").arg(
Arg::new("aliases")
.long("aliases")
.takes_value(true)
.help("multiple aliases")
.aliases(&["alias1", "alias2", "alias3"]),
);
let long = a
.clone()
.try_get_matches_from(vec!["", "--aliases", "value"]);
assert!(long.is_ok(), "{}", long.unwrap_err());
let long = long.unwrap();
let als1 = a
.clone()
.try_get_matches_from(vec!["", "--alias1", "value"]);
assert!(als1.is_ok(), "{}", als1.unwrap_err());
let als1 = als1.unwrap();
let als2 = a
.clone()
.try_get_matches_from(vec!["", "--alias2", "value"]);
assert!(als2.is_ok(), "{}", als2.unwrap_err());
let als2 = als2.unwrap();
let als3 = a
.clone()
.try_get_matches_from(vec!["", "--alias3", "value"]);
assert!(als3.is_ok(), "{}", als3.unwrap_err());
let als3 = als3.unwrap();
assert!(long.is_present("aliases"));
assert!(als1.is_present("aliases"));
assert!(als2.is_present("aliases"));
assert!(als3.is_present("aliases"));
assert_eq!(long.value_of("aliases").unwrap(), "value");
assert_eq!(als1.value_of("aliases").unwrap(), "value");
assert_eq!(als2.value_of("aliases").unwrap(), "value");
assert_eq!(als3.value_of("aliases").unwrap(), "value");
}
#[test]
fn single_alias_of_flag() {
let a = Command::new("test")
.arg(Arg::new("flag").long("flag").alias("alias"))
.try_get_matches_from(vec!["", "--alias"]);
assert!(a.is_ok(), "{}", a.unwrap_err());
let a = a.unwrap();
assert!(a.is_present("flag"));
}
#[test]
fn multiple_aliases_of_flag() {
let a = Command::new("test").arg(Arg::new("flag").long("flag").aliases(&[
"invisible",
"set",
"of",
"cool",
"aliases",
]));
let flag = a.clone().try_get_matches_from(vec!["", "--flag"]);
assert!(flag.is_ok(), "{}", flag.unwrap_err());
let flag = flag.unwrap();
let inv = a.clone().try_get_matches_from(vec!["", "--invisible"]);
assert!(inv.is_ok(), "{}", inv.unwrap_err());
let inv = inv.unwrap();
let cool = a.clone().try_get_matches_from(vec!["", "--cool"]);
assert!(cool.is_ok(), "{}", cool.unwrap_err());
let cool = cool.unwrap();
let als = a.clone().try_get_matches_from(vec!["", "--aliases"]);
assert!(als.is_ok(), "{}", als.unwrap_err());
let als = als.unwrap();
assert!(flag.is_present("flag"));
assert!(inv.is_present("flag"));
assert!(cool.is_present("flag"));
assert!(als.is_present("flag"));
}
#[test]
fn alias_on_a_subcommand_option() {
let m = Command::new("test")
.subcommand(
Command::new("some").arg(
Arg::new("test")
.short('t')
.long("test")
.takes_value(true)
.alias("opt")
.help("testing testing"),
),
)
.arg(Arg::new("other").long("other").aliases(&["o1", "o2", "o3"]))
.try_get_matches_from(vec!["test", "some", "--opt", "awesome"])
.unwrap();
assert!(m.subcommand_matches("some").is_some());
let sub_m = m.subcommand_matches("some").unwrap();
assert!(sub_m.is_present("test"));
assert_eq!(sub_m.value_of("test").unwrap(), "awesome");
}
#[test]
fn invisible_arg_aliases_help_output() {
let cmd = Command::new("ct").author("Salim Afiune").subcommand(
Command::new("test")
.about("Some help")
.version("1.2")
.arg(
Arg::new("opt")
.long("opt")
.short('o')
.takes_value(true)
.aliases(&["invisible", "als1", "more"]),
)
.arg(arg!(-f - -flag).aliases(&["unseeable", "flg1", "anyway"])),
);
utils::assert_output(cmd, "ct test --help", SC_INVISIBLE_ALIAS_HELP, false);
}
#[test]
fn visible_arg_aliases_help_output() {
let cmd = Command::new("ct").author("Salim Afiune").subcommand(
Command::new("test")
.about("Some help")
.version("1.2")
.arg(
Arg::new("opt")
.long("opt")
.short('o')
.takes_value(true)
.alias("invisible")
.visible_alias("visible"),
)
.arg(
Arg::new("flg")
.long("flag")
.short('f')
.visible_aliases(&["v_flg", "flag2", "flg3"]),
),
);
utils::assert_output(cmd, "ct test --help", SC_VISIBLE_ALIAS_HELP, false);
}

View file

@ -1,193 +0,0 @@
use super::utils;
use clap::{arg, Arg, Command};
static SC_VISIBLE_ALIAS_HELP: &str = "ct-test 1.2
Some help
USAGE:
ct test [OPTIONS]
OPTIONS:
-f, --flag [aliases: flag1] [short aliases: a, b, 🦆]
-h, --help Print help information
-o, --opt <opt> [short aliases: v]
-V, --version Print version information
";
static SC_INVISIBLE_ALIAS_HELP: &str = "ct-test 1.2
Some help
USAGE:
ct test [OPTIONS]
OPTIONS:
-f, --flag
-h, --help Print help information
-o, --opt <opt>
-V, --version Print version information
";
#[test]
fn single_short_alias_of_option() {
let a = Command::new("single_alias")
.arg(
Arg::new("alias")
.long("alias")
.takes_value(true)
.help("single short alias")
.short_alias('a'),
)
.try_get_matches_from(vec!["", "-a", "cool"]);
assert!(a.is_ok(), "{}", a.unwrap_err());
let a = a.unwrap();
assert!(a.is_present("alias"));
assert_eq!(a.value_of("alias").unwrap(), "cool");
}
#[test]
fn multiple_short_aliases_of_option() {
let a = Command::new("multiple_aliases").arg(
Arg::new("aliases")
.long("aliases")
.takes_value(true)
.help("multiple aliases")
.short_aliases(&['1', '2', '3']),
);
let long = a
.clone()
.try_get_matches_from(vec!["", "--aliases", "value"]);
assert!(long.is_ok(), "{}", long.unwrap_err());
let long = long.unwrap();
let als1 = a.clone().try_get_matches_from(vec!["", "-1", "value"]);
assert!(als1.is_ok(), "{}", als1.unwrap_err());
let als1 = als1.unwrap();
let als2 = a.clone().try_get_matches_from(vec!["", "-2", "value"]);
assert!(als2.is_ok(), "{}", als2.unwrap_err());
let als2 = als2.unwrap();
let als3 = a.clone().try_get_matches_from(vec!["", "-3", "value"]);
assert!(als3.is_ok(), "{}", als3.unwrap_err());
let als3 = als3.unwrap();
assert!(long.is_present("aliases"));
assert!(als1.is_present("aliases"));
assert!(als2.is_present("aliases"));
assert!(als3.is_present("aliases"));
assert_eq!(long.value_of("aliases").unwrap(), "value");
assert_eq!(als1.value_of("aliases").unwrap(), "value");
assert_eq!(als2.value_of("aliases").unwrap(), "value");
assert_eq!(als3.value_of("aliases").unwrap(), "value");
}
#[test]
fn single_short_alias_of_flag() {
let a = Command::new("test")
.arg(Arg::new("flag").long("flag").short_alias('f'))
.try_get_matches_from(vec!["", "-f"]);
assert!(a.is_ok(), "{}", a.unwrap_err());
let a = a.unwrap();
assert!(a.is_present("flag"));
}
#[test]
fn multiple_short_aliases_of_flag() {
let a = Command::new("test").arg(
Arg::new("flag")
.long("flag")
.short_aliases(&['a', 'b', 'c', 'd', 'e']),
);
let flag = a.clone().try_get_matches_from(vec!["", "--flag"]);
assert!(flag.is_ok(), "{}", flag.unwrap_err());
let flag = flag.unwrap();
let als1 = a.clone().try_get_matches_from(vec!["", "-a"]);
assert!(als1.is_ok(), "{}", als1.unwrap_err());
let als1 = als1.unwrap();
let als2 = a.clone().try_get_matches_from(vec!["", "-b"]);
assert!(als2.is_ok(), "{}", als2.unwrap_err());
let als2 = als2.unwrap();
let als3 = a.clone().try_get_matches_from(vec!["", "-c"]);
assert!(als3.is_ok(), "{}", als3.unwrap_err());
let als3 = als3.unwrap();
assert!(flag.is_present("flag"));
assert!(als1.is_present("flag"));
assert!(als2.is_present("flag"));
assert!(als3.is_present("flag"));
}
#[test]
fn short_alias_on_a_subcommand_option() {
let m = Command::new("test")
.subcommand(
Command::new("some").arg(
Arg::new("test")
.short('t')
.long("test")
.takes_value(true)
.short_alias('o')
.help("testing testing"),
),
)
.arg(
Arg::new("other")
.long("other")
.short_aliases(&['1', '2', '3']),
)
.try_get_matches_from(vec!["test", "some", "-o", "awesome"])
.unwrap();
assert!(m.subcommand_matches("some").is_some());
let sub_m = m.subcommand_matches("some").unwrap();
assert!(sub_m.is_present("test"));
assert_eq!(sub_m.value_of("test").unwrap(), "awesome");
}
#[test]
fn invisible_short_arg_aliases_help_output() {
let cmd = Command::new("ct").author("Salim Afiune").subcommand(
Command::new("test")
.about("Some help")
.version("1.2")
.arg(
Arg::new("opt")
.long("opt")
.short('o')
.takes_value(true)
.short_aliases(&['a', 'b', 'c']),
)
.arg(arg!(-f - -flag).short_aliases(&['x', 'y', 'z'])),
);
utils::assert_output(cmd, "ct test --help", SC_INVISIBLE_ALIAS_HELP, false);
}
#[test]
fn visible_short_arg_aliases_help_output() {
let cmd = Command::new("ct").author("Salim Afiune").subcommand(
Command::new("test")
.about("Some help")
.version("1.2")
.arg(
Arg::new("opt")
.long("opt")
.short('o')
.takes_value(true)
.short_alias('i')
.visible_short_alias('v'),
)
.arg(
Arg::new("flg")
.long("flag")
.short('f')
.visible_alias("flag1")
.visible_short_aliases(&['a', 'b', '🦆']),
),
);
utils::assert_output(cmd, "ct test --help", SC_VISIBLE_ALIAS_HELP, false);
}

View file

@ -1,41 +0,0 @@
#[cfg(debug_assertions)]
use clap::{Arg, Command};
#[test]
#[cfg(debug_assertions)]
#[should_panic = "`f` is not an id of an argument or a group."]
fn arg_matches_if_present_wrong_arg() {
let m = Command::new("test")
.arg(Arg::new("flag").short('f'))
.try_get_matches_from(&["test", "-f"])
.unwrap();
assert!(m.is_present("flag"));
m.is_present("f");
}
#[test]
#[cfg(debug_assertions)]
#[should_panic = "`o` is not an id of an argument or a group."]
fn arg_matches_value_of_wrong_arg() {
let m = Command::new("test")
.arg(Arg::new("opt").short('o').takes_value(true))
.try_get_matches_from(&["test", "-o", "val"])
.unwrap();
assert_eq!(m.value_of("opt"), Some("val"));
m.value_of("o");
}
#[test]
#[cfg(debug_assertions)]
#[should_panic = "`seed` is not a name of a subcommand."]
fn arg_matches_subcommand_matches_wrong_sub() {
let m = Command::new("test")
.subcommand(Command::new("speed"))
.try_get_matches_from(&["test", "speed"])
.unwrap();
assert!(m.subcommand_matches("speed").is_some());
m.subcommand_matches("seed");
}

View file

@ -1,44 +0,0 @@
#![allow(deprecated)]
use clap::{Arg, ArgSettings};
#[test]
fn setting() {
let m = Arg::new("setting").setting(ArgSettings::Required);
assert!(m.is_required_set());
}
#[test]
fn unset_setting() {
let m = Arg::new("unset_setting").setting(ArgSettings::Required);
assert!(m.is_required_set());
let m = m.unset_setting(ArgSettings::Required);
assert!(!m.is_required_set(), "{:#?}", m);
}
#[test]
fn setting_bitor() {
let m = Arg::new("setting_bitor")
.setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
assert!(m.is_required_set());
assert!(m.is_hide_set());
assert!(m.is_last_set());
}
#[test]
fn unset_setting_bitor() {
let m = Arg::new("unset_setting_bitor")
.setting(ArgSettings::Required)
.setting(ArgSettings::Hidden)
.setting(ArgSettings::Last);
assert!(m.is_required_set());
assert!(m.is_hide_set());
assert!(m.is_last_set());
let m = m.unset_setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
assert!(!m.is_required_set(), "{:#?}", m);
assert!(!m.is_hide_set(), "{:#?}", m);
assert!(!m.is_last_set(), "{:#?}", m);
}

View file

@ -1,17 +0,0 @@
use clap::{Arg, Command};
#[test]
fn borrowed_args() {
let arg = Arg::new("some").short('s').long("some").help("other help");
let arg2 = Arg::new("some2")
.short('S')
.long("some-thing")
.help("other help");
let result = Command::new("sub_command_negate")
.arg(Arg::new("test").index(1))
.arg(&arg)
.arg(&arg2)
.subcommand(Command::new("sub1").arg(&arg))
.try_get_matches_from(vec!["prog"]);
assert!(result.is_ok(), "{}", result.unwrap_err());
}

View file

@ -1,80 +0,0 @@
#![cfg(feature = "cargo")]
use clap::{
crate_authors, crate_description, crate_name, crate_version, error::ErrorKind, Command,
};
static DESCRIPTION_ONLY: &str = "prog 1
A simple to use, efficient, and full-featured Command Line Argument Parser
USAGE:
prog
OPTIONS:
-h, --help Print help information
-V, --version Print version information
";
static AUTHORS_ONLY: &str = "prog 1
USAGE:
prog
OPTIONS:
-h, --help Print help information
-V, --version Print version information
";
#[test]
fn crate_version() {
let res = Command::new("prog")
.version(crate_version!())
.try_get_matches_from(vec!["prog", "--version"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
assert_eq!(
err.to_string(),
format!("prog {}\n", env!("CARGO_PKG_VERSION"))
);
}
#[test]
fn crate_description() {
let res = Command::new("prog")
.version("1")
.about(crate_description!())
.try_get_matches_from(vec!["prog", "--help"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayHelp);
assert_eq!(err.to_string(), DESCRIPTION_ONLY);
}
#[test]
fn crate_authors() {
let res = Command::new("prog")
.version("1")
.author(crate_authors!())
.try_get_matches_from(vec!["prog", "--help"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayHelp);
assert_eq!(err.to_string(), AUTHORS_ONLY);
}
#[test]
fn crate_name() {
let res = Command::new(crate_name!())
.version("3.0")
.try_get_matches_from(vec!["clap", "--version"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
assert_eq!(err.to_string(), "clap 3.0\n");
}

View file

@ -1,27 +0,0 @@
#![cfg(feature = "cargo")]
use clap::{command, error::ErrorKind};
static EVERYTHING: &str = "clap {{version}}
A simple to use, efficient, and full-featured Command Line Argument Parser
USAGE:
clap
OPTIONS:
-h, --help Print help information
-V, --version Print version information
";
#[test]
fn command() {
let res = command!().try_get_matches_from(vec!["clap", "--help"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayHelp);
assert_eq!(
err.to_string(),
EVERYTHING.replace("{{version}}", env!("CARGO_PKG_VERSION"))
);
}

View file

@ -1,509 +0,0 @@
use super::utils;
use clap::{arg, error::ErrorKind, Arg, ArgGroup, Command};
static CONFLICT_ERR: &str = "error: The argument '--flag' cannot be used with '-F'
USAGE:
clap-test --flag --long-option-2 <option2> <positional> <positional2>
For more information try --help
";
static CONFLICT_ERR_REV: &str = "error: The argument '-F' cannot be used with '--flag'
USAGE:
clap-test -F --long-option-2 <option2> <positional> <positional2>
For more information try --help
";
static CONFLICT_ERR_THREE: &str = "error: The argument '--one' cannot be used with:
--two
--three
USAGE:
three_conflicting_arguments --one
For more information try --help
";
#[test]
fn flag_conflict() {
let result = Command::new("flag_conflict")
.arg(arg!(-f --flag "some flag").conflicts_with("other"))
.arg(arg!(-o --other "some flag"))
.try_get_matches_from(vec!["myprog", "-f", "-o"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
}
#[test]
fn flag_conflict_2() {
let result = Command::new("flag_conflict")
.arg(arg!(-f --flag "some flag").conflicts_with("other"))
.arg(arg!(-o --other "some flag"))
.try_get_matches_from(vec!["myprog", "-o", "-f"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
}
#[test]
fn flag_conflict_with_all() {
let result = Command::new("flag_conflict")
.arg(arg!(-f --flag "some flag").conflicts_with_all(&["other"]))
.arg(arg!(-o --other "some flag"))
.try_get_matches_from(vec!["myprog", "-o", "-f"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
}
#[test]
fn flag_conflict_with_everything() {
let result = Command::new("flag_conflict")
.arg(arg!(-f --flag "some flag").exclusive(true))
.arg(arg!(-o --other "some flag"))
.try_get_matches_from(vec!["myprog", "-o", "-f"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
}
#[test]
fn arg_conflicts_with_group() {
let mut cmd = Command::new("group_conflict")
.arg(arg!(-f --flag "some flag").conflicts_with("gr"))
.group(ArgGroup::new("gr").arg("some").arg("other"))
.arg(arg!(--some "some arg"))
.arg(arg!(--other "other arg"));
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other", "-f"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some"]);
if let Err(err) = result {
panic!("{}", err);
}
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other"]);
if let Err(err) = result {
panic!("{}", err);
}
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--flag"]);
if let Err(err) = result {
panic!("{}", err);
}
}
#[test]
fn arg_conflicts_with_group_with_multiple_sources() {
let mut cmd = clap::Command::new("group_conflict")
.arg(clap::arg!(-f --flag "some flag").conflicts_with("gr"))
.group(clap::ArgGroup::new("gr").multiple(true))
.arg(
clap::arg!(--some <name> "some arg")
.required(false)
.group("gr"),
)
.arg(
clap::arg!(--other <secs> "other arg")
.required(false)
.default_value("1000")
.group("gr"),
);
let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f"]);
if let Err(err) = result {
panic!("{}", err);
}
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some", "usb1"]);
if let Err(err) = result {
panic!("{}", err);
}
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some", "usb1", "--other", "40"]);
if let Err(err) = result {
panic!("{}", err);
}
let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some", "usb1"]);
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
}
#[test]
fn group_conflicts_with_arg() {
let mut cmd = Command::new("group_conflict")
.arg(arg!(-f --flag "some flag"))
.group(
ArgGroup::new("gr")
.arg("some")
.arg("other")
.conflicts_with("flag"),
)
.arg(arg!(--some "some arg"))
.arg(arg!(--other "other arg"));
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other", "-f"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some"]);
if let Err(err) = result {
panic!("{}", err);
}
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other"]);
if let Err(err) = result {
panic!("{}", err);
}
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--flag"]);
if let Err(err) = result {
panic!("{}", err);
}
}
#[test]
fn arg_conflicts_with_required_group() {
let mut cmd = Command::new("group_conflict")
.arg(arg!(-f --flag "some flag").conflicts_with("gr"))
.group(ArgGroup::new("gr").required(true).arg("some").arg("other"))
.arg(arg!(--some "some arg"))
.arg(arg!(--other "other arg"));
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other", "-f"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some"]);
if let Err(err) = result {
panic!("{}", err);
}
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other"]);
if let Err(err) = result {
panic!("{}", err);
}
}
#[test]
fn required_group_conflicts_with_arg() {
let mut cmd = Command::new("group_conflict")
.arg(arg!(-f --flag "some flag"))
.group(
ArgGroup::new("gr")
.required(true)
.arg("some")
.arg("other")
.conflicts_with("flag"),
)
.arg(arg!(--some "some arg"))
.arg(arg!(--other "other arg"));
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other", "-f"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some"]);
if let Err(err) = result {
panic!("{}", err);
}
let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other"]);
if let Err(err) = result {
panic!("{}", err);
}
}
#[test]
fn conflict_output() {
utils::assert_output(
utils::complex_app(),
"clap-test val1 fa --flag --long-option-2 val2 -F",
CONFLICT_ERR,
true,
);
}
#[test]
fn conflict_output_rev() {
utils::assert_output(
utils::complex_app(),
"clap-test val1 fa -F --long-option-2 val2 --flag",
CONFLICT_ERR_REV,
true,
);
}
#[test]
fn conflict_output_with_required() {
utils::assert_output(
utils::complex_app(),
"clap-test val1 --flag --long-option-2 val2 -F",
CONFLICT_ERR,
true,
);
}
#[test]
fn conflict_output_rev_with_required() {
utils::assert_output(
utils::complex_app(),
"clap-test val1 -F --long-option-2 val2 --flag",
CONFLICT_ERR_REV,
true,
);
}
#[test]
fn conflict_output_three_conflicting() {
let cmd = Command::new("three_conflicting_arguments")
.arg(
Arg::new("one")
.long("one")
.conflicts_with_all(&["two", "three"]),
)
.arg(
Arg::new("two")
.long("two")
.conflicts_with_all(&["one", "three"]),
)
.arg(
Arg::new("three")
.long("three")
.conflicts_with_all(&["one", "two"]),
);
utils::assert_output(
cmd,
"three_conflicting_arguments --one --two --three",
CONFLICT_ERR_THREE,
true,
);
}
#[test]
fn two_conflicting_arguments() {
let a = Command::new("two_conflicting_arguments")
.arg(
Arg::new("develop")
.long("develop")
.conflicts_with("production"),
)
.arg(
Arg::new("production")
.long("production")
.conflicts_with("develop"),
)
.try_get_matches_from(vec!["", "--develop", "--production"]);
assert!(a.is_err());
let a = a.unwrap_err();
assert!(
a.to_string()
.contains("The argument \'--develop\' cannot be used with \'--production\'"),
"{}",
a
);
}
#[test]
fn three_conflicting_arguments() {
let a = Command::new("three_conflicting_arguments")
.arg(
Arg::new("one")
.long("one")
.conflicts_with_all(&["two", "three"]),
)
.arg(
Arg::new("two")
.long("two")
.conflicts_with_all(&["one", "three"]),
)
.arg(
Arg::new("three")
.long("three")
.conflicts_with_all(&["one", "two"]),
)
.try_get_matches_from(vec!["", "--one", "--two", "--three"]);
assert!(a.is_err());
let a = a.unwrap_err();
assert!(
a.to_string()
.contains("The argument \'--one\' cannot be used with:"),
"{}",
a
);
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument 'config' cannot conflict with itself"]
fn self_conflicting_arg() {
let _ = Command::new("prog")
.arg(Arg::new("config").long("config").conflicts_with("config"))
.try_get_matches_from(vec!["", "--config"]);
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument or group 'extra' specified in 'conflicts_with*' for 'config' does not exist"]
fn conflicts_with_invalid_arg() {
let _ = Command::new("prog")
.arg(Arg::new("config").long("config").conflicts_with("extra"))
.try_get_matches_from(vec!["", "--config"]);
}
#[test]
fn conflict_with_unused_default() {
let result = Command::new("conflict")
.arg(
arg!(-o --opt <opt> "some opt")
.required(false)
.default_value("default"),
)
.arg(arg!(-f --flag "some flag").conflicts_with("opt"))
.try_get_matches_from(vec!["myprog", "-f"]);
assert!(result.is_ok(), "{}", result.unwrap_err());
let m = result.unwrap();
assert_eq!(m.value_of("opt"), Some("default"));
assert!(m.is_present("flag"));
}
#[test]
fn conflicts_with_alongside_default() {
let result = Command::new("conflict")
.arg(
arg!(-o --opt <opt> "some opt")
.default_value("default")
.required(false)
.conflicts_with("flag"),
)
.arg(arg!(-f --flag "some flag"))
.try_get_matches_from(vec!["myprog", "-f"]);
assert!(
result.is_ok(),
"conflicts_with should ignore default_value: {:?}",
result.unwrap_err()
);
let m = result.unwrap();
assert_eq!(m.value_of("opt"), Some("default"));
assert!(m.is_present("flag"));
}
#[test]
fn group_in_conflicts_with() {
let result = Command::new("conflict")
.arg(
Arg::new("opt")
.long("opt")
.default_value("default")
.group("one"),
)
.arg(Arg::new("flag").long("flag").conflicts_with("one"))
.try_get_matches_from(vec!["myprog", "--flag"]);
assert!(
result.is_ok(),
"conflicts_with on an arg group should ignore default_value: {:?}",
result.unwrap_err()
);
let m = result.unwrap();
assert_eq!(m.value_of("opt"), Some("default"));
assert!(m.is_present("flag"));
}
#[test]
fn group_conflicts_with_default_value() {
let result = Command::new("conflict")
.arg(
Arg::new("opt")
.long("opt")
.default_value("default")
.group("one"),
)
.arg(Arg::new("flag").long("flag").group("one"))
.try_get_matches_from(vec!["myprog", "--flag"]);
assert!(
result.is_ok(),
"arg group count should ignore default_value: {:?}",
result.unwrap_err()
);
let m = result.unwrap();
assert_eq!(m.value_of("opt"), Some("default"));
assert!(m.is_present("flag"));
}
#[test]
fn group_conflicts_with_default_arg() {
let result = Command::new("conflict")
.arg(Arg::new("opt").long("opt").default_value("default"))
.arg(Arg::new("flag").long("flag").group("one"))
.group(ArgGroup::new("one").conflicts_with("opt"))
.try_get_matches_from(vec!["myprog", "--flag"]);
assert!(
result.is_ok(),
"arg group conflicts_with should ignore default_value: {:?}",
result.unwrap_err()
);
let m = result.unwrap();
assert_eq!(m.value_of("opt"), Some("default"));
assert!(m.is_present("flag"));
}
#[test]
fn exclusive_with_required() {
let cmd = Command::new("bug")
.arg(Arg::new("test").long("test").exclusive(true))
.arg(Arg::new("input").takes_value(true).required(true));
cmd.clone()
.try_get_matches_from(["bug", "--test", "required"])
.unwrap_err();
cmd.clone()
.try_get_matches_from(["bug", "required"])
.unwrap();
cmd.clone().try_get_matches_from(["bug", "--test"]).unwrap();
}

View file

@ -1,187 +0,0 @@
use clap::{arg, Arg, ArgMatches, Command};
#[test]
fn opt_missing() {
let r = Command::new("df")
.arg(
Arg::new("color")
.long("color")
.default_value("auto")
.min_values(0)
.require_equals(true)
.default_missing_value("always"),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("color"));
assert_eq!(m.value_of("color").unwrap(), "auto");
assert_eq!(m.occurrences_of("color"), 0);
}
#[test]
fn opt_present_with_missing_value() {
let r = Command::new("df")
.arg(
Arg::new("color")
.long("color")
.default_value("auto")
.min_values(0)
.require_equals(true)
.default_missing_value("always"),
)
.try_get_matches_from(vec!["", "--color"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("color"));
assert_eq!(m.value_of("color").unwrap(), "always");
assert_eq!(m.occurrences_of("color"), 1);
}
#[test]
fn opt_present_with_value() {
let r = Command::new("df")
.arg(
Arg::new("color")
.long("color")
.default_value("auto")
.min_values(0)
.require_equals(true)
.default_missing_value("always"),
)
.try_get_matches_from(vec!["", "--color=never"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("color"));
assert_eq!(m.value_of("color").unwrap(), "never");
assert_eq!(m.occurrences_of("color"), 1);
}
#[test]
fn opt_present_with_empty_value() {
let r = Command::new("df")
.arg(
Arg::new("color")
.long("color")
.default_value("auto")
.require_equals(true)
.default_missing_value("always"),
)
.try_get_matches_from(vec!["", "--color="]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("color"));
assert_eq!(m.value_of("color").unwrap(), "");
assert_eq!(m.occurrences_of("color"), 1);
}
//## `default_value`/`default_missing_value` non-interaction checks
#[test]
fn opt_default() {
// assert no change to usual argument handling when adding default_missing_value()
let r = Command::new("cmd")
.arg(
arg!(o: -o [opt] "some opt")
.default_value("default")
.default_missing_value("default_missing"),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.value_of("o").unwrap(), "default");
}
#[test]
fn opt_default_user_override() {
// assert no change to usual argument handling when adding default_missing_value()
let r = Command::new("cmd")
.arg(
arg!(o: -o [opt] "some opt")
.default_value("default")
.default_missing_value("default_missing"),
)
.try_get_matches_from(vec!["", "-o=value"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.value_of("o").unwrap(), "value");
}
#[test]
#[allow(clippy::bool_assert_comparison)]
fn default_missing_value_flag_value() {
let cmd = Command::new("test").arg(
Arg::new("flag")
.long("flag")
.takes_value(true)
.default_missing_value("true"),
);
fn flag_value(m: ArgMatches) -> bool {
match m.value_of("flag") {
None => false,
Some(x) => x.parse().expect("non boolean value"),
}
}
assert_eq!(
flag_value(cmd.clone().try_get_matches_from(&["test"]).unwrap()),
false
);
assert_eq!(
flag_value(
cmd.clone()
.try_get_matches_from(&["test", "--flag"])
.unwrap()
),
true
);
assert_eq!(
flag_value(
cmd.clone()
.try_get_matches_from(&["test", "--flag=true"])
.unwrap()
),
true
);
assert_eq!(
flag_value(
cmd.clone()
.try_get_matches_from(&["test", "--flag=false"])
.unwrap()
),
false
);
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument `arg`'s default_missing_value=value doesn't match possible values"]
fn default_missing_values_are_possible_values() {
use clap::{Arg, Command};
let _ = Command::new("test")
.arg(
Arg::new("arg")
.possible_values(["one", "two"])
.default_missing_value("value"),
)
.try_get_matches();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument `arg`'s default_missing_value=value failed validation: invalid digit found in string"]
fn default_missing_values_are_valid() {
use clap::{Arg, Command};
let _ = Command::new("test")
.arg(
Arg::new("arg")
.validator(|val| val.parse::<u32>().map_err(|e| e.to_string()))
.default_missing_value("value"),
)
.try_get_matches();
}

View file

@ -1,708 +0,0 @@
use super::utils;
use clap::{arg, error::ErrorKind, Arg, Command};
#[test]
fn opts() {
let r = Command::new("df")
.arg(
arg!(o: -o <opt> "some opt")
.required(false)
.default_value("default"),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.value_of("o").unwrap(), "default");
}
#[test]
fn opt_without_value_fail() {
let r = Command::new("df")
.arg(
arg!(o: -o <opt> "some opt")
.required(false)
.default_value("default")
.forbid_empty_values(true),
)
.try_get_matches_from(vec!["", "-o"]);
assert!(r.is_err());
let err = r.unwrap_err();
assert_eq!(err.kind(), ErrorKind::EmptyValue);
assert!(err
.to_string()
.contains("The argument '-o <opt>' requires a value but none was supplied"));
}
#[test]
fn opt_user_override() {
let r = Command::new("df")
.arg(
arg!(--opt <FILE> "some arg")
.required(false)
.default_value("default"),
)
.try_get_matches_from(vec!["", "--opt", "value"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("opt"));
assert_eq!(m.value_of("opt").unwrap(), "value");
}
#[test]
fn positionals() {
let r = Command::new("df")
.arg(arg!([arg] "some opt").default_value("default"))
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "default");
}
#[test]
fn positional_user_override() {
let r = Command::new("df")
.arg(arg!([arg] "some arg").default_value("default"))
.try_get_matches_from(vec!["", "value"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "value");
}
// OsStr Default Values
#[test]
fn osstr_opts() {
use std::ffi::OsStr;
let expected = OsStr::new("default");
let r = Command::new("df")
.arg(
arg!(o: -o <opt> "some opt")
.required(false)
.default_value_os(expected),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.value_of("o").unwrap(), expected);
}
#[test]
fn osstr_opt_user_override() {
use std::ffi::OsStr;
let default = OsStr::new("default");
let r = Command::new("df")
.arg(
arg!(--opt <FILE> "some arg")
.required(false)
.default_value_os(default),
)
.try_get_matches_from(vec!["", "--opt", "value"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("opt"));
assert_eq!(m.value_of("opt").unwrap(), "value");
}
#[test]
fn osstr_positionals() {
use std::ffi::OsStr;
let expected = OsStr::new("default");
let r = Command::new("df")
.arg(arg!([arg] "some opt").default_value_os(expected))
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), expected);
}
#[test]
fn osstr_positional_user_override() {
use std::ffi::OsStr;
let default = OsStr::new("default");
let r = Command::new("df")
.arg(arg!([arg] "some arg").default_value_os(default))
.try_get_matches_from(vec!["", "value"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "value");
}
// --- Default if arg is present
#[test]
fn default_if_arg_present_no_default() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(true))
.arg(arg!([arg] "some arg").default_value_if("opt", None, Some("default")))
.try_get_matches_from(vec!["", "--opt", "some"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "default");
}
#[test]
fn default_if_arg_present_no_default_user_override() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(arg!([arg] "some arg").default_value_if("opt", None, Some("default")))
.try_get_matches_from(vec!["", "--opt", "some", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "other");
}
#[test]
fn default_if_arg_present_no_arg_with_default() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_if("opt", None, Some("default")),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "first");
}
#[test]
fn default_if_arg_present_with_default() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_if("opt", None, Some("default")),
)
.try_get_matches_from(vec!["", "--opt", "some"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "default");
}
#[test]
fn default_if_arg_present_with_default_user_override() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_if("opt", None, Some("default")),
)
.try_get_matches_from(vec!["", "--opt", "some", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "other");
}
#[test]
fn default_if_arg_present_no_arg_with_default_user_override() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_if("opt", None, Some("default")),
)
.try_get_matches_from(vec!["", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "other");
}
// Conditional Default Values
#[test]
fn default_if_arg_present_with_value_no_default() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(arg!([arg] "some arg").default_value_if("opt", Some("value"), Some("default")))
.try_get_matches_from(vec!["", "--opt", "value"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "default");
}
#[test]
fn default_if_arg_present_with_value_no_default_fail() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(arg!([arg] "some arg").default_value_if("opt", Some("value"), Some("default")))
.try_get_matches_from(vec!["", "--opt", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(!m.is_present("arg"));
assert!(m.value_of("arg").is_none());
}
#[test]
fn default_if_arg_present_with_value_no_default_user_override() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(arg!([arg] "some arg").default_value_if("opt", Some("some"), Some("default")))
.try_get_matches_from(vec!["", "--opt", "some", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "other");
}
#[test]
fn default_if_arg_present_with_value_no_arg_with_default() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_if("opt", Some("some"), Some("default")),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "first");
}
#[test]
fn default_if_arg_present_with_value_no_arg_with_default_fail() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_if("opt", Some("some"), Some("default")),
)
.try_get_matches_from(vec!["", "--opt", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "first");
}
#[test]
fn default_if_arg_present_with_value_with_default() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_if("opt", Some("some"), Some("default")),
)
.try_get_matches_from(vec!["", "--opt", "some"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "default");
}
#[test]
fn default_if_arg_present_with_value_with_default_user_override() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_if("opt", Some("some"), Some("default")),
)
.try_get_matches_from(vec!["", "--opt", "some", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "other");
}
#[test]
fn default_if_arg_present_no_arg_with_value_with_default_user_override() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_if("opt", Some("some"), Some("default")),
)
.try_get_matches_from(vec!["", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "other");
}
#[test]
fn default_if_arg_present_no_arg_with_value_with_default_user_override_fail() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_if("opt", Some("some"), Some("default")),
)
.try_get_matches_from(vec!["", "--opt", "value", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "other");
}
// Unsetting the default
#[test]
fn no_default_if_arg_present_with_value_no_default() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(arg!([arg] "some arg").default_value_if("opt", Some("value"), None))
.try_get_matches_from(vec!["", "--opt", "value"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(!m.is_present("arg"));
}
#[test]
fn no_default_if_arg_present_with_value_with_default() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("default")
.default_value_if("opt", Some("value"), None),
)
.try_get_matches_from(vec!["", "--opt", "value"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(!m.is_present("arg"));
assert!(m.value_of("arg").is_none());
}
#[test]
fn no_default_if_arg_present_with_value_with_default_user_override() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("default")
.default_value_if("opt", Some("value"), None),
)
.try_get_matches_from(vec!["", "--opt", "value", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "other");
}
#[test]
fn no_default_if_arg_present_no_arg_with_value_with_default() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(
arg!([arg] "some arg")
.default_value("default")
.default_value_if("opt", Some("value"), None),
)
.try_get_matches_from(vec!["", "--opt", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "default");
}
// Multiple conditions
#[test]
fn default_ifs_arg_present() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(arg!(--flag "some arg"))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_ifs(&[
("opt", Some("some"), Some("default")),
("flag", None, Some("flg")),
]),
)
.try_get_matches_from(vec!["", "--flag"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "flg");
}
#[test]
fn no_default_ifs_arg_present() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(arg!(--flag "some arg"))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_ifs(&[("opt", Some("some"), Some("default")), ("flag", None, None)]),
)
.try_get_matches_from(vec!["", "--flag"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(!m.is_present("arg"));
assert!(m.value_of("arg").is_none());
}
#[test]
fn default_ifs_arg_present_user_override() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(arg!(--flag "some arg"))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_ifs(&[
("opt", Some("some"), Some("default")),
("flag", None, Some("flg")),
]),
)
.try_get_matches_from(vec!["", "--flag", "value"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "value");
}
#[test]
fn default_ifs_arg_present_order() {
let r = Command::new("df")
.arg(arg!(--opt <FILE> "some arg").required(false))
.arg(arg!(--flag "some arg"))
.arg(
arg!([arg] "some arg")
.default_value("first")
.default_value_ifs(&[
("opt", Some("some"), Some("default")),
("flag", None, Some("flg")),
]),
)
.try_get_matches_from(vec!["", "--opt=some", "--flag"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "default");
}
// Interaction with requires
#[test]
fn conditional_reqs_pass() {
let m = Command::new("Test cmd")
.arg(
Arg::new("target")
.takes_value(true)
.default_value("file")
.long("target"),
)
.arg(
Arg::new("input")
.takes_value(true)
.required(true)
.long("input"),
)
.arg(
Arg::new("output")
.takes_value(true)
.required_if_eq("target", "file")
.long("output"),
)
.try_get_matches_from(vec!["test", "--input", "some", "--output", "other"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert_eq!(m.value_of("output"), Some("other"));
assert_eq!(m.value_of("input"), Some("some"));
}
#[test]
fn multiple_defaults() {
let r = Command::new("diff")
.arg(
Arg::new("files")
.long("files")
.number_of_values(2)
.allow_invalid_utf8(true)
.default_values(&["old", "new"]),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("files"));
assert_eq!(m.values_of_lossy("files").unwrap(), vec!["old", "new"]);
}
#[test]
fn multiple_defaults_override() {
let r = Command::new("diff")
.arg(
Arg::new("files")
.long("files")
.number_of_values(2)
.allow_invalid_utf8(true)
.default_values(&["old", "new"]),
)
.try_get_matches_from(vec!["", "--files", "other", "mine"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("files"));
assert_eq!(m.values_of_lossy("files").unwrap(), vec!["other", "mine"]);
}
#[test]
fn default_vals_donnot_show_in_smart_usage() {
let cmd = Command::new("bug")
.arg(
Arg::new("foo")
.long("config")
.takes_value(true)
.default_value("bar"),
)
.arg(Arg::new("input").required(true));
utils::assert_output(
cmd,
"bug",
"error: The following required arguments were not provided:
<input>
USAGE:
bug [OPTIONS] <input>
For more information try --help
",
true,
);
}
#[test]
fn issue_1050_num_vals_and_defaults() {
let res = Command::new("hello")
.arg(
Arg::new("exit-code")
.long("exit-code")
.takes_value(true)
.number_of_values(1)
.default_value("0"),
)
.try_get_matches_from(vec!["hello", "--exit-code=1"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert_eq!(m.value_of("exit-code"), Some("1"));
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument `arg`'s default_value=value doesn't match possible values"]
fn default_values_are_possible_values() {
use clap::{Arg, Command};
let _ = Command::new("test")
.arg(
Arg::new("arg")
.possible_values(["one", "two"])
.default_value("value"),
)
.try_get_matches();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument `arg`'s default_value=one failed validation: invalid digit found in string"]
fn invalid_default_values() {
use clap::{Arg, Command};
let _ = Command::new("test")
.arg(
Arg::new("arg")
.validator(|val| val.parse::<u32>().map_err(|e| e.to_string()))
.default_value("one"),
)
.try_get_matches();
}
#[test]
fn valid_delimited_default_values() {
use clap::{Arg, Command};
let _ = Command::new("test")
.arg(
Arg::new("arg")
.validator(|val| val.parse::<u32>().map_err(|e| e.to_string()))
.use_value_delimiter(true)
.require_value_delimiter(true)
.default_value("1,2,3"),
)
.try_get_matches();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument `arg`'s default_value=one failed validation: invalid digit found in string"]
fn invalid_delimited_default_values() {
use clap::{Arg, Command};
let _ = Command::new("test")
.arg(
Arg::new("arg")
.validator(|val| val.parse::<u32>().map_err(|e| e.to_string()))
.use_value_delimiter(true)
.require_value_delimiter(true)
.default_value("one,two"),
)
.try_get_matches();
}
#[test]
fn with_value_delimiter() {
let cmd = Command::new("multiple_values").arg(
Arg::new("option")
.long("option")
.help("multiple options")
.value_delimiter(';')
.default_value("first;second"),
);
let matches = cmd.try_get_matches_from(vec![""]).unwrap();
assert_eq!(
matches.values_of("option").unwrap().collect::<Vec<_>>(),
["first", "second"]
);
}
#[test]
fn missing_with_value_delimiter() {
let cmd = Command::new("program").arg(
Arg::new("option")
.long("option")
.value_delimiter(';')
.default_missing_values(&["value1;value2;value3", "value4;value5"]),
);
let matches = cmd
.try_get_matches_from(vec!["program", "--option"])
.unwrap();
assert_eq!(
matches.values_of("option").unwrap().collect::<Vec<_>>(),
["value1", "value2", "value3", "value4", "value5"]
);
}

View file

@ -1,113 +0,0 @@
use clap::{Arg, Command};
#[test]
fn opt_default_no_delim() {
let m = Command::new("no_delim")
.arg(Arg::new("option").long("option").takes_value(true))
.try_get_matches_from(vec!["", "--option", "val1,val2,val3"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("option"));
assert_eq!(m.occurrences_of("option"), 1);
assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3");
}
#[test]
fn opt_eq_no_delim() {
let m = Command::new("no_delim")
.arg(Arg::new("option").long("option").takes_value(true))
.try_get_matches_from(vec!["", "--option=val1,val2,val3"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("option"));
assert_eq!(m.occurrences_of("option"), 1);
assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3");
}
#[test]
fn opt_s_eq_no_delim() {
let m = Command::new("no_delim")
.arg(Arg::new("option").short('o').takes_value(true))
.try_get_matches_from(vec!["", "-o=val1,val2,val3"]);
assert!(m.is_ok(), "{:?}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("option"));
assert_eq!(m.occurrences_of("option"), 1);
assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3");
}
#[test]
fn opt_s_default_no_delim() {
let m = Command::new("no_delim")
.arg(Arg::new("option").short('o').takes_value(true))
.try_get_matches_from(vec!["", "-o", "val1,val2,val3"]);
assert!(m.is_ok(), "{:?}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("option"));
assert_eq!(m.occurrences_of("option"), 1);
assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3");
}
#[test]
fn opt_s_no_space_no_delim() {
let m = Command::new("no_delim")
.arg(Arg::new("option").short('o').takes_value(true))
.try_get_matches_from(vec!["", "-o", "val1,val2,val3"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("option"));
assert_eq!(m.occurrences_of("option"), 1);
assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3");
}
#[test]
fn opt_s_no_space_mult_no_delim() {
let m = Command::new("no_delim")
.arg(
Arg::new("option")
.short('o')
.takes_value(true)
.multiple_values(true),
)
.try_get_matches_from(vec!["", "-o", "val1,val2,val3"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("option"));
assert_eq!(m.occurrences_of("option"), 1);
assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3");
}
#[test]
fn opt_eq_mult_def_delim() {
let m = Command::new("no_delim")
.arg(
Arg::new("option")
.long("opt")
.takes_value(true)
.multiple_values(true)
.use_value_delimiter(true),
)
.try_get_matches_from(vec!["", "--opt=val1,val2,val3"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("option"));
assert_eq!(m.occurrences_of("option"), 1);
assert_eq!(
m.values_of("option").unwrap().collect::<Vec<_>>(),
&["val1", "val2", "val3"]
);
}

View file

@ -1,293 +0,0 @@
use super::utils;
use std::str;
use clap::{AppSettings, Arg, Command};
static NO_DERIVE_ORDER: &str = "test 1.2
USAGE:
test [OPTIONS]
OPTIONS:
--flag_a second flag
--flag_b first flag
-h, --help Print help information
--option_a <option_a> second option
--option_b <option_b> first option
-V, --version Print version information
";
static UNIFIED_HELP_AND_DERIVE: &str = "test 1.2
USAGE:
test [OPTIONS]
OPTIONS:
--flag_b first flag
--option_b <option_b> first option
--flag_a second flag
--option_a <option_a> second option
-h, --help Print help information
-V, --version Print version information
";
static UNIFIED_DERIVE_SC_PROP: &str = "test-sub 1.2
USAGE:
test sub [OPTIONS]
OPTIONS:
--flag_b first flag
--option_b <option_b> first option
--flag_a second flag
--option_a <option_a> second option
-h, --help Print help information
-V, --version Print version information
";
static UNIFIED_DERIVE_SC_PROP_EXPLICIT_ORDER: &str = "test-sub 1.2
USAGE:
test sub [OPTIONS]
OPTIONS:
--flag_a second flag
--flag_b first flag
--option_b <option_b> first option
--option_a <option_a> second option
-h, --help Print help information
-V, --version Print version information
";
static PREFER_USER_HELP_DERIVE_ORDER: &str = "test 1.2
USAGE:
test [OPTIONS]
OPTIONS:
-h, --help Print help message
--flag_b first flag
--flag_a second flag
-V, --version Print version information
";
static PREFER_USER_HELP_SUBCMD_DERIVE_ORDER: &str = "test-sub 1.2
USAGE:
test sub [OPTIONS]
OPTIONS:
-h, --help Print help message
--flag_b first flag
--flag_a second flag
-V, --version Print version information
";
#[test]
fn no_derive_order() {
let cmd = Command::new("test").version("1.2").args(&[
Arg::new("flag_b").long("flag_b").help("first flag"),
Arg::new("option_b")
.long("option_b")
.takes_value(true)
.help("first option"),
Arg::new("flag_a").long("flag_a").help("second flag"),
Arg::new("option_a")
.long("option_a")
.takes_value(true)
.help("second option"),
]);
utils::assert_output(cmd, "test --help", NO_DERIVE_ORDER, false);
}
#[test]
fn derive_order() {
let cmd = Command::new("test")
.setting(AppSettings::DeriveDisplayOrder)
.version("1.2")
.args(&[
Arg::new("flag_b").long("flag_b").help("first flag"),
Arg::new("option_b")
.long("option_b")
.takes_value(true)
.help("first option"),
Arg::new("flag_a").long("flag_a").help("second flag"),
Arg::new("option_a")
.long("option_a")
.takes_value(true)
.help("second option"),
]);
utils::assert_output(cmd, "test --help", UNIFIED_HELP_AND_DERIVE, false);
}
#[test]
fn derive_order_next_order() {
static HELP: &str = "test 1.2
USAGE:
test [OPTIONS]
OPTIONS:
--flag_b first flag
--option_b <option_b> first option
-h, --help Print help information
-V, --version Print version information
--flag_a second flag
--option_a <option_a> second option
";
let cmd = Command::new("test")
.setting(AppSettings::DeriveDisplayOrder)
.version("1.2")
.next_display_order(10000)
.arg(Arg::new("flag_a").long("flag_a").help("second flag"))
.arg(
Arg::new("option_a")
.long("option_a")
.takes_value(true)
.help("second option"),
)
.next_display_order(10)
.arg(Arg::new("flag_b").long("flag_b").help("first flag"))
.arg(
Arg::new("option_b")
.long("option_b")
.takes_value(true)
.help("first option"),
);
utils::assert_output(cmd, "test --help", HELP, false);
}
#[test]
fn derive_order_no_next_order() {
static HELP: &str = "test 1.2
USAGE:
test [OPTIONS]
OPTIONS:
--flag_a first flag
--flag_b second flag
-h, --help Print help information
--option_a <option_a> first option
--option_b <option_b> second option
-V, --version Print version information
";
let cmd = Command::new("test")
.setting(AppSettings::DeriveDisplayOrder)
.version("1.2")
.next_display_order(None)
.arg(Arg::new("flag_a").long("flag_a").help("first flag"))
.arg(
Arg::new("option_a")
.long("option_a")
.takes_value(true)
.help("first option"),
)
.arg(Arg::new("flag_b").long("flag_b").help("second flag"))
.arg(
Arg::new("option_b")
.long("option_b")
.takes_value(true)
.help("second option"),
);
utils::assert_output(cmd, "test --help", HELP, false);
}
#[test]
fn derive_order_subcommand_propagate() {
let cmd = Command::new("test")
.global_setting(AppSettings::DeriveDisplayOrder)
.subcommand(
Command::new("sub").version("1.2").args(&[
Arg::new("flag_b").long("flag_b").help("first flag"),
Arg::new("option_b")
.long("option_b")
.takes_value(true)
.help("first option"),
Arg::new("flag_a").long("flag_a").help("second flag"),
Arg::new("option_a")
.long("option_a")
.takes_value(true)
.help("second option"),
]),
);
utils::assert_output(cmd, "test sub --help", UNIFIED_DERIVE_SC_PROP, false);
}
#[test]
fn derive_order_subcommand_propagate_with_explicit_display_order() {
let cmd = Command::new("test")
.global_setting(AppSettings::DeriveDisplayOrder)
.subcommand(
Command::new("sub").version("1.2").args(&[
Arg::new("flag_b").long("flag_b").help("first flag"),
Arg::new("option_b")
.long("option_b")
.takes_value(true)
.help("first option"),
Arg::new("flag_a")
.long("flag_a")
.help("second flag")
.display_order(0),
Arg::new("option_a")
.long("option_a")
.takes_value(true)
.help("second option"),
]),
);
utils::assert_output(
cmd,
"test sub --help",
UNIFIED_DERIVE_SC_PROP_EXPLICIT_ORDER,
false,
);
}
#[test]
fn prefer_user_help_with_derive_order() {
let cmd = Command::new("test")
.setting(AppSettings::DeriveDisplayOrder)
.version("1.2")
.args(&[
Arg::new("help")
.long("help")
.short('h')
.help("Print help message"),
Arg::new("flag_b").long("flag_b").help("first flag"),
Arg::new("flag_a").long("flag_a").help("second flag"),
]);
utils::assert_output(cmd, "test --help", PREFER_USER_HELP_DERIVE_ORDER, false);
}
#[test]
fn prefer_user_help_in_subcommand_with_derive_order() {
let cmd = Command::new("test")
.global_setting(AppSettings::DeriveDisplayOrder)
.subcommand(
Command::new("sub").version("1.2").args(&[
Arg::new("help")
.long("help")
.short('h')
.help("Print help message"),
Arg::new("flag_b").long("flag_b").help("first flag"),
Arg::new("flag_a").long("flag_a").help("second flag"),
]),
);
utils::assert_output(
cmd,
"test sub --help",
PREFER_USER_HELP_SUBCMD_DERIVE_ORDER,
false,
);
}

View file

@ -1,26 +0,0 @@
use super::utils;
use clap::Command;
#[test]
fn very_large_display_order() {
let cmd = Command::new("test").subcommand(Command::new("sub").display_order(usize::MAX));
utils::assert_output(
cmd,
"test --help",
"test
USAGE:
test [SUBCOMMAND]
OPTIONS:
-h, --help Print help information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
sub
",
false,
);
}

View file

@ -1,88 +0,0 @@
use clap::{error::ErrorKind, Arg, Command};
static HELP: &str = "prog
USAGE:
prog [OPTIONS]
OPTIONS:
-a
-b
-c
-h, --help Print help information
";
static ONLY_B_ERROR: &str = "error: The following required arguments were not provided:
-c
USAGE:
prog -b -c
For more information try --help
";
static ONLY_C_ERROR: &str = "error: The following required arguments were not provided:
-b
USAGE:
prog -c -b
For more information try --help
";
fn cmd() -> Command<'static> {
Command::new("prog")
.arg(
Arg::new("a")
.short('a')
.required_unless_present_any(&["b", "c"])
.conflicts_with_all(&["b", "c"]),
)
.arg(
Arg::new("b")
.short('b')
.required_unless_present("a")
.requires("c"),
)
.arg(
Arg::new("c")
.short('c')
.required_unless_present("a")
.requires("b"),
)
}
#[test]
fn valid_cases() {
let res = cmd().try_get_matches_from(vec!["", "-a"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let res = cmd().clone().try_get_matches_from(vec!["", "-b", "-c"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let res = cmd().try_get_matches_from(vec!["", "-c", "-b"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
}
#[test]
fn help_text() {
let res = cmd().try_get_matches_from(vec!["prog", "--help"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayHelp);
println!("{}", err);
assert_eq!(err.to_string(), HELP);
}
#[test]
fn no_duplicate_error() {
let res = cmd().try_get_matches_from(vec!["", "-b"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
assert_eq!(err.to_string(), ONLY_B_ERROR);
let res = cmd().try_get_matches_from(vec!["", "-c"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
assert_eq!(err.to_string(), ONLY_C_ERROR);
}

View file

@ -1,128 +0,0 @@
use super::utils;
use clap::{error::ErrorKind, Arg, Command};
#[test]
fn empty_values() {
let m = Command::new("config")
.arg(Arg::new("config").long("config").takes_value(true))
.try_get_matches_from(&["config", "--config", ""])
.unwrap();
assert_eq!(m.value_of("config"), Some(""));
}
#[test]
fn empty_values_with_equals() {
let m = Command::new("config")
.arg(Arg::new("config").long("config").takes_value(true))
.try_get_matches_from(&["config", "--config="])
.unwrap();
assert_eq!(m.value_of("config"), Some(""));
let m = Command::new("config")
.arg(Arg::new("config").short('c').takes_value(true))
.try_get_matches_from(&["config", "-c="])
.unwrap();
assert_eq!(m.value_of("config"), Some(""))
}
#[test]
fn no_empty_values() {
let m = Command::new("config")
.arg(
Arg::new("config")
.long("config")
.takes_value(true)
.forbid_empty_values(true),
)
.try_get_matches_from(&["config", "--config", ""]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::EmptyValue);
let m = Command::new("config")
.arg(
Arg::new("config")
.short('c')
.takes_value(true)
.forbid_empty_values(true),
)
.try_get_matches_from(&["config", "-c", ""]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::EmptyValue)
}
#[test]
fn no_empty_values_with_equals() {
let m = Command::new("config")
.arg(
Arg::new("config")
.long("config")
.takes_value(true)
.forbid_empty_values(true),
)
.try_get_matches_from(&["config", "--config="]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::EmptyValue);
let m = Command::new("config")
.arg(
Arg::new("config")
.short('c')
.takes_value(true)
.forbid_empty_values(true),
)
.try_get_matches_from(&["config", "-c="]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::EmptyValue);
}
#[test]
fn no_empty_values_without_equals() {
let m = Command::new("config")
.arg(
Arg::new("config")
.long("config")
.takes_value(true)
.forbid_empty_values(true),
)
.try_get_matches_from(&["config", "--config"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::EmptyValue);
let m = Command::new("config")
.arg(
Arg::new("config")
.short('c')
.takes_value(true)
.forbid_empty_values(true),
)
.try_get_matches_from(&["config", "-c"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::EmptyValue)
}
#[test]
fn no_empty_values_without_equals_but_requires_equals() {
let cmd = Command::new("config").arg(
Arg::new("config")
.long("config")
.takes_value(true)
.forbid_empty_values(true)
.require_equals(true),
);
let m = cmd.clone().try_get_matches_from(&["config", "--config"]);
// Should error on no equals rather than empty value.
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::NoEquals);
static NO_EUQALS_ERROR: &str =
"error: Equal sign is needed when assigning values to '--config=<config>'.
USAGE:
config [OPTIONS]
For more information try --help
";
utils::assert_output(cmd, "config --config", NO_EUQALS_ERROR, true);
}

View file

@ -1,352 +0,0 @@
#![cfg(feature = "env")]
use std::env;
use std::ffi::OsStr;
use clap::{arg, Arg, Command};
#[test]
fn env() {
env::set_var("CLP_TEST_ENV", "env");
let r = Command::new("df")
.arg(arg!([arg] "some opt").env("CLP_TEST_ENV").takes_value(true))
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(m.value_of("arg").unwrap(), "env");
}
#[test]
fn env_bool_literal() {
env::set_var("CLP_TEST_FLAG_TRUE", "On");
env::set_var("CLP_TEST_FLAG_FALSE", "nO");
let r = Command::new("df")
.arg(Arg::new("present").short('p').env("CLP_TEST_FLAG_TRUE"))
.arg(Arg::new("negated").short('n').env("CLP_TEST_FLAG_FALSE"))
.arg(Arg::new("absent").short('a').env("CLP_TEST_FLAG_ABSENT"))
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("present"));
assert_eq!(m.occurrences_of("present"), 0);
assert_eq!(m.value_of("present"), None);
assert!(!m.is_present("negated"));
assert!(!m.is_present("absent"));
}
#[test]
fn env_os() {
env::set_var("CLP_TEST_ENV_OS", "env");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env_os(OsStr::new("CLP_TEST_ENV_OS"))
.takes_value(true),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(m.value_of("arg").unwrap(), "env");
}
#[test]
fn no_env() {
// All the other tests use the presence of the Environment variable...
// we need another variable just in case one of the others is running at the same time...
env::remove_var("CLP_TEST_ENV_NONE");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_NONE")
.takes_value(true),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(!m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(m.value_of("arg"), None);
}
#[test]
fn no_env_no_takes_value() {
// All the other tests use the presence of the Environment variable...
// we need another variable just in case one of the others is running at the same time...
env::remove_var("CLP_TEST_ENV_NONE");
let r = Command::new("df")
.arg(arg!([arg] "some opt").env("CLP_TEST_ENV_NONE"))
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(!m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(m.value_of("arg"), None);
}
#[test]
fn with_default() {
env::set_var("CLP_TEST_ENV_WD", "env");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_WD")
.takes_value(true)
.default_value("default"),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(m.value_of("arg").unwrap(), "env");
}
#[test]
fn opt_user_override() {
env::set_var("CLP_TEST_ENV_OR", "env");
let r = Command::new("df")
.arg(
arg!(--arg [FILE] "some arg")
.env("CLP_TEST_ENV_OR")
.takes_value(true),
)
.try_get_matches_from(vec!["", "--arg", "opt"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 1);
assert_eq!(m.value_of("arg").unwrap(), "opt");
// see https://github.com/clap-rs/clap/issues/1835
let values: Vec<_> = m.values_of("arg").unwrap().collect();
assert_eq!(values, vec!["opt"]);
}
#[test]
fn positionals() {
env::set_var("CLP_TEST_ENV_P", "env");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_P")
.takes_value(true),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(m.value_of("arg").unwrap(), "env");
}
#[test]
fn positionals_user_override() {
env::set_var("CLP_TEST_ENV_POR", "env");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_POR")
.takes_value(true),
)
.try_get_matches_from(vec!["", "opt"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 1);
assert_eq!(m.value_of("arg").unwrap(), "opt");
// see https://github.com/clap-rs/clap/issues/1835
let values: Vec<_> = m.values_of("arg").unwrap().collect();
assert_eq!(values, vec!["opt"]);
}
#[test]
fn multiple_one() {
env::set_var("CLP_TEST_ENV_MO", "env");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_MO")
.takes_value(true)
.use_value_delimiter(true)
.multiple_values(true),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(m.values_of("arg").unwrap().collect::<Vec<_>>(), vec!["env"]);
}
#[test]
fn multiple_three() {
env::set_var("CLP_TEST_ENV_MULTI1", "env1,env2,env3");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_MULTI1")
.takes_value(true)
.use_value_delimiter(true)
.multiple_values(true),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(
m.values_of("arg").unwrap().collect::<Vec<_>>(),
vec!["env1", "env2", "env3"]
);
}
#[test]
fn multiple_no_delimiter() {
env::set_var("CLP_TEST_ENV_MULTI2", "env1 env2 env3");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_MULTI2")
.takes_value(true)
.multiple_values(true),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(
m.values_of("arg").unwrap().collect::<Vec<_>>(),
vec!["env1 env2 env3"]
);
}
#[test]
fn possible_value() {
env::set_var("CLP_TEST_ENV_PV", "env");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_PV")
.takes_value(true)
.possible_value("env"),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(m.value_of("arg").unwrap(), "env");
}
#[test]
fn not_possible_value() {
env::set_var("CLP_TEST_ENV_NPV", "env");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_NPV")
.takes_value(true)
.possible_value("never"),
)
.try_get_matches_from(vec![""]);
assert!(r.is_err());
}
#[test]
fn validator() {
env::set_var("CLP_TEST_ENV_VDOR", "env");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_VDOR")
.takes_value(true)
.validator(|s| {
if s == "env" {
Ok(())
} else {
Err("not equal".to_string())
}
}),
)
.try_get_matches_from(vec![""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.occurrences_of("arg"), 0);
assert_eq!(m.value_of("arg").unwrap(), "env");
}
#[test]
fn validator_output() {
env::set_var("CLP_TEST_ENV_VO", "42");
let m = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_VO")
.takes_value(true)
.validator(|s| s.parse::<i32>()),
)
.try_get_matches_from(vec![""])
.unwrap();
assert_eq!(m.value_of("arg").unwrap().parse(), Ok(42));
}
#[test]
fn validator_invalid() {
env::set_var("CLP_TEST_ENV_IV", "env");
let r = Command::new("df")
.arg(
arg!([arg] "some opt")
.env("CLP_TEST_ENV_IV")
.takes_value(true)
.validator(|s| {
if s != "env" {
Ok(())
} else {
Err("is equal".to_string())
}
}),
)
.try_get_matches_from(vec![""]);
assert!(r.is_err());
}

View file

@ -1,90 +0,0 @@
use super::utils;
use clap::{arg, error::ErrorKind, Arg, Command, Error};
fn assert_error(err: Error, expected_kind: ErrorKind, expected_output: &str, stderr: bool) {
let actual_output = err.to_string();
assert_eq!(
stderr,
err.use_stderr(),
"Should Use STDERR failed. Should be {} but is {}",
stderr,
err.use_stderr()
);
assert_eq!(expected_kind, err.kind());
utils::assert_eq(expected_output, actual_output)
}
#[test]
fn app_error() {
static MESSAGE: &str = "error: Failed for mysterious reasons
USAGE:
test [OPTIONS] --all
For more information try --help
";
let cmd = Command::new("test")
.arg(
Arg::new("all")
.short('a')
.long("all")
.required(true)
.help("Also do versioning for private crates (will not be published)"),
)
.arg(
Arg::new("exact")
.long("exact")
.help("Specify inter dependency version numbers exactly with `=`"),
)
.arg(
Arg::new("no_git_commit")
.long("no-git-commit")
.help("Do not commit version changes"),
)
.arg(
Arg::new("no_git_push")
.long("no-git-push")
.help("Do not push generated commit and tags to git remote"),
);
let mut cmd = cmd;
let expected_kind = ErrorKind::InvalidValue;
let err = cmd.error(expected_kind, "Failed for mysterious reasons");
assert_error(err, expected_kind, MESSAGE, true);
}
#[test]
fn value_validation_has_newline() {
let m = Command::new("test")
.arg(arg!(<PORT>).help("Network port to use"))
.try_get_matches_from(["test", "foo"])
.unwrap();
let res = m.value_of_t::<usize>("PORT");
assert!(res.is_err());
let err = res.unwrap_err();
assert!(
err.to_string().ends_with('\n'),
"Errors should have a trailing newline, got {:?}",
err.to_string()
);
}
#[test]
fn argument_not_found_auto_has_newline() {
let m = Command::new("test")
.arg(arg!([PORT]).help("Network port to use"))
.try_get_matches_from(["test"])
.unwrap();
let res = m.value_of_t::<usize>("PORT");
assert!(res.is_err());
let err = res.unwrap_err();
assert!(
err.to_string().ends_with('\n'),
"Errors should have a trailing newline, got {:?}",
err.to_string()
);
}

View file

@ -1,613 +0,0 @@
use super::utils;
use clap::{arg, error::ErrorKind, Arg, Command};
#[test]
fn flag_subcommand_normal() {
let matches = Command::new("test")
.subcommand(
Command::new("some").short_flag('S').long_flag("some").arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
),
)
.try_get_matches_from(vec!["myprog", "some", "--test"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
let sub_matches = matches.subcommand_matches("some").unwrap();
assert!(sub_matches.is_present("test"));
}
#[test]
fn flag_subcommand_normal_with_alias() {
let matches = Command::new("test")
.subcommand(
Command::new("some")
.short_flag('S')
.long_flag("S")
.arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
)
.alias("result"),
)
.try_get_matches_from(vec!["myprog", "result", "--test"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
let sub_matches = matches.subcommand_matches("some").unwrap();
assert!(sub_matches.is_present("test"));
}
#[test]
fn flag_subcommand_short() {
let matches = Command::new("test")
.subcommand(
Command::new("some").short_flag('S').arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
),
)
.try_get_matches_from(vec!["myprog", "-S", "--test"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
let sub_matches = matches.subcommand_matches("some").unwrap();
assert!(sub_matches.is_present("test"));
}
#[test]
fn flag_subcommand_short_with_args() {
let matches = Command::new("test")
.subcommand(
Command::new("some").short_flag('S').arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
),
)
.try_get_matches_from(vec!["myprog", "-St"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
let sub_matches = matches.subcommand_matches("some").unwrap();
assert!(sub_matches.is_present("test"));
}
#[test]
fn flag_subcommand_short_with_alias() {
let matches = Command::new("test")
.subcommand(
Command::new("some")
.short_flag('S')
.arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
)
.short_flag_alias('M')
.short_flag_alias('B'),
)
.try_get_matches_from(vec!["myprog", "-Bt"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
let sub_matches = matches.subcommand_matches("some").unwrap();
assert!(sub_matches.is_present("test"));
}
#[test]
fn flag_subcommand_short_with_alias_same_as_short_flag() {
let matches = Command::new("test")
.subcommand(Command::new("some").short_flag('S').short_flag_alias('S'))
.try_get_matches_from(vec!["myprog", "-S"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
}
#[test]
fn flag_subcommand_long_with_alias_same_as_long_flag() {
let matches = Command::new("test")
.subcommand(
Command::new("some")
.long_flag("sync")
.long_flag_alias("sync"),
)
.try_get_matches_from(vec!["myprog", "--sync"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
}
#[test]
fn flag_subcommand_short_with_aliases_vis_and_hidden() {
let cmd = Command::new("test").subcommand(
Command::new("some")
.short_flag('S')
.arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
)
.visible_short_flag_aliases(&['M', 'B'])
.short_flag_alias('C'),
);
let app1 = cmd.clone();
let matches1 = app1.try_get_matches_from(vec!["test", "-M"]).unwrap();
assert_eq!(matches1.subcommand_name().unwrap(), "some");
let app2 = cmd.clone();
let matches2 = app2.try_get_matches_from(vec!["test", "-C"]).unwrap();
assert_eq!(matches2.subcommand_name().unwrap(), "some");
let app3 = cmd.clone();
let matches3 = app3.try_get_matches_from(vec!["test", "-B"]).unwrap();
assert_eq!(matches3.subcommand_name().unwrap(), "some");
}
#[test]
fn flag_subcommand_short_with_aliases() {
let matches = Command::new("test")
.subcommand(
Command::new("some")
.short_flag('S')
.arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
)
.short_flag_aliases(&['M', 'B']),
)
.try_get_matches_from(vec!["myprog", "-Bt"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
let sub_matches = matches.subcommand_matches("some").unwrap();
assert!(sub_matches.is_present("test"));
}
#[test]
#[should_panic]
fn flag_subcommand_short_with_alias_hyphen() {
let _ = Command::new("test")
.subcommand(
Command::new("some")
.short_flag('S')
.arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
)
.short_flag_alias('-'),
)
.try_get_matches_from(vec!["myprog", "-Bt"])
.unwrap();
}
#[test]
#[should_panic]
fn flag_subcommand_short_with_aliases_hyphen() {
let _ = Command::new("test")
.subcommand(
Command::new("some")
.short_flag('S')
.arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
)
.short_flag_aliases(&['-', '-', '-']),
)
.try_get_matches_from(vec!["myprog", "-Bt"])
.unwrap();
}
#[test]
fn flag_subcommand_short_after_long_arg() {
let m = Command::new("pacman")
.subcommand(
Command::new("sync")
.short_flag('S')
.arg(Arg::new("clean").short('c')),
)
.arg(Arg::new("arg").long("arg").takes_value(true))
.try_get_matches_from(vec!["pacman", "--arg", "foo", "-Sc"])
.unwrap();
let subm = m.subcommand_matches("sync");
assert!(subm.is_some());
let subm = subm.unwrap();
assert!(subm.is_present("clean"));
}
#[test]
fn flag_subcommand_long() {
let matches = Command::new("test")
.subcommand(
Command::new("some").long_flag("some").arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
),
)
.try_get_matches_from(vec!["myprog", "--some", "--test"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
let sub_matches = matches.subcommand_matches("some").unwrap();
assert!(sub_matches.is_present("test"));
}
#[test]
fn flag_subcommand_long_with_alias() {
let matches = Command::new("test")
.subcommand(
Command::new("some")
.long_flag("some")
.arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
)
.long_flag_alias("result"),
)
.try_get_matches_from(vec!["myprog", "--result", "--test"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
let sub_matches = matches.subcommand_matches("some").unwrap();
assert!(sub_matches.is_present("test"));
}
#[test]
fn flag_subcommand_long_with_aliases() {
let matches = Command::new("test")
.subcommand(
Command::new("some")
.long_flag("some")
.arg(
Arg::new("test")
.short('t')
.long("test")
.help("testing testing"),
)
.long_flag_aliases(&["result", "someall"]),
)
.try_get_matches_from(vec!["myprog", "--result", "--test"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
let sub_matches = matches.subcommand_matches("some").unwrap();
assert!(sub_matches.is_present("test"));
}
#[test]
fn flag_subcommand_multiple() {
let matches = Command::new("test")
.subcommand(
Command::new("some")
.short_flag('S')
.long_flag("some")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-p --print "print something"))
.subcommand(
Command::new("result")
.short_flag('R')
.long_flag("result")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-p --print "print something")),
),
)
.try_get_matches_from(vec!["myprog", "-SfpRfp"])
.unwrap();
assert_eq!(matches.subcommand_name().unwrap(), "some");
let sub_matches = matches.subcommand_matches("some").unwrap();
assert!(sub_matches.is_present("flag"));
assert!(sub_matches.is_present("print"));
assert_eq!(sub_matches.subcommand_name().unwrap(), "result");
let result_matches = sub_matches.subcommand_matches("result").unwrap();
assert!(result_matches.is_present("flag"));
assert!(result_matches.is_present("print"));
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "the \'-f\' short flag for the \'test\' argument conflicts with the short flag for \'some\' subcommand"]
fn flag_subcommand_short_conflict_with_arg() {
let _ = Command::new("test")
.subcommand(Command::new("some").short_flag('f').long_flag("some"))
.arg(Arg::new("test").short('f'))
.try_get_matches_from(vec!["myprog", "-f"])
.unwrap();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "the \'-f\' short flag is specified for both \'some\' and \'result\' subcommands"]
fn flag_subcommand_short_conflict_with_alias() {
let _ = Command::new("test")
.subcommand(Command::new("some").short_flag('f').long_flag("some"))
.subcommand(Command::new("result").short_flag('t').short_flag_alias('f'))
.try_get_matches_from(vec!["myprog", "-f"])
.unwrap();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "the \'--flag\' long flag is specified for both \'some\' and \'result\' subcommands"]
fn flag_subcommand_long_conflict_with_alias() {
let _ = Command::new("test")
.subcommand(Command::new("some").long_flag("flag"))
.subcommand(
Command::new("result")
.long_flag("test")
.long_flag_alias("flag"),
)
.try_get_matches_from(vec!["myprog", "--flag"])
.unwrap();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "the \'-f\' short flag for the \'test\' argument conflicts with the short flag for \'some\' subcommand"]
fn flag_subcommand_short_conflict_with_arg_alias() {
let _ = Command::new("test")
.subcommand(Command::new("some").short_flag('f').long_flag("some"))
.arg(Arg::new("test").short('t').short_alias('f'))
.try_get_matches_from(vec!["myprog", "-f"])
.unwrap();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "the \'--some\' long flag for the \'test\' argument conflicts with the short flag for \'some\' subcommand"]
fn flag_subcommand_long_conflict_with_arg_alias() {
let _ = Command::new("test")
.subcommand(Command::new("some").short_flag('f').long_flag("some"))
.arg(Arg::new("test").long("test").alias("some"))
.try_get_matches_from(vec!["myprog", "--some"])
.unwrap();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "the \'--flag\' long flag for the \'flag\' argument conflicts with the short flag for \'some\' subcommand"]
fn flag_subcommand_long_conflict_with_arg() {
let _ = Command::new("test")
.subcommand(Command::new("some").short_flag('a').long_flag("flag"))
.arg(Arg::new("flag").long("flag"))
.try_get_matches_from(vec!["myprog", "--flag"])
.unwrap();
}
#[test]
fn flag_subcommand_conflict_with_help() {
let _ = Command::new("test")
.subcommand(Command::new("help").short_flag('h').long_flag("help"))
.try_get_matches_from(vec!["myprog", "--help"])
.unwrap();
}
#[test]
fn flag_subcommand_conflict_with_version() {
let _ = Command::new("test")
.subcommand(Command::new("ver").short_flag('V').long_flag("version"))
.try_get_matches_from(vec!["myprog", "--version"])
.unwrap();
}
#[test]
fn flag_subcommand_long_infer_pass() {
let m = Command::new("prog")
.infer_subcommands(true)
.subcommand(Command::new("test").long_flag("test"))
.try_get_matches_from(vec!["prog", "--te"])
.unwrap();
assert_eq!(m.subcommand_name(), Some("test"));
}
#[cfg(not(feature = "suggestions"))]
#[test]
fn flag_subcommand_long_infer_fail() {
let m = Command::new("prog")
.infer_subcommands(true)
.subcommand(Command::new("test").long_flag("test"))
.subcommand(Command::new("temp").long_flag("temp"))
.try_get_matches_from(vec!["prog", "--te"]);
assert!(m.is_err(), "{:#?}", m.unwrap());
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
}
#[cfg(feature = "suggestions")]
#[test]
fn flag_subcommand_long_infer_fail() {
let m = Command::new("prog")
.infer_subcommands(true)
.subcommand(Command::new("test").long_flag("test"))
.subcommand(Command::new("temp").long_flag("temp"))
.try_get_matches_from(vec!["prog", "--te"]);
assert!(m.is_err(), "{:#?}", m.unwrap());
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
}
#[test]
fn flag_subcommand_long_infer_pass_close() {
let m = Command::new("prog")
.infer_subcommands(true)
.subcommand(Command::new("test").long_flag("test"))
.subcommand(Command::new("temp").long_flag("temp"))
.try_get_matches_from(vec!["prog", "--tes"])
.unwrap();
assert_eq!(m.subcommand_name(), Some("test"));
}
#[test]
fn flag_subcommand_long_infer_exact_match() {
let m = Command::new("prog")
.infer_subcommands(true)
.subcommand(Command::new("test").long_flag("test"))
.subcommand(Command::new("testa").long_flag("testa"))
.subcommand(Command::new("testb").long_flag("testb"))
.try_get_matches_from(vec!["prog", "--test"])
.unwrap();
assert_eq!(m.subcommand_name(), Some("test"));
}
static FLAG_SUBCOMMAND_HELP: &str = "pacman-query
Query the package database.
USAGE:
pacman {query|--query|-Q} [OPTIONS]
OPTIONS:
-h, --help Print help information
-i, --info <info>... view package information
-s, --search <search>... search locally installed packages for matching strings
";
#[test]
fn flag_subcommand_long_short_normal_usage_string() {
let cmd = Command::new("pacman")
.about("package manager utility")
.version("5.2.1")
.subcommand_required(true)
.author("Pacman Development Team")
// Query subcommand
//
// Only a few of its arguments are implemented below.
.subcommand(
Command::new("query")
.short_flag('Q')
.long_flag("query")
.about("Query the package database.")
.arg(
Arg::new("search")
.short('s')
.long("search")
.help("search locally installed packages for matching strings")
.conflicts_with("info")
.takes_value(true)
.multiple_values(true),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.takes_value(true)
.multiple_values(true),
),
);
utils::assert_output(cmd, "pacman -Qh", FLAG_SUBCOMMAND_HELP, false);
}
static FLAG_SUBCOMMAND_NO_SHORT_HELP: &str = "pacman-query
Query the package database.
USAGE:
pacman {query|--query} [OPTIONS]
OPTIONS:
-h, --help Print help information
-i, --info <info>... view package information
-s, --search <search>... search locally installed packages for matching strings
";
#[test]
fn flag_subcommand_long_normal_usage_string() {
let cmd = Command::new("pacman")
.about("package manager utility")
.version("5.2.1")
.subcommand_required(true)
.author("Pacman Development Team")
// Query subcommand
//
// Only a few of its arguments are implemented below.
.subcommand(
Command::new("query")
.long_flag("query")
.about("Query the package database.")
.arg(
Arg::new("search")
.short('s')
.long("search")
.help("search locally installed packages for matching strings")
.conflicts_with("info")
.takes_value(true)
.multiple_values(true),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.takes_value(true)
.multiple_values(true),
),
);
utils::assert_output(
cmd,
"pacman query --help",
FLAG_SUBCOMMAND_NO_SHORT_HELP,
false,
);
}
static FLAG_SUBCOMMAND_NO_LONG_HELP: &str = "pacman-query
Query the package database.
USAGE:
pacman {query|-Q} [OPTIONS]
OPTIONS:
-h, --help Print help information
-i, --info <info>... view package information
-s, --search <search>... search locally installed packages for matching strings
";
#[test]
fn flag_subcommand_short_normal_usage_string() {
let cmd = Command::new("pacman")
.about("package manager utility")
.version("5.2.1")
.subcommand_required(true)
.author("Pacman Development Team")
// Query subcommand
//
// Only a few of its arguments are implemented below.
.subcommand(
Command::new("query")
.short_flag('Q')
.about("Query the package database.")
.arg(
Arg::new("search")
.short('s')
.long("search")
.help("search locally installed packages for matching strings")
.conflicts_with("info")
.takes_value(true)
.multiple_values(true),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.takes_value(true)
.multiple_values(true),
),
);
utils::assert_output(
cmd,
"pacman query --help",
FLAG_SUBCOMMAND_NO_LONG_HELP,
false,
);
}

View file

@ -1,198 +0,0 @@
use super::utils;
use clap::{arg, Arg, Command};
const USE_FLAG_AS_ARGUMENT: &str =
"error: Found argument '--another-flag' which wasn't expected, or isn't valid in this context
\tIf you tried to supply `--another-flag` as a value rather than a flag, use `-- --another-flag`
USAGE:
mycat [OPTIONS] [filename]
For more information try --help
";
#[test]
fn flag_using_short() {
let m = Command::new("flag")
.args(&[
arg!(-f --flag "some flag"),
arg!(-c --color "some other flag"),
])
.try_get_matches_from(vec!["", "-f", "-c"])
.unwrap();
assert!(m.is_present("flag"));
assert!(m.is_present("color"));
}
#[test]
fn lots_o_flags_sep() {
let r = Command::new("opts")
.arg(arg!(o: -o ... "some flag"))
.try_get_matches_from(vec![
"", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
"-o", "-o", "-o",
]);
assert!(r.is_ok(), "{:?}", r.unwrap_err().kind());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.occurrences_of("o"), 297); // i.e. more than u8
}
#[test]
fn lots_o_flags_combined() {
let r = Command::new("opts")
.arg(arg!(o: -o ... "some flag"))
.try_get_matches_from(vec![
"",
"-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
"-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
"-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
"-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
"-ooooooooooooooooooooooooooooooooooooooooo",
]);
assert!(r.is_ok(), "{:?}", r.unwrap_err().kind());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.occurrences_of("o"), 297); // i.e. more than u8
}
#[test]
fn flag_using_long() {
let m = Command::new("flag")
.args(&[arg!(--flag "some flag"), arg!(--color "some other flag")])
.try_get_matches_from(vec!["", "--flag", "--color"])
.unwrap();
assert!(m.is_present("flag"));
assert!(m.is_present("color"));
}
#[test]
fn flag_using_long_with_literals() {
use clap::error::ErrorKind;
let m = Command::new("flag")
.arg(Arg::new("rainbow").long("rainbow"))
.try_get_matches_from(vec!["", "--rainbow=false"]);
assert!(m.is_err(), "{:#?}", m.unwrap());
assert_eq!(m.unwrap_err().kind(), ErrorKind::TooManyValues);
}
#[test]
fn flag_using_mixed() {
let m = Command::new("flag")
.args(&[
arg!(-f --flag "some flag"),
arg!(-c --color "some other flag"),
])
.try_get_matches_from(vec!["", "-f", "--color"])
.unwrap();
assert!(m.is_present("flag"));
assert!(m.is_present("color"));
let m = Command::new("flag")
.args(&[
arg!(-f --flag "some flag"),
arg!(-c --color "some other flag"),
])
.try_get_matches_from(vec!["", "--flag", "-c"])
.unwrap();
assert!(m.is_present("flag"));
assert!(m.is_present("color"));
}
#[test]
fn multiple_flags_in_single() {
let m = Command::new("multe_flags")
.args(&[
arg!(-f --flag "some flag"),
arg!(-c --color "some other flag"),
arg!(-d --debug "another other flag"),
])
.try_get_matches_from(vec!["", "-fcd"])
.unwrap();
assert!(m.is_present("flag"));
assert!(m.is_present("color"));
assert!(m.is_present("debug"));
}
#[test]
fn issue_1284_argument_in_flag_style() {
let cmd = Command::new("mycat")
.arg(Arg::new("filename"))
.arg(Arg::new("a-flag").long("a-flag"));
let m = cmd
.clone()
.try_get_matches_from(vec!["", "--", "--another-flag"])
.unwrap();
assert_eq!(m.value_of("filename"), Some("--another-flag"));
let m = cmd
.clone()
.try_get_matches_from(vec!["", "--a-flag"])
.unwrap();
assert!(m.is_present("a-flag"));
let m = cmd
.clone()
.try_get_matches_from(vec!["", "--", "--a-flag"])
.unwrap();
assert_eq!(m.value_of("filename"), Some("--a-flag"));
utils::assert_output(cmd, "mycat --another-flag", USE_FLAG_AS_ARGUMENT, true);
}
#[test]
fn issue_2308_multiple_dashes() {
static MULTIPLE_DASHES: &str =
"error: Found argument '-----' which wasn't expected, or isn't valid in this context
If you tried to supply `-----` as a value rather than a flag, use `-- -----`
USAGE:
test <arg>
For more information try --help
";
let cmd = Command::new("test").arg(Arg::new("arg").takes_value(true).required(true));
utils::assert_output(cmd, "test -----", MULTIPLE_DASHES, true);
}
#[test]
#[cfg(not(feature = "unstable-v4"))]
fn leading_dash_stripped() {
let cmd = Command::new("mycat").arg(Arg::new("filename").long("--filename"));
let matches = cmd.try_get_matches_from(["mycat", "--filename"]).unwrap();
assert!(matches.is_present("filename"));
}
#[test]
#[cfg(feature = "unstable-v4")]
#[cfg(debug_assertions)]
#[should_panic = "Argument filename: long \"--filename\" must not start with a `-`, that will be handled by the parser"]
fn leading_dash_stripped() {
let cmd = Command::new("mycat").arg(Arg::new("filename").long("--filename"));
cmd.debug_assert();
}

View file

@ -1,114 +0,0 @@
use clap::{arg, Arg, Command};
#[test]
fn issue_1076() {
let mut cmd = Command::new("myprog")
.arg(
Arg::new("GLOBAL_ARG")
.long("global-arg")
.help("Specifies something needed by the subcommands")
.global(true)
.takes_value(true)
.default_value("default_value"),
)
.arg(
Arg::new("GLOBAL_FLAG")
.long("global-flag")
.help("Specifies something needed by the subcommands")
.global(true)
.takes_value(true),
)
.subcommand(Command::new("outer").subcommand(Command::new("inner")));
let _ = cmd.try_get_matches_from_mut(vec!["myprog"]);
let _ = cmd.try_get_matches_from_mut(vec!["myprog"]);
let _ = cmd.try_get_matches_from_mut(vec!["myprog"]);
}
#[test]
fn propagate_global_arg_in_subcommand_to_subsubcommand_1385() {
let m1 = Command::new("foo")
.subcommand(
Command::new("sub1")
.arg(Arg::new("arg1").long("arg1").takes_value(true).global(true))
.subcommand(Command::new("sub1a")),
)
.try_get_matches_from(&["foo", "sub1", "--arg1", "v1", "sub1a"])
.unwrap();
assert_eq!(
"v1",
m1.subcommand_matches("sub1")
.unwrap()
.subcommand_matches("sub1a")
.unwrap()
.value_of("arg1")
.unwrap()
);
}
#[test]
fn propagate_global_arg_to_subcommand_in_subsubcommand_2053() {
let m = Command::new("opts")
.arg(arg!(--"global-flag").global(true))
.arg(arg!(--"global-str" <str>).required(false).global(true))
.subcommand(
Command::new("test")
.arg(arg!(--"sub-flag").global(true))
.arg(arg!(--"sub-str" <str>).required(false).global(true))
.subcommand(Command::new("test")),
)
.try_get_matches_from(&[
"cmd",
"test",
"test",
"--global-flag",
"--global-str",
"hello",
"--sub-flag",
"--sub-str",
"world",
])
.unwrap();
assert_eq!(
Some("world"),
m.subcommand_matches("test").unwrap().value_of("sub-str")
);
}
#[test]
fn global_arg_available_in_subcommand() {
let m = Command::new("opt")
.args(&[
Arg::new("global").global(true).long("global"),
Arg::new("not").global(false).long("not"),
])
.subcommand(Command::new("ping"))
.try_get_matches_from(&["opt", "ping", "--global"])
.unwrap();
assert!(m.is_present("global"));
assert!(m.subcommand_matches("ping").unwrap().is_present("global"));
}
#[test]
fn deeply_nested_discovery() {
let cmd = Command::new("a")
.arg(arg!(--"long-a").global(true))
.subcommand(
Command::new("b")
.arg(arg!(--"long-b").global(true))
.subcommand(
Command::new("c")
.arg(arg!(--"long-c").global(true))
.subcommand(Command::new("d")),
),
);
let m = cmd
.try_get_matches_from(["a", "b", "c", "d", "--long-a", "--long-b", "--long-c"])
.unwrap();
assert!(m.is_present("long-a"));
let m = m.subcommand_matches("b").unwrap();
assert!(m.is_present("long-b"));
let m = m.subcommand_matches("c").unwrap();
assert!(m.is_present("long-c"));
}

View file

@ -1,221 +0,0 @@
#![cfg(feature = "unstable-grouped")]
use clap::{Arg, Command};
#[test]
fn grouped_value_works() {
let m = Command::new("cli")
.arg(
Arg::new("option")
.long("option")
.takes_value(true)
.multiple_values(true)
.multiple_occurrences(true),
)
.try_get_matches_from(&[
"cli",
"--option",
"fr_FR:mon option 1",
"en_US:my option 1",
"--option",
"fr_FR:mon option 2",
"en_US:my option 2",
])
.unwrap();
let grouped_vals: Vec<_> = m.grouped_values_of("option").unwrap().collect();
assert_eq!(
grouped_vals,
vec![
vec!["fr_FR:mon option 1", "en_US:my option 1",],
vec!["fr_FR:mon option 2", "en_US:my option 2",],
]
);
}
#[test]
fn issue_1026() {
let m = Command::new("cli")
.arg(Arg::new("server").short('s').takes_value(true))
.arg(Arg::new("user").short('u').takes_value(true))
.arg(
Arg::new("target")
.long("target")
.takes_value(true)
.multiple_values(true)
.multiple_occurrences(true),
)
.try_get_matches_from(&[
"backup", "-s", "server", "-u", "user", "--target", "target1", "file1", "file2",
"file3", "--target", "target2", "file4", "file5", "file6", "file7", "--target",
"target3", "file8",
])
.unwrap();
let grouped_vals: Vec<_> = m.grouped_values_of("target").unwrap().collect();
assert_eq!(
grouped_vals,
vec![
vec!["target1", "file1", "file2", "file3"],
vec!["target2", "file4", "file5", "file6", "file7",],
vec!["target3", "file8"]
]
);
}
#[test]
fn grouped_value_long_flag_delimiter() {
let m = Command::new("myapp")
.arg(
Arg::new("option")
.long("option")
.takes_value(true)
.use_value_delimiter(true)
.multiple_values(true)
.multiple_occurrences(true),
)
.try_get_matches_from(vec![
"myapp",
"--option=hmm",
"--option=val1,val2,val3",
"--option",
"alice,bob",
])
.unwrap();
let grouped_vals: Vec<_> = m.grouped_values_of("option").unwrap().collect();
assert_eq!(
grouped_vals,
vec![
vec!["hmm"],
vec!["val1", "val2", "val3"],
vec!["alice", "bob"]
]
);
}
#[test]
fn grouped_value_short_flag_delimiter() {
let m = Command::new("myapp")
.arg(
Arg::new("option")
.short('o')
.takes_value(true)
.use_value_delimiter(true)
.multiple_values(true)
.multiple_occurrences(true),
)
.try_get_matches_from(vec!["myapp", "-o=foo", "-o=val1,val2,val3", "-o=bar"])
.unwrap();
let grouped_vals: Vec<_> = m.grouped_values_of("option").unwrap().collect();
assert_eq!(
grouped_vals,
vec![vec!["foo"], vec!["val1", "val2", "val3"], vec!["bar"]]
);
}
#[test]
fn grouped_value_positional_arg() {
let m = Command::new("multiple_values")
.arg(
Arg::new("pos")
.help("multiple positionals")
.takes_value(true)
.multiple_values(true),
)
.try_get_matches_from(vec![
"myprog", "val1", "val2", "val3", "val4", "val5", "val6",
])
.unwrap();
let grouped_vals: Vec<_> = m.grouped_values_of("pos").unwrap().collect();
assert_eq!(
grouped_vals,
vec![vec!["val1", "val2", "val3", "val4", "val5", "val6"]]
);
}
#[test]
fn grouped_value_multiple_positional_arg() {
let m = Command::new("multiple_values")
.arg(Arg::new("pos1").help("multiple positionals"))
.arg(
Arg::new("pos2")
.help("multiple positionals")
.takes_value(true)
.multiple_values(true),
)
.try_get_matches_from(vec![
"myprog", "val1", "val2", "val3", "val4", "val5", "val6",
])
.unwrap();
let grouped_vals: Vec<_> = m.grouped_values_of("pos2").unwrap().collect();
assert_eq!(
grouped_vals,
vec![vec!["val2", "val3", "val4", "val5", "val6"]]
);
}
#[test]
fn grouped_value_multiple_positional_arg_last_multiple() {
let m = Command::new("multiple_values")
.arg(Arg::new("pos1").help("multiple positionals"))
.arg(
Arg::new("pos2")
.help("multiple positionals")
.takes_value(true)
.multiple_values(true)
.last(true),
)
.try_get_matches_from(vec![
"myprog", "val1", "--", "val2", "val3", "val4", "val5", "val6",
])
.unwrap();
let grouped_vals: Vec<_> = m.grouped_values_of("pos2").unwrap().collect();
assert_eq!(
grouped_vals,
vec![vec!["val2", "val3", "val4", "val5", "val6"]]
);
}
#[test]
fn issue_1374() {
let cmd = Command::new("MyApp").arg(
Arg::new("input")
.takes_value(true)
.long("input")
.overrides_with("input")
.min_values(0)
.multiple_occurrences(true),
);
let matches = cmd
.clone()
.try_get_matches_from(&["MyApp", "--input", "a", "b", "c", "--input", "d"])
.unwrap();
let vs = matches.values_of("input").unwrap();
assert_eq!(vs.collect::<Vec<_>>(), vec!["a", "b", "c", "d"]);
let matches = cmd
.clone()
.try_get_matches_from(&["MyApp", "--input", "a", "b", "--input", "c", "d"])
.unwrap();
let vs = matches.values_of("input").unwrap();
assert_eq!(vs.collect::<Vec<_>>(), vec!["a", "b", "c", "d"]);
}
#[test]
fn issue_2171() {
let schema = Command::new("ripgrep#1701 reproducer")
.args_override_self(true)
.arg(Arg::new("pretty").short('p').long("pretty"))
.arg(Arg::new("search_zip").short('z').long("search-zip"));
let test_args = &[
vec!["reproducer", "-pz", "-p"],
vec!["reproducer", "-pzp"],
vec!["reproducer", "-zpp"],
vec!["reproducer", "-pp", "-z"],
vec!["reproducer", "-p", "-p", "-z"],
vec!["reproducer", "-p", "-pz"],
vec!["reproducer", "-ppz"],
];
for argv in test_args {
let _ = schema.clone().try_get_matches_from(argv).unwrap();
}
}

View file

@ -1,325 +0,0 @@
use super::utils;
use clap::{arg, error::ErrorKind, Arg, ArgGroup, Command};
static REQ_GROUP_USAGE: &str = "error: The following required arguments were not provided:
<base|--delete>
USAGE:
clap-test <base|--delete>
For more information try --help
";
static REQ_GROUP_CONFLICT_USAGE: &str =
"error: The argument '--delete' cannot be used with '<base>'
USAGE:
clap-test <base|--delete>
For more information try --help
";
static REQ_GROUP_CONFLICT_ONLY_OPTIONS: &str =
"error: The argument '--delete' cannot be used with '--all'
USAGE:
clap-test <--all|--delete>
For more information try --help
";
#[test]
fn required_group_missing_arg() {
let result = Command::new("group")
.arg(arg!(-f --flag "some flag"))
.arg(arg!( -c --color "some other flag"))
.group(ArgGroup::new("req").args(&["flag", "color"]).required(true))
.try_get_matches_from(vec![""]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument group 'req' contains non-existent argument"]
fn non_existing_arg() {
let _ = Command::new("group")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-c --color "some other flag"))
.group(ArgGroup::new("req").args(&["flg", "color"]).required(true))
.try_get_matches_from(vec![""]);
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument group name must be unique\n\n\t'req' is already in use"]
fn unique_group_name() {
let _ = Command::new("group")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-c --color "some other flag"))
.group(ArgGroup::new("req").args(&["flag"]).required(true))
.group(ArgGroup::new("req").args(&["color"]).required(true))
.try_get_matches_from(vec![""]);
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument group name '' must not conflict with argument name"]
fn groups_new_of_arg_name() {
let _ = Command::new("group")
.arg(Arg::new("a").long("a").group("a"))
.try_get_matches_from(vec!["", "--a"]);
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument group name 'a' must not conflict with argument name"]
fn arg_group_new_of_arg_name() {
let _ = Command::new("group")
.arg(Arg::new("a").long("a").group("a"))
.group(ArgGroup::new("a"))
.try_get_matches_from(vec!["", "--a"]);
}
#[test]
fn group_single_value() {
let res = Command::new("group")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-c --color [color] "some option"))
.group(ArgGroup::new("grp").args(&["flag", "color"]))
.try_get_matches_from(vec!["", "-c", "blue"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("grp"));
assert_eq!(m.value_of("grp").unwrap(), "blue");
}
#[test]
fn group_single_flag() {
let res = Command::new("group")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-c --color [color] "some option"))
.group(ArgGroup::new("grp").args(&["flag", "color"]))
.try_get_matches_from(vec!["", "-f"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("grp"));
assert!(m.value_of("grp").is_none());
}
#[test]
fn group_empty() {
let res = Command::new("group")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-c --color [color] "some option"))
.group(ArgGroup::new("grp").args(&["flag", "color"]))
.try_get_matches_from(vec![""]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(!m.is_present("grp"));
assert!(m.value_of("grp").is_none());
}
#[test]
fn group_reqired_flags_empty() {
let result = Command::new("group")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-c --color "some option"))
.group(ArgGroup::new("grp").required(true).args(&["flag", "color"]))
.try_get_matches_from(vec![""]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
}
#[test]
fn group_multi_value_single_arg() {
let res = Command::new("group")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-c --color <color> "some option").multiple_values(true))
.group(ArgGroup::new("grp").args(&["flag", "color"]))
.try_get_matches_from(vec!["", "-c", "blue", "red", "green"]);
assert!(res.is_ok(), "{:?}", res.unwrap_err().kind());
let m = res.unwrap();
assert!(m.is_present("grp"));
assert_eq!(
&*m.values_of("grp").unwrap().collect::<Vec<_>>(),
&["blue", "red", "green"]
);
}
#[test]
fn empty_group() {
let r = Command::new("empty_group")
.arg(arg!(-f --flag "some flag"))
.group(ArgGroup::new("vers").required(true))
.try_get_matches_from(vec!["empty_prog"]);
assert!(r.is_err());
let err = r.err().unwrap();
assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
}
#[test]
fn req_group_usage_string() {
let cmd = Command::new("req_group")
.arg(arg!([base] "Base commit"))
.arg(arg!(
-d --delete "Remove the base commit information"
))
.group(
ArgGroup::new("base_or_delete")
.args(&["base", "delete"])
.required(true),
);
utils::assert_output(cmd, "clap-test", REQ_GROUP_USAGE, true);
}
#[test]
fn req_group_with_conflict_usage_string() {
let cmd = Command::new("req_group")
.arg(arg!([base] "Base commit").conflicts_with("delete"))
.arg(arg!(
-d --delete "Remove the base commit information"
))
.group(
ArgGroup::new("base_or_delete")
.args(&["base", "delete"])
.required(true),
);
utils::assert_output(
cmd,
"clap-test --delete base",
REQ_GROUP_CONFLICT_USAGE,
true,
);
}
#[test]
fn req_group_with_conflict_usage_string_only_options() {
let cmd = Command::new("req_group")
.arg(arg!(-a --all "All").conflicts_with("delete"))
.arg(arg!(
-d --delete "Remove the base commit information"
))
.group(
ArgGroup::new("all_or_delete")
.args(&["all", "delete"])
.required(true),
);
utils::assert_output(
cmd,
"clap-test --delete --all",
REQ_GROUP_CONFLICT_ONLY_OPTIONS,
true,
);
}
#[test]
fn required_group_multiple_args() {
let result = Command::new("group")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-c --color "some other flag"))
.group(
ArgGroup::new("req")
.args(&["flag", "color"])
.required(true)
.multiple(true),
)
.try_get_matches_from(vec!["group", "-f", "-c"]);
assert!(result.is_ok(), "{}", result.unwrap_err());
let m = result.unwrap();
assert!(m.is_present("flag"));
assert!(m.is_present("color"));
}
#[test]
fn group_multiple_args_error() {
let result = Command::new("group")
.arg(arg!(-f --flag "some flag"))
.arg(arg!(-c --color "some other flag"))
.group(ArgGroup::new("req").args(&["flag", "color"]))
.try_get_matches_from(vec!["group", "-f", "-c"]);
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
}
#[test]
fn group_overrides_required() {
let command = Command::new("group")
.arg(arg!(--foo <FOO>))
.arg(arg!(--bar <BAR>))
.group(ArgGroup::new("group").args(&["foo", "bar"]).required(true));
let result = command.try_get_matches_from(vec!["group", "--foo", "value"]);
assert!(result.is_ok(), "{}", result.unwrap_err());
let m = result.unwrap();
assert!(m.is_present("foo"));
assert!(!m.is_present("bar"));
}
#[test]
fn group_usage_use_val_name() {
static GROUP_USAGE_USE_VAL_NAME: &str = "prog
USAGE:
prog <A>
ARGS:
<A>
OPTIONS:
-h, --help Print help information
";
let cmd = Command::new("prog")
.arg(Arg::new("a").value_name("A"))
.group(ArgGroup::new("group").arg("a").required(true));
utils::assert_output(cmd, "prog --help", GROUP_USAGE_USE_VAL_NAME, false);
}
#[test]
fn group_acts_like_arg() {
let result = Command::new("prog")
.arg(Arg::new("debug").long("debug").group("mode"))
.arg(Arg::new("verbose").long("verbose").group("mode"))
.try_get_matches_from(vec!["prog", "--debug"]);
assert!(result.is_ok(), "{}", result.unwrap_err());
let m = result.unwrap();
assert!(m.is_present("mode"));
}
/* This is used to be fixed in a hack, we need to find a better way to fix it.
#[test]
fn issue_1794() {
let cmd = clap::Command::new("hello")
.bin_name("deno")
.arg(Arg::new("option1").long("option1").takes_value(false))
.arg(Arg::new("pos1").takes_value(true))
.arg(Arg::new("pos2").takes_value(true))
.group(
ArgGroup::new("arg1")
.args(&["pos1", "option1"])
.required(true),
);
let m = cmd.clone().try_get_matches_from(&["cmd", "pos1", "pos2"]).unwrap();
assert_eq!(m.value_of("pos1"), Some("pos1"));
assert_eq!(m.value_of("pos2"), Some("pos2"));
assert!(!m.is_present("option1"));
let m = cmd
.clone()
.try_get_matches_from(&["cmd", "--option1", "positional"]).unwrap();
assert_eq!(m.value_of("pos1"), None);
assert_eq!(m.value_of("pos2"), Some("positional"));
assert!(m.is_present("option1"));
}
*/

File diff suppressed because it is too large Load diff

View file

@ -1,227 +0,0 @@
#![cfg(feature = "env")]
use std::env;
use clap::{Arg, Command};
use super::utils;
static HIDE_ENV: &str = "ctest 0.1
USAGE:
ctest [OPTIONS]
OPTIONS:
-c, --cafe <FILE> A coffeehouse, coffee shop, or café.
-h, --help Print help information
-V, --version Print version information
";
static SHOW_ENV: &str = "ctest 0.1
USAGE:
ctest [OPTIONS]
OPTIONS:
-c, --cafe <FILE> A coffeehouse, coffee shop, or café. [env: ENVVAR=MYVAL]
-h, --help Print help information
-V, --version Print version information
";
static HIDE_ENV_VALS: &str = "ctest 0.1
USAGE:
ctest [OPTIONS]
OPTIONS:
-c, --cafe <FILE> A coffeehouse, coffee shop, or café. [env: ENVVAR]
-h, --help Print help information
-V, --version Print version information
";
static SHOW_ENV_VALS: &str = "ctest 0.1
USAGE:
ctest [OPTIONS]
OPTIONS:
-c, --cafe <FILE> A coffeehouse, coffee shop, or café. [env: ENVVAR=MYVAL]
-h, --help Print help information
-V, --version Print version information
";
static HIDE_ENV_FLAG: &str = "ctest 0.1
USAGE:
ctest [OPTIONS]
OPTIONS:
-c, --cafe A coffeehouse, coffee shop, or café.
-h, --help Print help information
-V, --version Print version information
";
static SHOW_ENV_FLAG: &str = "ctest 0.1
USAGE:
ctest [OPTIONS]
OPTIONS:
-c, --cafe A coffeehouse, coffee shop, or café. [env: ENVVAR=MYVAL]
-h, --help Print help information
-V, --version Print version information
";
static HIDE_ENV_VALS_FLAG: &str = "ctest 0.1
USAGE:
ctest [OPTIONS]
OPTIONS:
-c, --cafe A coffeehouse, coffee shop, or café. [env: ENVVAR]
-h, --help Print help information
-V, --version Print version information
";
static SHOW_ENV_VALS_FLAG: &str = "ctest 0.1
USAGE:
ctest [OPTIONS]
OPTIONS:
-c, --cafe A coffeehouse, coffee shop, or café. [env: ENVVAR=MYVAL]
-h, --help Print help information
-V, --version Print version information
";
#[test]
fn hide_env() {
env::set_var("ENVVAR", "MYVAL");
let cmd = Command::new("ctest").version("0.1").arg(
Arg::new("cafe")
.short('c')
.long("cafe")
.value_name("FILE")
.hide_env(true)
.env("ENVVAR")
.help("A coffeehouse, coffee shop, or café.")
.takes_value(true),
);
utils::assert_output(cmd, "ctest --help", HIDE_ENV, false);
}
#[test]
fn show_env() {
env::set_var("ENVVAR", "MYVAL");
let cmd = Command::new("ctest").version("0.1").arg(
Arg::new("cafe")
.short('c')
.long("cafe")
.value_name("FILE")
.env("ENVVAR")
.help("A coffeehouse, coffee shop, or café.")
.takes_value(true),
);
utils::assert_output(cmd, "ctest --help", SHOW_ENV, false);
}
#[test]
fn hide_env_vals() {
env::set_var("ENVVAR", "MYVAL");
let cmd = Command::new("ctest").version("0.1").arg(
Arg::new("cafe")
.short('c')
.long("cafe")
.value_name("FILE")
.hide_env_values(true)
.env("ENVVAR")
.help("A coffeehouse, coffee shop, or café.")
.takes_value(true),
);
utils::assert_output(cmd, "ctest --help", HIDE_ENV_VALS, false);
}
#[test]
fn show_env_vals() {
env::set_var("ENVVAR", "MYVAL");
let cmd = Command::new("ctest").version("0.1").arg(
Arg::new("cafe")
.short('c')
.long("cafe")
.value_name("FILE")
.env("ENVVAR")
.help("A coffeehouse, coffee shop, or café.")
.takes_value(true),
);
utils::assert_output(cmd, "ctest --help", SHOW_ENV_VALS, false);
}
#[test]
fn hide_env_flag() {
env::set_var("ENVVAR", "MYVAL");
let cmd = Command::new("ctest").version("0.1").arg(
Arg::new("cafe")
.short('c')
.long("cafe")
.hide_env(true)
.env("ENVVAR")
.help("A coffeehouse, coffee shop, or café."),
);
utils::assert_output(cmd, "ctest --help", HIDE_ENV_FLAG, false);
}
#[test]
fn show_env_flag() {
env::set_var("ENVVAR", "MYVAL");
let cmd = Command::new("ctest").version("0.1").arg(
Arg::new("cafe")
.short('c')
.long("cafe")
.env("ENVVAR")
.help("A coffeehouse, coffee shop, or café."),
);
utils::assert_output(cmd, "ctest --help", SHOW_ENV_FLAG, false);
}
#[test]
fn hide_env_vals_flag() {
env::set_var("ENVVAR", "MYVAL");
let cmd = Command::new("ctest").version("0.1").arg(
Arg::new("cafe")
.short('c')
.long("cafe")
.hide_env_values(true)
.env("ENVVAR")
.help("A coffeehouse, coffee shop, or café."),
);
utils::assert_output(cmd, "ctest --help", HIDE_ENV_VALS_FLAG, false);
}
#[test]
fn show_env_vals_flag() {
env::set_var("ENVVAR", "MYVAL");
let cmd = Command::new("ctest").version("0.1").arg(
Arg::new("cafe")
.short('c')
.long("cafe")
.env("ENVVAR")
.help("A coffeehouse, coffee shop, or café."),
);
utils::assert_output(cmd, "ctest --help", SHOW_ENV_VALS_FLAG, false);
}

View file

@ -1,290 +0,0 @@
use super::utils;
use clap::{arg, Arg, Command};
static HIDDEN_ARGS: &str = "test 1.4
Kevin K.
tests stuff
USAGE:
test [OPTIONS]
OPTIONS:
-F, --flag2 some other flag
-h, --help Print help information
--option <opt> some option
-V, --version Print version information
";
#[test]
fn hide_args() {
let cmd = Command::new("test")
.author("Kevin K.")
.about("tests stuff")
.version("1.4")
.args(&[
arg!(-f --flag "some flag").hide(true),
arg!(-F --flag2 "some other flag"),
arg!(--option <opt> "some option").required(false),
Arg::new("DUMMY").hide(true),
]);
utils::assert_output(cmd, "test --help", HIDDEN_ARGS, false);
}
static HIDDEN_SHORT_ARGS: &str = "test 2.31.2
Steve P.
hides short args
USAGE:
test [OPTIONS]
OPTIONS:
-h, --help Print help information
-v, --visible This text should be visible
-V, --version Print version information
";
static HIDDEN_SHORT_ARGS_LONG_HELP: &str = "test 2.31.2
Steve P.
hides short args
USAGE:
test [OPTIONS]
OPTIONS:
-c, --config
Some help text describing the --config arg
-h, --help
Print help information
-v, --visible
This text should be visible
-V, --version
Print version information
";
/// Ensure hide with short option
#[test]
fn hide_short_args() {
let cmd = Command::new("test")
.about("hides short args")
.author("Steve P.")
.version("2.31.2")
.args(&[
Arg::new("cfg")
.short('c')
.long("config")
.hide_short_help(true)
.help("Some help text describing the --config arg"),
Arg::new("visible")
.short('v')
.long("visible")
.help("This text should be visible"),
]);
utils::assert_output(cmd, "test -h", HIDDEN_SHORT_ARGS, false);
}
/// Ensure visible with opposite option
#[test]
fn hide_short_args_long_help() {
let cmd = Command::new("test")
.about("hides short args")
.author("Steve P.")
.version("2.31.2")
.args(&[
Arg::new("cfg")
.short('c')
.long("config")
.hide_short_help(true)
.help("Some help text describing the --config arg"),
Arg::new("visible")
.short('v')
.long("visible")
.help("This text should be visible"),
]);
utils::assert_output(cmd, "test --help", HIDDEN_SHORT_ARGS_LONG_HELP, false);
}
static HIDDEN_LONG_ARGS: &str = "test 2.31.2
Steve P.
hides long args
USAGE:
test [OPTIONS]
OPTIONS:
-h, --help
Print help information
-v, --visible
This text should be visible
-V, --version
Print version information
";
#[test]
fn hide_long_args() {
let cmd = Command::new("test")
.about("hides long args")
.author("Steve P.")
.version("2.31.2")
.args(&[
Arg::new("cfg")
.short('c')
.long("config")
.hide_long_help(true)
.help("Some help text describing the --config arg"),
Arg::new("visible")
.short('v')
.long("visible")
.help("This text should be visible"),
]);
utils::assert_output(cmd, "test --help", HIDDEN_LONG_ARGS, false);
}
static HIDDEN_LONG_ARGS_SHORT_HELP: &str = "test 2.31.2
Steve P.
hides long args
USAGE:
test [OPTIONS]
OPTIONS:
-c, --config Some help text describing the --config arg
-h, --help Print help information
-v, --visible This text should be visible
-V, --version Print version information
";
#[test]
fn hide_long_args_short_help() {
let cmd = Command::new("test")
.about("hides long args")
.author("Steve P.")
.version("2.31.2")
.args(&[
Arg::new("cfg")
.short('c')
.long("config")
.hide_long_help(true)
.help("Some help text describing the --config arg"),
Arg::new("visible")
.short('v')
.long("visible")
.help("This text should be visible"),
]);
utils::assert_output(cmd, "test -h", HIDDEN_LONG_ARGS_SHORT_HELP, false);
}
static HIDDEN_POS_ARGS: &str = "test 1.4
USAGE:
test [another]
ARGS:
<another> another pos
OPTIONS:
-h, --help Print help information
-V, --version Print version information
";
#[test]
fn hide_pos_args() {
let cmd = Command::new("test").version("1.4").args(&[
Arg::new("pos").help("some pos").hide(true),
Arg::new("another").help("another pos"),
]);
utils::assert_output(cmd, "test --help", HIDDEN_POS_ARGS, false);
}
static HIDDEN_SUBCMDS: &str = "test 1.4
USAGE:
test
OPTIONS:
-h, --help Print help information
-V, --version Print version information
";
#[test]
fn hide_subcmds() {
let cmd = Command::new("test")
.version("1.4")
.subcommand(Command::new("sub").hide(true));
utils::assert_output(cmd, "test --help", HIDDEN_SUBCMDS, false);
}
static HIDDEN_OPT_ARGS_ONLY: &str = "test 1.4
USAGE:
test
After help
";
#[test]
fn hide_opt_args_only() {
let cmd = Command::new("test")
.version("1.4")
.after_help("After help")
.mut_arg("help", |a| a.hide(true))
.mut_arg("version", |a| a.hide(true))
.arg(
arg!(--option <opt> "some option")
.required(false)
.hide(true),
);
utils::assert_output(cmd, "test --help", HIDDEN_OPT_ARGS_ONLY, false);
}
static HIDDEN_POS_ARGS_ONLY: &str = "test 1.4
USAGE:
test
After help
";
#[test]
fn hide_pos_args_only() {
let cmd = Command::new("test")
.version("1.4")
.after_help("After help")
.mut_arg("help", |a| a.hide(true))
.mut_arg("version", |a| a.hide(true))
.args(&[Arg::new("pos").help("some pos").hide(true)]);
utils::assert_output(cmd, "test --help", HIDDEN_POS_ARGS_ONLY, false);
}
static HIDDEN_SUBCMDS_ONLY: &str = "test 1.4
USAGE:
test
After help
";
#[test]
fn hide_subcmds_only() {
let cmd = Command::new("test")
.version("1.4")
.after_help("After help")
.mut_arg("help", |a| a.hide(true))
.mut_arg("version", |a| a.hide(true))
.subcommand(Command::new("sub").hide(true));
utils::assert_output(cmd, "test --help", HIDDEN_SUBCMDS_ONLY, false);
}

View file

@ -1,117 +0,0 @@
use clap::{arg, Arg, Command};
#[test]
fn single_short_arg_without_value() {
let cmd = Command::new("cmd").ignore_errors(true).arg(arg!(
-c --config [FILE] "Sets a custom config file"
));
let r = cmd.try_get_matches_from(vec!["cmd", "-c" /* missing: , "config file" */]);
assert!(r.is_ok(), "unexpected error: {:?}", r);
let m = r.unwrap();
assert!(m.is_present("config"));
}
#[test]
fn single_long_arg_without_value() {
let cmd = Command::new("cmd").ignore_errors(true).arg(arg!(
-c --config [FILE] "Sets a custom config file"
));
let r = cmd.try_get_matches_from(vec!["cmd", "--config" /* missing: , "config file" */]);
assert!(r.is_ok(), "unexpected error: {:?}", r);
let m = r.unwrap();
assert!(m.is_present("config"));
}
#[test]
fn multiple_args_and_final_arg_without_value() {
let cmd = Command::new("cmd")
.ignore_errors(true)
.arg(arg!(
-c --config [FILE] "Sets a custom config file"
))
.arg(arg!(
-x --stuff [FILE] "Sets a custom stuff file"
))
.arg(arg!(f: -f "Flag"));
let r = cmd.try_get_matches_from(vec![
"cmd", "-c", "file", "-f", "-x", /* missing: , "some stuff" */
]);
assert!(r.is_ok(), "unexpected error: {:?}", r);
let m = r.unwrap();
assert_eq!(m.value_of("config"), Some("file"));
assert!(m.is_present("f"));
assert_eq!(m.value_of("stuff"), None);
}
#[test]
fn multiple_args_and_intermittent_arg_without_value() {
let cmd = Command::new("cmd")
.ignore_errors(true)
.arg(arg!(
-c --config[FILE] "Sets a custom config file"
))
.arg(arg!(
-x --stuff[FILE] "Sets a custom stuff file"
))
.arg(arg!(f: -f "Flag"));
let r = cmd.try_get_matches_from(vec![
"cmd", "-x", /* missing: ,"some stuff" */
"-c", "file", "-f",
]);
assert!(r.is_ok(), "unexpected error: {:?}", r);
let m = r.unwrap();
assert_eq!(m.value_of("config"), Some("file"));
assert!(m.is_present("f"));
assert_eq!(m.value_of("stuff"), None);
}
#[test]
fn subcommand() {
let cmd = Command::new("test")
.ignore_errors(true)
.subcommand(
Command::new("some")
.arg(
Arg::new("test")
.short('t')
.long("test")
.takes_value(true)
.help("testing testing"),
)
.arg(
Arg::new("stuff")
.short('x')
.long("stuff")
.takes_value(true)
.help("stuf value"),
),
)
.arg(Arg::new("other").long("other"));
let m = cmd
.try_get_matches_from(vec![
"myprog",
"some",
"--test", /* missing: ,"some val" */
"-x",
"some other val",
])
.unwrap();
assert_eq!(m.subcommand_name().unwrap(), "some");
let sub_m = m.subcommand_matches("some").unwrap();
assert!(
sub_m.is_present("test"),
"expected subcommand to be present due to partial parsing"
);
assert_eq!(sub_m.value_of("test"), None);
assert_eq!(sub_m.value_of("stuff"), Some("some other val"));
}

View file

@ -1,202 +0,0 @@
use clap::{Arg, Command};
#[test]
fn indices_mult_opts() {
let m = Command::new("ind")
.arg(
Arg::new("exclude")
.short('e')
.takes_value(true)
.multiple_values(true)
.multiple_occurrences(true),
)
.arg(
Arg::new("include")
.short('i')
.takes_value(true)
.multiple_values(true),
)
.try_get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"])
.unwrap();
assert_eq!(
m.indices_of("exclude").unwrap().collect::<Vec<_>>(),
&[2, 3, 8]
);
assert_eq!(
m.indices_of("include").unwrap().collect::<Vec<_>>(),
&[5, 6]
);
}
#[test]
fn index_mult_opts() {
let m = Command::new("ind")
.arg(
Arg::new("exclude")
.short('e')
.takes_value(true)
.multiple_values(true)
.multiple_occurrences(true),
)
.arg(
Arg::new("include")
.short('i')
.takes_value(true)
.multiple_values(true),
)
.try_get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"])
.unwrap();
assert_eq!(m.index_of("exclude"), Some(2));
assert_eq!(m.index_of("include"), Some(5));
}
#[test]
fn index_flag() {
let m = Command::new("ind")
.arg(Arg::new("exclude").short('e'))
.arg(Arg::new("include").short('i'))
.try_get_matches_from(vec!["ind", "-e", "-i"])
.unwrap();
assert_eq!(m.index_of("exclude"), Some(1));
assert_eq!(m.index_of("include"), Some(2));
}
#[test]
fn index_flags() {
let m = Command::new("ind")
.arg(Arg::new("exclude").short('e').multiple_occurrences(true))
.arg(Arg::new("include").short('i').multiple_occurrences(true))
.try_get_matches_from(vec!["ind", "-e", "-i", "-e", "-e", "-i"])
.unwrap();
assert_eq!(m.index_of("exclude"), Some(1));
assert_eq!(m.index_of("include"), Some(2));
}
#[test]
fn indices_mult_flags() {
let m = Command::new("ind")
.arg(Arg::new("exclude").short('e').multiple_occurrences(true))
.arg(Arg::new("include").short('i').multiple_occurrences(true))
.try_get_matches_from(vec!["ind", "-e", "-i", "-e", "-e", "-i"])
.unwrap();
assert_eq!(
m.indices_of("exclude").unwrap().collect::<Vec<_>>(),
&[1, 3, 4]
);
assert_eq!(
m.indices_of("include").unwrap().collect::<Vec<_>>(),
&[2, 5]
);
}
#[test]
fn indices_mult_flags_combined() {
let m = Command::new("ind")
.arg(Arg::new("exclude").short('e').multiple_occurrences(true))
.arg(Arg::new("include").short('i').multiple_occurrences(true))
.try_get_matches_from(vec!["ind", "-eieei"])
.unwrap();
assert_eq!(
m.indices_of("exclude").unwrap().collect::<Vec<_>>(),
&[1, 3, 4]
);
assert_eq!(
m.indices_of("include").unwrap().collect::<Vec<_>>(),
&[2, 5]
);
}
#[test]
fn indices_mult_flags_opt_combined() {
let m = Command::new("ind")
.arg(Arg::new("exclude").short('e').multiple_occurrences(true))
.arg(Arg::new("include").short('i').multiple_occurrences(true))
.arg(Arg::new("option").short('o').takes_value(true))
.try_get_matches_from(vec!["ind", "-eieeio", "val"])
.unwrap();
assert_eq!(
m.indices_of("exclude").unwrap().collect::<Vec<_>>(),
&[1, 3, 4]
);
assert_eq!(
m.indices_of("include").unwrap().collect::<Vec<_>>(),
&[2, 5]
);
assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[7]);
}
#[test]
fn indices_mult_flags_opt_combined_eq() {
let m = Command::new("ind")
.arg(Arg::new("exclude").short('e').multiple_occurrences(true))
.arg(Arg::new("include").short('i').multiple_occurrences(true))
.arg(Arg::new("option").short('o').takes_value(true))
.try_get_matches_from(vec!["ind", "-eieeio=val"])
.unwrap();
assert_eq!(
m.indices_of("exclude").unwrap().collect::<Vec<_>>(),
&[1, 3, 4]
);
assert_eq!(
m.indices_of("include").unwrap().collect::<Vec<_>>(),
&[2, 5]
);
assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[7]);
}
#[test]
fn indices_mult_opt_value_delim_eq() {
let m = Command::new("myapp")
.arg(
Arg::new("option")
.short('o')
.takes_value(true)
.use_value_delimiter(true)
.multiple_values(true),
)
.try_get_matches_from(vec!["myapp", "-o=val1,val2,val3"])
.unwrap();
assert_eq!(
m.indices_of("option").unwrap().collect::<Vec<_>>(),
&[2, 3, 4]
);
}
#[test]
fn indices_mult_opt_value_no_delim_eq() {
let m = Command::new("myapp")
.arg(
Arg::new("option")
.short('o')
.takes_value(true)
.multiple_values(true),
)
.try_get_matches_from(vec!["myapp", "-o=val1,val2,val3"])
.unwrap();
assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2]);
}
#[test]
fn indices_mult_opt_mult_flag() {
let m = Command::new("myapp")
.arg(
Arg::new("option")
.short('o')
.takes_value(true)
.multiple_occurrences(true),
)
.arg(Arg::new("flag").short('f').multiple_occurrences(true))
.try_get_matches_from(vec!["myapp", "-o", "val1", "-f", "-o", "val2", "-f"])
.unwrap();
assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 5]);
assert_eq!(m.indices_of("flag").unwrap().collect::<Vec<_>>(), &[3, 6]);
}

View file

@ -1,51 +0,0 @@
#![allow(deprecated)]
#![cfg(not(feature = "unstable-v4"))]
mod app_from_crate;
mod app_settings;
mod arg_aliases;
mod arg_aliases_short;
mod arg_matcher_assertions;
mod arg_settings;
mod borrowed;
mod cargo;
mod command;
mod conflicts;
mod default_missing_vals;
mod default_vals;
mod delimiters;
mod derive_order;
mod display_order;
mod double_require;
mod empty_values;
mod env;
mod error;
mod flag_subcommands;
mod flags;
mod global_args;
mod grouped_values;
mod groups;
mod help;
mod help_env;
mod hidden_args;
mod ignore_errors;
mod indices;
mod multiple_occurrences;
mod multiple_values;
mod opts;
mod positionals;
mod posix_compatible;
mod possible_values;
mod propagate_globals;
mod regex;
mod require;
mod subcommands;
mod template_help;
mod tests;
mod unicode;
mod unique_args;
mod utf16;
mod utf8;
mod utils;
mod validators;
mod version;

View file

@ -1,241 +0,0 @@
use clap::{arg, error::ErrorKind, Arg, Command};
#[test]
fn multiple_occurrences_of_flags_long() {
let m = Command::new("mo_flags_long")
.arg(arg!(--multflag "allowed multiple flag").multiple_occurrences(true))
.arg(arg!(--flag "disallowed multiple flag"))
.try_get_matches_from(vec!["", "--multflag", "--flag", "--multflag"])
.unwrap();
assert!(m.is_present("multflag"));
assert_eq!(m.occurrences_of("multflag"), 2);
assert!(m.is_present("flag"));
assert_eq!(m.occurrences_of("flag"), 1)
}
#[test]
fn multiple_occurrences_of_flags_short() {
let m = Command::new("mo_flags_short")
.arg(arg!(-m --multflag "allowed multiple flag").multiple_occurrences(true))
.arg(arg!(-f --flag "disallowed multiple flag"))
.try_get_matches_from(vec!["", "-m", "-f", "-m"])
.unwrap();
assert!(m.is_present("multflag"));
assert_eq!(m.occurrences_of("multflag"), 2);
assert!(m.is_present("flag"));
assert_eq!(m.occurrences_of("flag"), 1);
}
#[test]
fn multiple_occurrences_of_flags_mixed() {
let m = Command::new("mo_flags_mixed")
.arg(arg!(-m --multflag1 "allowed multiple flag").multiple_occurrences(true))
.arg(arg!(-n --multflag2 "another allowed multiple flag").multiple_occurrences(true))
.arg(arg!(-f --flag "disallowed multiple flag"))
.try_get_matches_from(vec![
"",
"-m",
"-f",
"-n",
"--multflag1",
"-m",
"--multflag2",
])
.unwrap();
assert!(m.is_present("multflag1"));
assert_eq!(m.occurrences_of("multflag1"), 3);
assert!(m.is_present("multflag2"));
assert_eq!(m.occurrences_of("multflag2"), 2);
assert!(m.is_present("flag"));
assert_eq!(m.occurrences_of("flag"), 1);
}
#[test]
fn multiple_occurrences_of_positional() {
let cmd = Command::new("test").arg(Arg::new("multi").multiple_occurrences(true));
let m = cmd
.clone()
.try_get_matches_from(&["test"])
.expect("zero occurrences work");
assert!(!m.is_present("multi"));
assert_eq!(m.occurrences_of("multi"), 0);
assert!(m.values_of("multi").is_none());
let m = cmd
.clone()
.try_get_matches_from(&["test", "one"])
.expect("single occurrence work");
assert!(m.is_present("multi"));
assert_eq!(m.occurrences_of("multi"), 1);
assert_eq!(m.values_of("multi").unwrap().collect::<Vec<_>>(), ["one"]);
let m = cmd
.clone()
.try_get_matches_from(&["test", "one", "two", "three", "four"])
.expect("many occurrences work");
assert!(m.is_present("multi"));
assert_eq!(m.occurrences_of("multi"), 4);
assert_eq!(
m.values_of("multi").unwrap().collect::<Vec<_>>(),
["one", "two", "three", "four"]
);
}
#[test]
fn multiple_occurrences_of_flags_large_quantity() {
let args: Vec<&str> = vec![""]
.into_iter()
.chain(vec!["-m"; 1024].into_iter())
.collect();
let m = Command::new("mo_flags_large_qty")
.arg(arg!(-m --multflag "allowed multiple flag").multiple_occurrences(true))
.try_get_matches_from(args)
.unwrap();
assert!(m.is_present("multflag"));
assert_eq!(m.occurrences_of("multflag"), 1024);
}
#[cfg(feature = "env")]
#[test]
fn multiple_occurrences_of_before_env() {
let cmd = Command::new("mo_before_env").arg(
Arg::new("verbose")
.env("VERBOSE")
.short('v')
.long("verbose")
.takes_value(false)
.multiple_occurrences(true),
);
let m = cmd.clone().try_get_matches_from(vec![""]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 0);
let m = cmd.clone().try_get_matches_from(vec!["", "-v"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 1);
let m = cmd.clone().try_get_matches_from(vec!["", "-vv"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 2);
let m = cmd.clone().try_get_matches_from(vec!["", "-vvv"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
}
#[cfg(feature = "env")]
#[test]
fn multiple_occurrences_of_after_env() {
let cmd = Command::new("mo_after_env").arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.takes_value(false)
.multiple_occurrences(true)
.env("VERBOSE"),
);
let m = cmd.clone().try_get_matches_from(vec![""]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 0);
let m = cmd.clone().try_get_matches_from(vec!["", "-v"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 1);
let m = cmd.clone().try_get_matches_from(vec!["", "-vv"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 2);
let m = cmd.clone().try_get_matches_from(vec!["", "-vvv"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
}
#[test]
fn max_occurrences_implies_multiple_occurrences() {
let cmd = Command::new("prog").arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.max_occurrences(3),
);
let m = cmd.try_get_matches_from(vec!["prog", "-vvv"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
// One max should not imply multiple occurrences
let cmd = Command::new("prog").arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.max_occurrences(1),
);
let m = cmd.try_get_matches_from(vec!["prog", "-vvv"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnexpectedMultipleUsage);
}
#[test]
fn max_occurrences_try_inputs() {
let cmd = Command::new("prog").arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.max_occurrences(3),
);
let m = cmd.clone().try_get_matches_from(vec!["prog", "-v"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 1);
let m = cmd.clone().try_get_matches_from(vec!["prog", "-vv"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 2);
let m = cmd.clone().try_get_matches_from(vec!["prog", "-vvv"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
let m = cmd.clone().try_get_matches_from(vec!["prog", "-vvvv"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::TooManyOccurrences);
let m = cmd
.clone()
.try_get_matches_from(vec!["prog", "-v", "-v", "-v"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
let m = cmd
.clone()
.try_get_matches_from(vec!["prog", "-v", "-vv", "-v"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::TooManyOccurrences);
}
#[test]
fn max_occurrences_positional() {
let cmd = Command::new("prog").arg(Arg::new("verbose").max_occurrences(3));
let m = cmd.clone().try_get_matches_from(vec!["prog", "v"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 1);
let m = cmd.clone().try_get_matches_from(vec!["prog", "v", "v"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 2);
let m = cmd
.clone()
.try_get_matches_from(vec!["prog", "v", "v", "v"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
let m = cmd
.clone()
.try_get_matches_from(vec!["prog", "v", "v", "v", "v"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::TooManyOccurrences);
}

File diff suppressed because it is too large Load diff

View file

@ -1,616 +0,0 @@
use super::utils;
use clap::{arg, error::ErrorKind, Arg, ArgMatches, Command};
#[cfg(feature = "suggestions")]
static DYM: &str =
"error: Found argument '--optio' which wasn't expected, or isn't valid in this context
\tDid you mean '--option'?
\tIf you tried to supply `--optio` as a value rather than a flag, use `-- --optio`
USAGE:
clap-test --option <opt>...
For more information try --help
";
#[cfg(feature = "suggestions")]
static DYM_ISSUE_1073: &str =
"error: Found argument '--files-without-matches' which wasn't expected, or isn't valid in this context
\tDid you mean '--files-without-match'?
\tIf you tried to supply `--files-without-matches` as a value rather than a flag, use `-- --files-without-matches`
USAGE:
ripgrep-616 --files-without-match
For more information try --help
";
#[test]
fn require_equals_fail() {
let res = Command::new("prog")
.arg(
Arg::new("cfg")
.require_equals(true)
.forbid_empty_values(true)
.takes_value(true)
.long("config"),
)
.try_get_matches_from(vec!["prog", "--config", "file.conf"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind(), ErrorKind::NoEquals);
}
#[test]
fn require_equals_fail_message() {
static NO_EQUALS: &str =
"error: Equal sign is needed when assigning values to '--config=<cfg>'.
USAGE:
prog [OPTIONS]
For more information try --help
";
let cmd = Command::new("prog").arg(
Arg::new("cfg")
.require_equals(true)
.takes_value(true)
.long("config"),
);
utils::assert_output(cmd, "prog --config file.conf", NO_EQUALS, true);
}
#[test]
fn require_equals_min_values_zero() {
let res = Command::new("prog")
.arg(
Arg::new("cfg")
.takes_value(true)
.require_equals(true)
.min_values(0)
.long("config"),
)
.arg(Arg::new("cmd"))
.try_get_matches_from(vec!["prog", "--config", "cmd"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("cfg"));
assert_eq!(m.value_of("cmd"), Some("cmd"));
}
#[test]
fn double_hyphen_as_value() {
let res = Command::new("prog")
.arg(
Arg::new("cfg")
.takes_value(true)
.allow_hyphen_values(true)
.long("config"),
)
.try_get_matches_from(vec!["prog", "--config", "--"]);
assert!(res.is_ok(), "{:?}", res);
assert_eq!(res.unwrap().value_of("cfg"), Some("--"));
}
#[test]
fn require_equals_no_empty_values_fail() {
let res = Command::new("prog")
.arg(
Arg::new("cfg")
.takes_value(true)
.require_equals(true)
.forbid_empty_values(true)
.long("config"),
)
.arg(Arg::new("some"))
.try_get_matches_from(vec!["prog", "--config=", "file.conf"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind(), ErrorKind::EmptyValue);
}
#[test]
fn require_equals_empty_vals_pass() {
let res = Command::new("prog")
.arg(
Arg::new("cfg")
.takes_value(true)
.require_equals(true)
.long("config"),
)
.try_get_matches_from(vec!["prog", "--config="]);
assert!(res.is_ok(), "{}", res.unwrap_err());
}
#[test]
fn require_equals_pass() {
let res = Command::new("prog")
.arg(
Arg::new("cfg")
.takes_value(true)
.require_equals(true)
.long("config"),
)
.try_get_matches_from(vec!["prog", "--config=file.conf"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
}
#[test]
fn stdin_char() {
let r = Command::new("opts")
.arg(arg!(f: -f [flag] "some flag"))
.try_get_matches_from(vec!["", "-f", "-"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("f"));
assert_eq!(m.value_of("f").unwrap(), "-");
}
#[test]
fn opts_using_short() {
let r = Command::new("opts")
.args(&[
arg!(f: -f [flag] "some flag"),
arg!(c: -c [color] "some other flag"),
])
.try_get_matches_from(vec!["", "-f", "some", "-c", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("f"));
assert_eq!(m.value_of("f").unwrap(), "some");
assert!(m.is_present("c"));
assert_eq!(m.value_of("c").unwrap(), "other");
}
#[test]
fn lots_o_vals() {
let r = Command::new("opts")
.arg(arg!(o: -o <opt> "some opt").multiple_values(true))
.try_get_matches_from(vec![
"", "-o", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some",
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.values_of("o").unwrap().count(), 297); // i.e. more than u8
}
#[test]
fn opts_using_long_space() {
let r = Command::new("opts")
.args(&[
arg!(--flag [flag] "some flag"),
arg!(--color [color] "some other flag"),
])
.try_get_matches_from(vec!["", "--flag", "some", "--color", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("flag"));
assert_eq!(m.value_of("flag").unwrap(), "some");
assert!(m.is_present("color"));
assert_eq!(m.value_of("color").unwrap(), "other");
}
#[test]
fn opts_using_long_equals() {
let r = Command::new("opts")
.args(&[
arg!(--flag [flag] "some flag"),
arg!(--color [color] "some other flag"),
])
.try_get_matches_from(vec!["", "--flag=some", "--color=other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("flag"));
assert_eq!(m.value_of("flag").unwrap(), "some");
assert!(m.is_present("color"));
assert_eq!(m.value_of("color").unwrap(), "other");
}
#[test]
fn opts_using_mixed() {
let r = Command::new("opts")
.args(&[
arg!(-f --flag [flag] "some flag"),
arg!(-c --color [color] "some other flag"),
])
.try_get_matches_from(vec!["", "-f", "some", "--color", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("flag"));
assert_eq!(m.value_of("flag").unwrap(), "some");
assert!(m.is_present("color"));
assert_eq!(m.value_of("color").unwrap(), "other");
}
#[test]
fn opts_using_mixed2() {
let r = Command::new("opts")
.args(&[
arg!(-f --flag [flag] "some flag"),
arg!(-c --color [color] "some other flag"),
])
.try_get_matches_from(vec!["", "--flag=some", "-c", "other"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("flag"));
assert_eq!(m.value_of("flag").unwrap(), "some");
assert!(m.is_present("color"));
assert_eq!(m.value_of("color").unwrap(), "other");
}
#[test]
fn default_values_user_value() {
let r = Command::new("df")
.arg(arg!(o: -o [opt] "some opt").default_value("default"))
.try_get_matches_from(vec!["", "-o", "value"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.value_of("o").unwrap(), "value");
}
#[test]
fn multiple_vals_pos_arg_equals() {
let r = Command::new("mvae")
.arg(arg!(o: -o [opt] ... "some opt"))
.arg(arg!([file] "some file"))
.try_get_matches_from(vec!["", "-o=1", "some"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.value_of("o").unwrap(), "1");
assert!(m.is_present("file"));
assert_eq!(m.value_of("file").unwrap(), "some");
}
#[test]
fn multiple_vals_pos_arg_delim() {
let r = Command::new("mvae")
.arg(
arg!(o: -o <opt> "some opt")
.multiple_values(true)
.use_value_delimiter(true),
)
.arg(arg!([file] "some file"))
.try_get_matches_from(vec!["", "-o", "1,2", "some"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["1", "2"]);
assert!(m.is_present("file"));
assert_eq!(m.value_of("file").unwrap(), "some");
}
#[test]
fn require_delims_no_delim() {
let r = Command::new("mvae")
.arg(
arg!(o: -o [opt] ... "some opt")
.use_value_delimiter(true)
.require_value_delimiter(true),
)
.arg(arg!([file] "some file"))
.try_get_matches_from(vec!["mvae", "-o", "1", "2", "some"]);
assert!(r.is_err());
let err = r.unwrap_err();
assert_eq!(err.kind(), ErrorKind::UnknownArgument);
}
#[test]
fn require_delims() {
let r = Command::new("mvae")
.arg(
arg!(o: -o <opt> "some opt")
.multiple_values(true)
.use_value_delimiter(true)
.require_value_delimiter(true),
)
.arg(arg!([file] "some file"))
.try_get_matches_from(vec!["", "-o", "1,2", "some"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["1", "2"]);
assert!(m.is_present("file"));
assert_eq!(m.value_of("file").unwrap(), "some");
}
#[test]
fn leading_hyphen_pass() {
let r = Command::new("mvae")
.arg(
arg!(o: -o <opt> "some opt")
.multiple_values(true)
.allow_hyphen_values(true),
)
.try_get_matches_from(vec!["", "-o", "-2", "3"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2", "3"]);
}
#[test]
fn leading_hyphen_fail() {
let r = Command::new("mvae")
.arg(arg!(o: -o <opt> "some opt"))
.try_get_matches_from(vec!["", "-o", "-2"]);
assert!(r.is_err());
let m = r.unwrap_err();
assert_eq!(m.kind(), ErrorKind::UnknownArgument);
}
#[test]
fn leading_hyphen_with_flag_after() {
let r = Command::new("mvae")
.arg(
arg!(o: -o <opt> "some opt")
.multiple_values(true)
.allow_hyphen_values(true),
)
.arg(arg!(f: -f "some flag"))
.try_get_matches_from(vec!["", "-o", "-2", "-f"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2", "-f"]);
assert!(!m.is_present("f"));
}
#[test]
fn leading_hyphen_with_flag_before() {
let r = Command::new("mvae")
.arg(arg!(o: -o [opt] ... "some opt").allow_hyphen_values(true))
.arg(arg!(f: -f "some flag"))
.try_get_matches_from(vec!["", "-f", "-o", "-2"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2"]);
assert!(m.is_present("f"));
}
#[test]
fn leading_hyphen_with_only_pos_follows() {
let r = Command::new("mvae")
.arg(
arg!(o: -o [opt] ... "some opt")
.number_of_values(1)
.takes_value(true)
.allow_hyphen_values(true),
)
.arg(arg!([arg] "some arg"))
.try_get_matches_from(vec!["", "-o", "-2", "--", "val"]);
assert!(r.is_ok(), "{:?}", r);
let m = r.unwrap();
assert!(m.is_present("o"));
assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2"]);
assert_eq!(m.value_of("arg"), Some("val"));
}
#[test]
#[cfg(feature = "suggestions")]
fn did_you_mean() {
utils::assert_output(utils::complex_app(), "clap-test --optio=foo", DYM, true);
}
#[test]
fn issue_1047_min_zero_vals_default_val() {
let m = Command::new("foo")
.arg(
Arg::new("del")
.short('d')
.long("del")
.takes_value(true)
.require_equals(true)
.min_values(0)
.default_missing_value("default"),
)
.try_get_matches_from(vec!["foo", "-d"])
.unwrap();
assert_eq!(m.occurrences_of("del"), 1);
assert_eq!(m.value_of("del"), Some("default"));
}
fn issue_1105_setup(argv: Vec<&'static str>) -> Result<ArgMatches, clap::Error> {
Command::new("opts")
.arg(arg!(-o --option <opt> "some option"))
.arg(arg!(--flag "some flag"))
.try_get_matches_from(argv)
}
#[test]
fn issue_1105_empty_value_long_fail() {
let r = issue_1105_setup(vec!["cmd", "--option", "--flag"]);
assert!(r.is_err());
assert_eq!(r.unwrap_err().kind(), ErrorKind::EmptyValue);
}
#[test]
fn issue_1105_empty_value_long_explicit() {
let r = issue_1105_setup(vec!["cmd", "--option", ""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert_eq!(m.value_of("option"), Some(""));
}
#[test]
fn issue_1105_empty_value_long_equals() {
let r = issue_1105_setup(vec!["cmd", "--option="]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert_eq!(m.value_of("option"), Some(""));
}
#[test]
fn issue_1105_empty_value_short_fail() {
let r = issue_1105_setup(vec!["cmd", "-o", "--flag"]);
assert!(r.is_err());
assert_eq!(r.unwrap_err().kind(), ErrorKind::EmptyValue);
}
#[test]
fn issue_1105_empty_value_short_explicit() {
let r = issue_1105_setup(vec!["cmd", "-o", ""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert_eq!(m.value_of("option"), Some(""));
}
#[test]
fn issue_1105_empty_value_short_equals() {
let r = issue_1105_setup(vec!["cmd", "-o="]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert_eq!(m.value_of("option"), Some(""));
}
#[test]
fn issue_1105_empty_value_short_explicit_no_space() {
let r = issue_1105_setup(vec!["cmd", "-o", ""]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert_eq!(m.value_of("option"), Some(""));
}
#[test]
#[cfg(feature = "suggestions")]
fn issue_1073_suboptimal_flag_suggestion() {
let cmd = Command::new("ripgrep-616")
.arg(Arg::new("files-with-matches").long("files-with-matches"))
.arg(Arg::new("files-without-match").long("files-without-match"));
utils::assert_output(
cmd,
"ripgrep-616 --files-without-matches",
DYM_ISSUE_1073,
true,
);
}
#[test]
fn short_non_ascii_no_space() {
let matches = Command::new("cmd")
.arg(arg!(opt: -'磨' <opt>))
.try_get_matches_from(&["test", "-磨VALUE"])
.unwrap();
assert_eq!("VALUE", matches.value_of("opt").unwrap());
}
#[test]
fn short_eq_val_starts_with_eq() {
let matches = Command::new("cmd")
.arg(arg!(opt: -f <opt>))
.try_get_matches_from(&["test", "-f==value"])
.unwrap();
assert_eq!("=value", matches.value_of("opt").unwrap());
}
#[test]
fn long_eq_val_starts_with_eq() {
let matches = Command::new("cmd")
.arg(arg!(opt: --foo <opt>))
.try_get_matches_from(&["test", "--foo==value"])
.unwrap();
assert_eq!("=value", matches.value_of("opt").unwrap());
}
#[test]
fn issue_2022_get_flags_misuse() {
let cmd = Command::new("test")
.next_help_heading(Some("test"))
.arg(Arg::new("a").long("a").default_value("32"));
let matches = cmd.try_get_matches_from(&[""]).unwrap();
assert!(matches.value_of("a").is_some())
}
#[test]
fn issue_2279() {
let before_help_heading = Command::new("cmd")
.arg(Arg::new("foo").short('f').default_value("bar"))
.next_help_heading(Some("This causes default_value to be ignored"))
.try_get_matches_from(&[""])
.unwrap();
assert_eq!(before_help_heading.value_of("foo"), Some("bar"));
let after_help_heading = Command::new("cmd")
.next_help_heading(Some("This causes default_value to be ignored"))
.arg(Arg::new("foo").short('f').default_value("bar"))
.try_get_matches_from(&[""])
.unwrap();
assert_eq!(after_help_heading.value_of("foo"), Some("bar"));
}
#[test]
fn infer_long_arg() {
let cmd = Command::new("test")
.infer_long_args(true)
.arg(Arg::new("racetrack").long("racetrack").alias("autobahn"))
.arg(Arg::new("racecar").long("racecar").takes_value(true));
let matches = cmd
.clone()
.try_get_matches_from(&["test", "--racec=hello"])
.unwrap();
assert!(!matches.is_present("racetrack"));
assert_eq!(matches.value_of("racecar"), Some("hello"));
let matches = cmd
.clone()
.try_get_matches_from(&["test", "--racet"])
.unwrap();
assert!(matches.is_present("racetrack"));
assert_eq!(matches.value_of("racecar"), None);
let matches = cmd
.clone()
.try_get_matches_from(&["test", "--auto"])
.unwrap();
assert!(matches.is_present("racetrack"));
assert_eq!(matches.value_of("racecar"), None);
let cmd = Command::new("test")
.infer_long_args(true)
.arg(Arg::new("arg").long("arg"));
let matches = cmd.clone().try_get_matches_from(&["test", "--"]).unwrap();
assert!(!matches.is_present("arg"));
let matches = cmd.clone().try_get_matches_from(&["test", "--a"]).unwrap();
assert!(matches.is_present("arg"));
}

View file

@ -1,310 +0,0 @@
use clap::{arg, error::ErrorKind, Arg, Command};
#[test]
fn only_pos_follow() {
let r = Command::new("onlypos")
.args(&[arg!(f: -f [flag] "some opt"), arg!([arg] "some arg")])
.try_get_matches_from(vec!["", "--", "-f"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert!(!m.is_present("f"));
assert_eq!(m.value_of("arg").unwrap(), "-f");
}
#[test]
fn issue_946() {
let r = Command::new("compiletest")
.allow_hyphen_values(true)
.arg(arg!(--exact "filters match exactly"))
.arg(
clap::Arg::new("filter")
.index(1)
.takes_value(true)
.help("filters to apply to output"),
)
.try_get_matches_from(vec!["compiletest", "--exact"]);
assert!(r.is_ok(), "{:#?}", r);
let matches = r.unwrap();
assert!(matches.is_present("exact"));
assert!(matches.value_of("filter").is_none());
}
#[test]
fn positional() {
let r = Command::new("positional")
.args(&[arg!(-f --flag "some flag"), Arg::new("positional").index(1)])
.try_get_matches_from(vec!["", "-f", "test"]);
assert!(r.is_ok(), "{:#?}", r);
let m = r.unwrap();
assert!(m.is_present("positional"));
assert!(m.is_present("flag"));
assert_eq!(m.value_of("positional").unwrap(), "test");
let m = Command::new("positional")
.args(&[arg!(-f --flag "some flag"), Arg::new("positional").index(1)])
.try_get_matches_from(vec!["", "test", "--flag"])
.unwrap();
assert!(m.is_present("positional"));
assert!(m.is_present("flag"));
assert_eq!(m.value_of("positional").unwrap(), "test");
}
#[test]
fn lots_o_vals() {
let r = Command::new("opts")
.arg(arg!(<opt>... "some pos"))
.try_get_matches_from(vec![
"", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some",
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("opt"));
assert_eq!(m.values_of("opt").unwrap().count(), 297); // i.e. more than u8
}
#[test]
fn positional_multiple() {
let r = Command::new("positional_multiple")
.args(&[
arg!(-f --flag "some flag"),
Arg::new("positional")
.index(1)
.takes_value(true)
.multiple_values(true),
])
.try_get_matches_from(vec!["", "-f", "test1", "test2", "test3"]);
assert!(r.is_ok(), "{:#?}", r);
let m = r.unwrap();
assert!(m.is_present("positional"));
assert!(m.is_present("flag"));
assert_eq!(
&*m.values_of("positional").unwrap().collect::<Vec<_>>(),
&["test1", "test2", "test3"]
);
}
#[test]
fn positional_multiple_3() {
let r = Command::new("positional_multiple")
.args(&[
arg!(-f --flag "some flag"),
Arg::new("positional")
.index(1)
.takes_value(true)
.multiple_values(true),
])
.try_get_matches_from(vec!["", "test1", "test2", "test3", "--flag"]);
assert!(r.is_ok(), "{:#?}", r);
let m = r.unwrap();
assert!(m.is_present("positional"));
assert!(m.is_present("flag"));
assert_eq!(
&*m.values_of("positional").unwrap().collect::<Vec<_>>(),
&["test1", "test2", "test3"]
);
}
#[test]
fn positional_multiple_2() {
let result = Command::new("positional_multiple")
.args(&[arg!(-f --flag "some flag"), Arg::new("positional").index(1)])
.try_get_matches_from(vec!["", "-f", "test1", "test2", "test3"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::UnknownArgument);
}
#[test]
fn positional_possible_values() {
let r = Command::new("positional_possible_values")
.args(&[
arg!(-f --flag "some flag"),
Arg::new("positional").index(1).possible_value("test123"),
])
.try_get_matches_from(vec!["", "-f", "test123"]);
assert!(r.is_ok(), "{:#?}", r);
let m = r.unwrap();
assert!(m.is_present("positional"));
assert!(m.is_present("flag"));
assert_eq!(
&*m.values_of("positional").unwrap().collect::<Vec<_>>(),
&["test123"]
);
}
#[test]
fn create_positional() {
let _ = Command::new("test")
.arg(Arg::new("test").index(1).help("testing testing"))
.try_get_matches_from(vec![""])
.unwrap();
}
#[test]
fn positional_hyphen_does_not_panic() {
let _ = Command::new("test")
.arg(Arg::new("dummy"))
.try_get_matches_from(vec!["test", "-"])
.unwrap();
}
#[test]
fn single_positional_usage_string() {
let mut cmd = Command::new("test").arg(arg!([FILE] "some file"));
assert_eq!(cmd.render_usage(), "USAGE:\n test [FILE]");
}
#[test]
fn single_positional_multiple_usage_string() {
let mut cmd = Command::new("test").arg(arg!([FILE]... "some file"));
assert_eq!(cmd.render_usage(), "USAGE:\n test [FILE]...");
}
#[test]
fn multiple_positional_usage_string() {
let mut cmd = Command::new("test")
.arg(arg!([FILE] "some file"))
.arg(arg!([FILES]... "some file"));
assert_eq!(cmd.render_usage(), "USAGE:\n test [ARGS]");
}
#[test]
fn multiple_positional_one_required_usage_string() {
let mut cmd = Command::new("test")
.arg(arg!(<FILE> "some file"))
.arg(arg!([FILES]... "some file"));
assert_eq!(cmd.render_usage(), "USAGE:\n test <FILE> [FILES]...");
}
#[test]
fn single_positional_required_usage_string() {
let mut cmd = Command::new("test").arg(arg!(<FILE> "some file"));
assert_eq!(cmd.render_usage(), "USAGE:\n test <FILE>");
}
// This tests a programmer error and will only succeed with debug_assertions
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Found non-required positional argument \
with a lower index than a required positional argument"]
fn missing_required() {
let _ = Command::new("test")
.arg(arg!([FILE1] "some file"))
.arg(arg!(<FILE2> "some file"))
.try_get_matches_from(vec![""]);
}
#[test]
fn missing_required_2() {
let r = Command::new("test")
.arg(arg!(<FILE1> "some file"))
.arg(arg!(<FILE2> "some file"))
.try_get_matches_from(vec!["test", "file"]);
assert!(r.is_err());
assert_eq!(r.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
}
#[test]
fn last_positional() {
let r = Command::new("test")
.arg(arg!(<TARGET> "some target"))
.arg(arg!([CORPUS] "some corpus"))
.arg(arg!([ARGS]... "some file").last(true))
.try_get_matches_from(vec!["test", "tgt", "--", "arg"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert_eq!(m.values_of("ARGS").unwrap().collect::<Vec<_>>(), &["arg"]);
}
#[test]
fn last_positional_no_double_dash() {
let r = Command::new("test")
.arg(arg!(<TARGET> "some target"))
.arg(arg!([CORPUS] "some corpus"))
.arg(arg!([ARGS]... "some file").last(true))
.try_get_matches_from(vec!["test", "tgt", "crp", "arg"]);
assert!(r.is_err());
assert_eq!(r.unwrap_err().kind(), ErrorKind::UnknownArgument);
}
#[test]
fn last_positional_second_to_last_mult() {
let r = Command::new("test")
.arg(arg!(<TARGET> "some target"))
.arg(arg!([CORPUS]... "some corpus"))
.arg(arg!([ARGS]... "some file").last(true))
.try_get_matches_from(vec!["test", "tgt", "crp1", "crp2", "--", "arg"]);
assert!(r.is_ok(), "{:?}", r.unwrap_err().kind());
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument 'arg' is a positional argument and can't have short or long name versions"]
fn positional_arg_with_long() {
use clap::{Arg, Command};
let _ = Command::new("test")
.arg(Arg::new("arg").index(1).long("arg"))
.try_get_matches();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument 'arg' is a positional argument and can't have short or long name versions"]
fn positional_arg_with_short() {
use clap::{Arg, Command};
let _ = Command::new("test")
.arg(Arg::new("arg").index(1).short('a'))
.try_get_matches();
}
#[test]
fn ignore_hyphen_values_on_last() {
let cmd = clap::Command::new("foo")
.arg(
clap::Arg::new("cmd")
.multiple_values(true)
.last(true)
.allow_hyphen_values(true),
)
.arg(
clap::Arg::new("name")
.long("name")
.short('n')
.takes_value(true)
.required(false),
);
let matches = cmd.try_get_matches_from(["test", "-n", "foo"]).unwrap();
assert_eq!(matches.value_of("name"), Some("foo"));
}

View file

@ -1,401 +0,0 @@
use clap::{arg, error::ErrorKind, Arg, Command};
#[test]
fn flag_overrides_itself() {
let res = Command::new("posix")
.arg(
arg!(--flag "some flag"
)
.overrides_with("flag"),
)
.try_get_matches_from(vec!["", "--flag", "--flag"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("flag"));
assert_eq!(m.occurrences_of("flag"), 1);
}
#[test]
fn mult_flag_overrides_itself() {
let res = Command::new("posix")
.arg(arg!(--flag ... "some flag").overrides_with("flag"))
.try_get_matches_from(vec!["", "--flag", "--flag", "--flag", "--flag"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("flag"));
assert_eq!(m.occurrences_of("flag"), 4);
}
#[test]
fn option_overrides_itself() {
let res = Command::new("posix")
.arg(
arg!(--opt <val> "some option")
.required(false)
.overrides_with("opt"),
)
.try_get_matches_from(vec!["", "--opt=some", "--opt=other"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("opt"));
assert_eq!(m.occurrences_of("opt"), 1);
assert_eq!(m.value_of("opt"), Some("other"));
}
#[test]
fn mult_option_require_delim_overrides_itself() {
let res = Command::new("posix")
.arg(
arg!(--opt <val> ... "some option")
.required(false)
.overrides_with("opt")
.number_of_values(1)
.takes_value(true)
.use_value_delimiter(true)
.require_value_delimiter(true),
)
.try_get_matches_from(vec!["", "--opt=some", "--opt=other", "--opt=one,two"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("opt"));
assert_eq!(m.occurrences_of("opt"), 3);
assert_eq!(
m.values_of("opt").unwrap().collect::<Vec<_>>(),
&["some", "other", "one", "two"]
);
}
#[test]
fn mult_option_overrides_itself() {
let res = Command::new("posix")
.arg(
arg!(--opt <val> ... "some option")
.required(false)
.multiple_values(true)
.overrides_with("opt"),
)
.try_get_matches_from(vec![
"",
"--opt",
"first",
"overrides",
"--opt",
"some",
"other",
"val",
]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("opt"));
assert_eq!(m.occurrences_of("opt"), 2);
assert_eq!(
m.values_of("opt").unwrap().collect::<Vec<_>>(),
&["first", "overrides", "some", "other", "val"]
);
}
#[test]
fn option_use_delim_false_override_itself() {
let m = Command::new("posix")
.arg(
arg!(--opt <val> "some option")
.required(false)
.overrides_with("opt"),
)
.try_get_matches_from(vec!["", "--opt=some,other", "--opt=one,two"])
.unwrap();
assert!(m.is_present("opt"));
assert_eq!(m.occurrences_of("opt"), 1);
assert_eq!(
m.values_of("opt").unwrap().collect::<Vec<_>>(),
&["one,two"]
);
}
#[test]
fn pos_mult_overrides_itself() {
// opts with multiple
let res = Command::new("posix")
.arg(arg!([val] ... "some pos").overrides_with("val"))
.try_get_matches_from(vec!["", "some", "other", "value"]);
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("val"));
assert_eq!(m.occurrences_of("val"), 3);
assert_eq!(
m.values_of("val").unwrap().collect::<Vec<_>>(),
&["some", "other", "value"]
);
}
#[test]
fn posix_compatible_flags_long() {
let m = Command::new("posix")
.arg(arg!(--flag "some flag").overrides_with("color"))
.arg(arg!(--color "some other flag"))
.try_get_matches_from(vec!["", "--flag", "--color"])
.unwrap();
assert!(m.is_present("color"));
assert!(!m.is_present("flag"));
}
#[test]
fn posix_compatible_flags_long_rev() {
let m = Command::new("posix")
.arg(arg!(--flag "some flag").overrides_with("color"))
.arg(arg!(--color "some other flag"))
.try_get_matches_from(vec!["", "--color", "--flag"])
.unwrap();
assert!(!m.is_present("color"));
assert!(m.is_present("flag"));
}
#[test]
fn posix_compatible_flags_short() {
let m = Command::new("posix")
.arg(arg!(-f --flag "some flag").overrides_with("color"))
.arg(arg!(-c --color "some other flag"))
.try_get_matches_from(vec!["", "-f", "-c"])
.unwrap();
assert!(m.is_present("color"));
assert!(!m.is_present("flag"));
}
#[test]
fn posix_compatible_flags_short_rev() {
let m = Command::new("posix")
.arg(arg!(-f --flag "some flag").overrides_with("color"))
.arg(arg!(-c --color "some other flag"))
.try_get_matches_from(vec!["", "-c", "-f"])
.unwrap();
assert!(!m.is_present("color"));
assert!(m.is_present("flag"));
}
#[test]
fn posix_compatible_opts_long() {
let m = Command::new("posix")
.arg(
arg!(--flag <flag> "some flag")
.required(false)
.overrides_with("color"),
)
.arg(arg!(--color <color> "some other flag").required(false))
.try_get_matches_from(vec!["", "--flag", "some", "--color", "other"])
.unwrap();
assert!(m.is_present("color"));
assert_eq!(m.value_of("color").unwrap(), "other");
assert!(!m.is_present("flag"));
}
#[test]
fn posix_compatible_opts_long_rev() {
let m = Command::new("posix")
.arg(
arg!(--flag <flag> "some flag")
.required(false)
.overrides_with("color"),
)
.arg(arg!(--color <color> "some other flag").required(false))
.try_get_matches_from(vec!["", "--color", "some", "--flag", "other"])
.unwrap();
assert!(!m.is_present("color"));
assert!(m.is_present("flag"));
assert_eq!(m.value_of("flag").unwrap(), "other");
}
#[test]
fn posix_compatible_opts_long_equals() {
let m = Command::new("posix")
.arg(
arg!(--flag <flag> "some flag")
.required(false)
.overrides_with("color"),
)
.arg(arg!(--color <color> "some other flag").required(false))
.try_get_matches_from(vec!["", "--flag=some", "--color=other"])
.unwrap();
assert!(m.is_present("color"));
assert_eq!(m.value_of("color").unwrap(), "other");
assert!(!m.is_present("flag"));
}
#[test]
fn posix_compatible_opts_long_equals_rev() {
let m = Command::new("posix")
.arg(
arg!(--flag <flag> "some flag")
.required(false)
.overrides_with("color"),
)
.arg(arg!(--color <color> "some other flag").required(false))
.try_get_matches_from(vec!["", "--color=some", "--flag=other"])
.unwrap();
assert!(!m.is_present("color"));
assert!(m.is_present("flag"));
assert_eq!(m.value_of("flag").unwrap(), "other");
}
#[test]
fn posix_compatible_opts_short() {
let m = Command::new("posix")
.arg(
arg!(f: -f <flag> "some flag")
.required(false)
.overrides_with("c"),
)
.arg(arg!(c: -c <color> "some other flag").required(false))
.try_get_matches_from(vec!["", "-f", "some", "-c", "other"])
.unwrap();
assert!(m.is_present("c"));
assert_eq!(m.value_of("c").unwrap(), "other");
assert!(!m.is_present("f"));
}
#[test]
fn posix_compatible_opts_short_rev() {
let m = Command::new("posix")
.arg(
arg!(f: -f <flag> "some flag")
.required(false)
.overrides_with("c"),
)
.arg(arg!(c: -c <color> "some other flag").required(false))
.try_get_matches_from(vec!["", "-c", "some", "-f", "other"])
.unwrap();
assert!(!m.is_present("c"));
assert!(m.is_present("f"));
assert_eq!(m.value_of("f").unwrap(), "other");
}
#[test]
fn conflict_overridden() {
let m = Command::new("conflict_overridden")
.arg(arg!(-f --flag "some flag").conflicts_with("debug"))
.arg(arg!(-d --debug "other flag"))
.arg(arg!(-c --color "third flag").overrides_with("flag"))
.try_get_matches_from(vec!["", "-f", "-c", "-d"])
.unwrap();
assert!(m.is_present("color"));
assert!(!m.is_present("flag"));
assert!(m.is_present("debug"));
}
#[test]
fn conflict_overridden_2() {
let result = Command::new("conflict_overridden")
.arg(arg!(-f --flag "some flag").conflicts_with("debug"))
.arg(arg!(-d --debug "other flag"))
.arg(arg!(-c --color "third flag").overrides_with("flag"))
.try_get_matches_from(vec!["", "-f", "-d", "-c"]);
assert!(result.is_ok(), "{}", result.unwrap_err());
let m = result.unwrap();
assert!(m.is_present("color"));
assert!(m.is_present("debug"));
assert!(!m.is_present("flag"));
}
#[test]
fn conflict_overridden_3() {
let result = Command::new("conflict_overridden")
.arg(arg!(-f --flag "some flag").conflicts_with("debug"))
.arg(arg!(-d --debug "other flag"))
.arg(arg!(-c --color "third flag").overrides_with("flag"))
.try_get_matches_from(vec!["", "-d", "-c", "-f"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
}
#[test]
fn conflict_overridden_4() {
let m = Command::new("conflict_overridden")
.arg(arg!(-f --flag "some flag").conflicts_with("debug"))
.arg(arg!(-d --debug "other flag"))
.arg(arg!(-c --color "third flag").overrides_with("flag"))
.try_get_matches_from(vec!["", "-d", "-f", "-c"])
.unwrap();
assert!(m.is_present("color"));
assert!(!m.is_present("flag"));
assert!(m.is_present("debug"));
}
#[test]
fn pos_required_overridden_by_flag() {
let result = Command::new("require_overridden")
.arg(Arg::new("pos").index(1).required(true))
.arg(arg!(-c --color "some flag").overrides_with("pos"))
.try_get_matches_from(vec!["", "test", "-c"]);
assert!(result.is_ok(), "{:?}", result.unwrap_err());
}
#[test]
fn require_overridden_2() {
let m = Command::new("require_overridden")
.arg(Arg::new("req_pos").required(true))
.arg(arg!(-c --color "other flag").overrides_with("req_pos"))
.try_get_matches_from(vec!["", "-c", "req_pos"])
.unwrap();
assert!(!m.is_present("color"));
assert!(m.is_present("req_pos"));
}
#[test]
fn require_overridden_3() {
let m = Command::new("require_overridden")
.arg(arg!(-f --flag "some flag").requires("debug"))
.arg(arg!(-d --debug "other flag"))
.arg(arg!(-c --color "third flag").overrides_with("flag"))
.try_get_matches_from(vec!["", "-f", "-c"])
.unwrap();
assert!(m.is_present("color"));
assert!(!m.is_present("flag"));
assert!(!m.is_present("debug"));
}
#[test]
fn require_overridden_4() {
let result = Command::new("require_overridden")
.arg(arg!(-f --flag "some flag").requires("debug"))
.arg(arg!(-d --debug "other flag"))
.arg(arg!(-c --color "third flag").overrides_with("flag"))
.try_get_matches_from(vec!["", "-c", "-f"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
}
#[test]
fn issue_1374_overrides_self_with_multiple_values() {
let cmd = Command::new("test").arg(
Arg::new("input")
.long("input")
.takes_value(true)
.overrides_with("input")
.min_values(0),
);
let m = cmd
.clone()
.try_get_matches_from(&["test", "--input", "a", "b", "c", "--input", "d"])
.unwrap();
assert_eq!(m.values_of("input").unwrap().collect::<Vec<_>>(), &["d"]);
let m = cmd
.clone()
.try_get_matches_from(&["test", "--input", "a", "b", "--input", "c", "d"])
.unwrap();
assert_eq!(
m.values_of("input").unwrap().collect::<Vec<_>>(),
&["c", "d"]
);
}
#[test]
fn incremental_override() {
let mut cmd = Command::new("test")
.arg(arg!(--name <NAME>).multiple_occurrences(true))
.arg(arg!(--"no-name").overrides_with("name"));
let m = cmd
.try_get_matches_from_mut(&["test", "--name=ahmed", "--no-name", "--name=ali"])
.unwrap();
assert_eq!(m.values_of("name").unwrap().collect::<Vec<_>>(), &["ali"]);
assert!(!m.is_present("no-name"));
}

View file

@ -1,393 +0,0 @@
use super::utils;
use clap::{error::ErrorKind, Arg, Command, PossibleValue};
#[cfg(feature = "suggestions")]
static PV_ERROR: &str = "error: \"slo\" isn't a valid value for '-O <option>'
\t[possible values: slow, fast, \"ludicrous speed\"]
\tDid you mean \"slow\"?
For more information try --help
";
#[cfg(not(feature = "suggestions"))]
static PV_ERROR: &str = "error: \"slo\" isn't a valid value for '-O <option>'
\t[possible values: slow, fast, \"ludicrous speed\"]
For more information try --help
";
#[cfg(feature = "suggestions")]
static PV_ERROR_ESCAPED: &str = "error: \"ludicrous\" isn't a valid value for '-O <option>'
\t[possible values: slow, fast, \"ludicrous speed\"]
\tDid you mean \"ludicrous speed\"?
For more information try --help
";
#[cfg(not(feature = "suggestions"))]
static PV_ERROR_ESCAPED: &str = "error: \"ludicrous\" isn't a valid value for '-O <option>'
\t[possible values: slow, fast, \"ludicrous speed\"]
For more information try --help
";
#[test]
fn possible_values_of_positional() {
let m = Command::new("possible_values")
.arg(Arg::new("positional").index(1).possible_value("test123"))
.try_get_matches_from(vec!["myprog", "test123"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("positional"));
assert_eq!(m.value_of("positional"), Some("test123"));
}
#[test]
fn possible_value_arg_value() {
let m = Command::new("possible_values")
.arg(
Arg::new("arg_value").index(1).possible_value(
PossibleValue::new("test123")
.hide(false)
.help("It's just a test"),
),
)
.try_get_matches_from(vec!["myprog", "test123"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("arg_value"));
assert_eq!(m.value_of("arg_value"), Some("test123"));
}
#[test]
fn possible_values_of_positional_fail() {
let m = Command::new("possible_values")
.arg(Arg::new("positional").index(1).possible_value("test123"))
.try_get_matches_from(vec!["myprog", "notest"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidValue);
}
#[test]
fn possible_values_of_positional_multiple() {
let m = Command::new("possible_values")
.arg(
Arg::new("positional")
.index(1)
.takes_value(true)
.possible_value("test123")
.possible_value("test321")
.multiple_values(true),
)
.try_get_matches_from(vec!["myprog", "test123", "test321"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("positional"));
assert_eq!(
m.values_of("positional").unwrap().collect::<Vec<_>>(),
vec!["test123", "test321"]
);
}
#[test]
fn possible_values_of_positional_multiple_fail() {
let m = Command::new("possible_values")
.arg(
Arg::new("positional")
.index(1)
.takes_value(true)
.possible_value("test123")
.possible_value("test321")
.multiple_values(true),
)
.try_get_matches_from(vec!["myprog", "test123", "notest"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidValue);
}
#[test]
fn possible_values_of_option() {
let m = Command::new("possible_values")
.arg(
Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value("test123"),
)
.try_get_matches_from(vec!["myprog", "--option", "test123"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("option"));
assert_eq!(m.value_of("option"), Some("test123"));
}
#[test]
fn possible_values_of_option_fail() {
let m = Command::new("possible_values")
.arg(
Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value("test123"),
)
.try_get_matches_from(vec!["myprog", "--option", "notest"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidValue);
}
#[test]
fn possible_values_of_option_multiple() {
let m = Command::new("possible_values")
.arg(
Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value("test123")
.possible_value("test321")
.multiple_occurrences(true),
)
.try_get_matches_from(vec!["", "--option", "test123", "--option", "test321"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
assert!(m.is_present("option"));
assert_eq!(
m.values_of("option").unwrap().collect::<Vec<_>>(),
vec!["test123", "test321"]
);
}
#[test]
fn possible_values_of_option_multiple_fail() {
let m = Command::new("possible_values")
.arg(
Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value("test123")
.possible_value("test321")
.multiple_occurrences(true),
)
.try_get_matches_from(vec!["", "--option", "test123", "--option", "notest"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidValue);
}
#[test]
fn possible_values_output() {
utils::assert_output(
Command::new("test").arg(Arg::new("option").short('O').possible_values([
"slow",
"fast",
"ludicrous speed",
])),
"clap-test -O slo",
PV_ERROR,
true,
);
}
#[test]
fn possible_values_alias_output() {
utils::assert_output(
Command::new("test").arg(
Arg::new("option")
.short('O')
.possible_value("slow")
.possible_value(PossibleValue::new("fast").alias("fost"))
.possible_value(PossibleValue::new("ludicrous speed").aliases(["ls", "lcs"])),
),
"clap-test -O slo",
PV_ERROR,
true,
);
}
#[test]
fn possible_values_hidden_output() {
utils::assert_output(
Command::new("test").arg(
Arg::new("option")
.short('O')
.possible_values(["slow", "fast"])
.possible_value(PossibleValue::new("ludicrous speed"))
.possible_value(PossibleValue::new("forbidden speed").hide(true)),
),
"clap-test -O slo",
PV_ERROR,
true,
);
}
#[test]
fn escaped_possible_values_output() {
utils::assert_output(
Command::new("test").arg(Arg::new("option").short('O').possible_values([
"slow",
"fast",
"ludicrous speed",
])),
"clap-test -O ludicrous",
PV_ERROR_ESCAPED,
true,
);
}
#[test]
fn missing_possible_value_error() {
utils::assert_output(
Command::new("test").arg(
Arg::new("option")
.short('O')
.possible_value("slow")
.possible_value(PossibleValue::new("fast").alias("fost"))
.possible_value(PossibleValue::new("ludicrous speed"))
.possible_value(PossibleValue::new("forbidden speed").hide(true)),
),
"clap-test -O",
MISSING_PV_ERROR,
true,
);
}
static MISSING_PV_ERROR: &str =
"error: The argument '-O <option>' requires a value but none was supplied
\t[possible values: slow, fast, \"ludicrous speed\"]
For more information try --help
";
#[test]
fn alias() {
let m = Command::new("pv")
.arg(
Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value(PossibleValue::new("test123").alias("123"))
.possible_value("test321")
.ignore_case(true),
)
.try_get_matches_from(vec!["pv", "--option", "123"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert!(m.unwrap().value_of("option").unwrap().eq("123"));
}
#[test]
fn aliases() {
let m = Command::new("pv")
.arg(
Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value(PossibleValue::new("test123").aliases(["1", "2", "3"]))
.possible_value("test321")
.ignore_case(true),
)
.try_get_matches_from(vec!["pv", "--option", "2"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert!(m.unwrap().value_of("option").unwrap().eq("2"));
}
#[test]
fn ignore_case() {
let m = Command::new("pv")
.arg(
Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value("test123")
.possible_value("test321")
.ignore_case(true),
)
.try_get_matches_from(vec!["pv", "--option", "TeSt123"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert!(m
.unwrap()
.value_of("option")
.unwrap()
.eq_ignore_ascii_case("test123"));
}
#[test]
fn ignore_case_fail() {
let m = Command::new("pv")
.arg(
Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value("test123")
.possible_value("test321"),
)
.try_get_matches_from(vec!["pv", "--option", "TeSt123"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidValue);
}
#[test]
fn ignore_case_multiple() {
let m = Command::new("pv")
.arg(
Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value("test123")
.possible_value("test321")
.multiple_values(true)
.ignore_case(true),
)
.try_get_matches_from(vec!["pv", "--option", "TeSt123", "teST123", "tESt321"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert_eq!(
m.unwrap().values_of("option").unwrap().collect::<Vec<_>>(),
&["TeSt123", "teST123", "tESt321"]
);
}
#[test]
fn ignore_case_multiple_fail() {
let m = Command::new("pv")
.arg(
Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value("test123")
.possible_value("test321")
.multiple_values(true),
)
.try_get_matches_from(vec!["pv", "--option", "test123", "teST123", "test321"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidValue);
}

View file

@ -1,144 +0,0 @@
use clap::{Arg, ArgMatches, Command};
fn get_app() -> Command<'static> {
Command::new("myprog")
.arg(
Arg::new("GLOBAL_ARG")
.long("global-arg")
.help("Specifies something needed by the subcommands")
.global(true)
.takes_value(true)
.default_value("default_value"),
)
.arg(
Arg::new("GLOBAL_FLAG")
.long("global-flag")
.help("Specifies something needed by the subcommands")
.global(true)
.multiple_occurrences(true),
)
.subcommand(Command::new("outer").subcommand(Command::new("inner")))
}
fn get_matches(cmd: Command<'static>, argv: &'static str) -> ArgMatches {
cmd.try_get_matches_from(argv.split(' ').collect::<Vec<_>>())
.unwrap()
}
fn get_outer_matches(m: &ArgMatches) -> &ArgMatches {
m.subcommand_matches("outer")
.expect("could not access outer subcommand")
}
fn get_inner_matches(m: &ArgMatches) -> &ArgMatches {
get_outer_matches(m)
.subcommand_matches("inner")
.expect("could not access inner subcommand")
}
fn top_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches, val: T) -> bool {
m.value_of("GLOBAL_ARG") == val.into()
}
fn inner_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches, val: T) -> bool {
get_inner_matches(m).value_of("GLOBAL_ARG") == val.into()
}
fn outer_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches, val: T) -> bool {
get_outer_matches(m).value_of("GLOBAL_ARG") == val.into()
}
fn top_can_access_flag(m: &ArgMatches, present: bool, occurrences: u64) -> bool {
(m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
}
fn inner_can_access_flag(m: &ArgMatches, present: bool, occurrences: u64) -> bool {
let m = get_inner_matches(m);
(m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
}
fn outer_can_access_flag(m: &ArgMatches, present: bool, occurrences: u64) -> bool {
let m = get_outer_matches(m);
(m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
}
#[test]
fn global_arg_used_top_level() {
let m = get_matches(get_app(), "myprog --global-arg=some_value outer inner");
assert!(top_can_access_arg(&m, "some_value"));
assert!(inner_can_access_arg(&m, "some_value"));
assert!(outer_can_access_arg(&m, "some_value"));
}
#[test]
fn global_arg_used_outer() {
let m = get_matches(get_app(), "myprog outer --global-arg=some_value inner");
assert!(top_can_access_arg(&m, "some_value"));
assert!(inner_can_access_arg(&m, "some_value"));
assert!(outer_can_access_arg(&m, "some_value"));
}
#[test]
fn global_arg_used_inner() {
let m = get_matches(get_app(), "myprog outer inner --global-arg=some_value");
assert!(top_can_access_arg(&m, "some_value"));
assert!(inner_can_access_arg(&m, "some_value"));
assert!(outer_can_access_arg(&m, "some_value"));
}
#[test]
fn global_arg_default_value() {
let m = get_matches(get_app(), "myprog outer inner");
assert!(top_can_access_arg(&m, "default_value"));
assert!(inner_can_access_arg(&m, "default_value"));
assert!(outer_can_access_arg(&m, "default_value"));
}
#[test]
fn global_flag_used_top_level() {
let m = get_matches(get_app(), "myprog --global-flag outer inner");
assert!(top_can_access_flag(&m, true, 1));
assert!(inner_can_access_flag(&m, true, 1));
assert!(outer_can_access_flag(&m, true, 1));
}
#[test]
fn global_flag_used_outer() {
let m = get_matches(get_app(), "myprog outer --global-flag inner");
assert!(top_can_access_flag(&m, true, 1));
assert!(inner_can_access_flag(&m, true, 1));
assert!(outer_can_access_flag(&m, true, 1));
}
#[test]
fn global_flag_used_inner() {
let m = get_matches(get_app(), "myprog outer inner --global-flag");
assert!(top_can_access_flag(&m, true, 1));
assert!(inner_can_access_flag(&m, true, 1));
assert!(outer_can_access_flag(&m, true, 1));
}
#[test]
fn global_flag_2x_used_top_level() {
let m = get_matches(get_app(), "myprog --global-flag --global-flag outer inner");
assert!(top_can_access_flag(&m, true, 2));
assert!(inner_can_access_flag(&m, true, 2));
assert!(outer_can_access_flag(&m, true, 2));
}
#[test]
fn global_flag_2x_used_inner() {
let m = get_matches(get_app(), "myprog outer inner --global-flag --global-flag");
assert!(top_can_access_flag(&m, true, 2));
assert!(inner_can_access_flag(&m, true, 2));
assert!(outer_can_access_flag(&m, true, 2));
}

View file

@ -1,36 +0,0 @@
#![cfg(feature = "regex")]
use clap::{error::ErrorKind, Arg, Command};
use regex::{Regex, RegexSet};
#[test]
fn validator_regex() {
let priority = Regex::new(r"[A-C]").unwrap();
let m = Command::new("prog")
.arg(
Arg::new("priority")
.index(1)
.validator_regex(priority, "A, B or C are allowed"),
)
.try_get_matches_from(vec!["prog", "12345"]);
assert!(m.is_err());
assert_eq!(m.err().unwrap().kind(), ErrorKind::ValueValidation)
}
#[test]
fn validator_regex_with_regex_set() {
let priority = RegexSet::new(&[r"[A-C]", r"[X-Z]"]).unwrap();
let m = Command::new("prog")
.arg(
Arg::new("priority")
.index(1)
.validator_regex(priority, "A, B, C, X, Y or Z are allowed"),
)
.try_get_matches_from(vec!["prog", "12345"]);
assert!(m.is_err());
assert_eq!(m.err().unwrap().kind(), ErrorKind::ValueValidation)
}

File diff suppressed because it is too large Load diff

View file

@ -1,696 +0,0 @@
use super::utils;
use clap::{arg, error::ErrorKind, Arg, Command};
static VISIBLE_ALIAS_HELP: &str = "clap-test 2.6
USAGE:
clap-test [SUBCOMMAND]
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test Some help [aliases: dongle, done]
";
static INVISIBLE_ALIAS_HELP: &str = "clap-test 2.6
USAGE:
clap-test [SUBCOMMAND]
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test Some help
";
static SUBCMD_ALPHA_ORDER: &str = "test 1
USAGE:
test [SUBCOMMAND]
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
a1 blah a1
b1 blah b1
help Print this message or the help of the given subcommand(s)
";
static SUBCMD_DECL_ORDER: &str = "test 1
USAGE:
test [SUBCOMMAND]
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
b1 blah b1
a1 blah a1
help Print this message or the help of the given subcommand(s)
";
#[cfg(feature = "suggestions")]
static DYM_SUBCMD: &str = "error: The subcommand 'subcm' wasn't recognized
Did you mean 'subcmd'?
If you believe you received this message in error, try re-running with 'dym -- subcm'
USAGE:
dym [SUBCOMMAND]
For more information try --help
";
#[cfg(feature = "suggestions")]
static DYM_SUBCMD_AMBIGUOUS: &str = "error: The subcommand 'te' wasn't recognized
Did you mean 'test' or 'temp'?
If you believe you received this message in error, try re-running with 'dym -- te'
USAGE:
dym [SUBCOMMAND]
For more information try --help
";
static SUBCMD_AFTER_DOUBLE_DASH: &str =
"error: Found argument 'subcmd' which wasn't expected, or isn't valid in this context
\tIf you tried to supply `subcmd` as a subcommand, remove the '--' before it.
USAGE:
cmd [SUBCOMMAND]
For more information try --help
";
#[test]
fn subcommand() {
let m = Command::new("test")
.subcommand(
Command::new("some").arg(
Arg::new("test")
.short('t')
.long("test")
.takes_value(true)
.help("testing testing"),
),
)
.arg(Arg::new("other").long("other"))
.try_get_matches_from(vec!["myprog", "some", "--test", "testing"])
.unwrap();
assert_eq!(m.subcommand_name().unwrap(), "some");
let sub_m = m.subcommand_matches("some").unwrap();
assert!(sub_m.is_present("test"));
assert_eq!(sub_m.value_of("test").unwrap(), "testing");
}
#[test]
fn subcommand_none_given() {
let m = Command::new("test")
.subcommand(
Command::new("some").arg(
Arg::new("test")
.short('t')
.long("test")
.takes_value(true)
.help("testing testing"),
),
)
.arg(Arg::new("other").long("other"))
.try_get_matches_from(vec![""])
.unwrap();
assert!(m.subcommand_name().is_none());
}
#[test]
fn subcommand_multiple() {
let m = Command::new("test")
.subcommands(vec![
Command::new("some").arg(
Arg::new("test")
.short('t')
.long("test")
.takes_value(true)
.help("testing testing"),
),
Command::new("add").arg(Arg::new("roster").short('r')),
])
.arg(Arg::new("other").long("other"))
.try_get_matches_from(vec!["myprog", "some", "--test", "testing"])
.unwrap();
assert!(m.subcommand_matches("some").is_some());
assert!(m.subcommand_matches("add").is_none());
assert_eq!(m.subcommand_name().unwrap(), "some");
let sub_m = m.subcommand_matches("some").unwrap();
assert!(sub_m.is_present("test"));
assert_eq!(sub_m.value_of("test").unwrap(), "testing");
}
#[test]
fn subcommand_display_order() {
let app_subcmd_alpha_order = Command::new("test").version("1").subcommands(vec![
Command::new("b1")
.about("blah b1")
.arg(Arg::new("test").short('t')),
Command::new("a1")
.about("blah a1")
.arg(Arg::new("roster").short('r')),
]);
utils::assert_output(
app_subcmd_alpha_order,
"test --help",
SUBCMD_ALPHA_ORDER,
false,
);
let app_subcmd_decl_order = Command::new("test")
.version("1")
.setting(clap::AppSettings::DeriveDisplayOrder)
.subcommands(vec![
Command::new("b1")
.about("blah b1")
.arg(Arg::new("test").short('t')),
Command::new("a1")
.about("blah a1")
.arg(Arg::new("roster").short('r')),
]);
utils::assert_output(
app_subcmd_decl_order,
"test --help",
SUBCMD_DECL_ORDER,
false,
);
}
#[test]
fn single_alias() {
let m = Command::new("myprog")
.subcommand(Command::new("test").alias("do-stuff"))
.try_get_matches_from(vec!["myprog", "do-stuff"])
.unwrap();
assert_eq!(m.subcommand_name(), Some("test"));
}
#[test]
fn multiple_aliases() {
let m = Command::new("myprog")
.subcommand(Command::new("test").aliases(&["do-stuff", "test-stuff"]))
.try_get_matches_from(vec!["myprog", "test-stuff"])
.unwrap();
assert_eq!(m.subcommand_name(), Some("test"));
}
#[test]
#[cfg(feature = "suggestions")]
fn subcmd_did_you_mean_output() {
let cmd = Command::new("dym").subcommand(Command::new("subcmd"));
utils::assert_output(cmd, "dym subcm", DYM_SUBCMD, true);
}
#[test]
#[cfg(feature = "suggestions")]
fn subcmd_did_you_mean_output_ambiguous() {
let cmd = Command::new("dym")
.subcommand(Command::new("test"))
.subcommand(Command::new("temp"));
utils::assert_output(cmd, "dym te", DYM_SUBCMD_AMBIGUOUS, true);
}
#[test]
#[cfg(feature = "suggestions")]
fn subcmd_did_you_mean_output_arg() {
static EXPECTED: &str =
"error: Found argument '--subcmarg' which wasn't expected, or isn't valid in this context
\tDid you mean to put '--subcmdarg' after the subcommand 'subcmd'?
\tIf you tried to supply `--subcmarg` as a value rather than a flag, use `-- --subcmarg`
USAGE:
dym [SUBCOMMAND]
For more information try --help
";
let cmd = Command::new("dym").subcommand(
Command::new("subcmd").arg(arg!(-s --subcmdarg <subcmdarg> "tests").required(false)),
);
utils::assert_output(cmd, "dym --subcmarg subcmd", EXPECTED, true);
}
#[test]
#[cfg(feature = "suggestions")]
fn subcmd_did_you_mean_output_arg_false_positives() {
static EXPECTED: &str =
"error: Found argument '--subcmarg' which wasn't expected, or isn't valid in this context
\tIf you tried to supply `--subcmarg` as a value rather than a flag, use `-- --subcmarg`
USAGE:
dym [SUBCOMMAND]
For more information try --help
";
let cmd = Command::new("dym").subcommand(
Command::new("subcmd").arg(arg!(-s --subcmdarg <subcmdarg> "tests").required(false)),
);
utils::assert_output(cmd, "dym --subcmarg foo", EXPECTED, true);
}
#[test]
fn alias_help() {
let m = Command::new("myprog")
.subcommand(Command::new("test").alias("do-stuff"))
.try_get_matches_from(vec!["myprog", "help", "do-stuff"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::DisplayHelp);
}
#[test]
fn visible_aliases_help_output() {
let cmd = Command::new("clap-test").version("2.6").subcommand(
Command::new("test")
.about("Some help")
.alias("invisible")
.visible_alias("dongle")
.visible_alias("done"),
);
utils::assert_output(cmd, "clap-test --help", VISIBLE_ALIAS_HELP, false);
}
#[test]
fn invisible_aliases_help_output() {
let cmd = Command::new("clap-test")
.version("2.6")
.subcommand(Command::new("test").about("Some help").alias("invisible"));
utils::assert_output(cmd, "clap-test --help", INVISIBLE_ALIAS_HELP, false);
}
#[test]
#[cfg(feature = "unstable-replace")]
fn replace() {
let m = Command::new("prog")
.subcommand(
Command::new("module").subcommand(Command::new("install").about("Install module")),
)
.replace("install", &["module", "install"])
.try_get_matches_from(vec!["prog", "install"])
.unwrap();
assert_eq!(m.subcommand_name(), Some("module"));
assert_eq!(
m.subcommand_matches("module").unwrap().subcommand_name(),
Some("install")
);
}
#[test]
fn issue_1031_args_with_same_name() {
let res = Command::new("prog")
.arg(arg!(--"ui-path" <PATH>))
.subcommand(Command::new("signer"))
.try_get_matches_from(vec!["prog", "--ui-path", "signer"]);
assert!(res.is_ok(), "{:?}", res.unwrap_err().kind());
let m = res.unwrap();
assert_eq!(m.value_of("ui-path"), Some("signer"));
}
#[test]
fn issue_1031_args_with_same_name_no_more_vals() {
let res = Command::new("prog")
.arg(arg!(--"ui-path" <PATH>))
.subcommand(Command::new("signer"))
.try_get_matches_from(vec!["prog", "--ui-path", "value", "signer"]);
assert!(res.is_ok(), "{:?}", res.unwrap_err().kind());
let m = res.unwrap();
assert_eq!(m.value_of("ui-path"), Some("value"));
assert_eq!(m.subcommand_name(), Some("signer"));
}
#[test]
fn issue_1161_multiple_hyphen_hyphen() {
// from example 22
let res = Command::new("myprog")
.arg(Arg::new("eff").short('f'))
.arg(Arg::new("pea").short('p').takes_value(true))
.arg(
Arg::new("slop")
.takes_value(true)
.multiple_values(true)
.last(true),
)
.try_get_matches_from(vec![
"-f",
"-p=bob",
"--",
"sloppy",
"slop",
"-a",
"--",
"subprogram",
"position",
"args",
]);
assert!(res.is_ok(), "{:?}", res.unwrap_err().kind());
let m = res.unwrap();
let expected = Some(vec![
"sloppy",
"slop",
"-a",
"--",
"subprogram",
"position",
"args",
]);
let actual = m.values_of("slop").map(|vals| vals.collect::<Vec<_>>());
assert_eq!(expected, actual);
}
#[test]
fn issue_1722_not_emit_error_when_arg_follows_similar_to_a_subcommand() {
let m = Command::new("myprog")
.subcommand(Command::new("subcommand"))
.arg(Arg::new("argument"))
.try_get_matches_from(vec!["myprog", "--", "subcommand"]);
assert_eq!(m.unwrap().value_of("argument"), Some("subcommand"));
}
#[test]
fn subcommand_placeholder_test() {
let mut cmd = Command::new("myprog")
.subcommand(Command::new("subcommand"))
.subcommand_value_name("TEST_PLACEHOLDER")
.subcommand_help_heading("TEST_HEADER");
assert_eq!(&cmd.render_usage(), "USAGE:\n myprog [TEST_PLACEHOLDER]");
let mut help_text = Vec::new();
cmd.write_help(&mut help_text)
.expect("Failed to write to internal buffer");
assert!(String::from_utf8(help_text)
.unwrap()
.contains("TEST_HEADER:"));
}
#[test]
fn subcommand_used_after_double_dash() {
let cmd = Command::new("cmd").subcommand(Command::new("subcmd"));
utils::assert_output(cmd, "cmd -- subcmd", SUBCMD_AFTER_DOUBLE_DASH, true);
}
#[test]
fn subcommand_after_argument() {
let m = Command::new("myprog")
.arg(Arg::new("some_text"))
.subcommand(Command::new("test"))
.try_get_matches_from(vec!["myprog", "teat", "test"])
.unwrap();
assert_eq!(m.value_of("some_text"), Some("teat"));
assert_eq!(m.subcommand().unwrap().0, "test");
}
#[test]
fn subcommand_after_argument_looks_like_help() {
let m = Command::new("myprog")
.arg(Arg::new("some_text"))
.subcommand(Command::new("test"))
.try_get_matches_from(vec!["myprog", "helt", "test"])
.unwrap();
assert_eq!(m.value_of("some_text"), Some("helt"));
assert_eq!(m.subcommand().unwrap().0, "test");
}
#[test]
fn issue_2494_subcommand_is_present() {
let cmd = Command::new("opt")
.arg(Arg::new("global").long("global"))
.subcommand(Command::new("global"));
let m = cmd
.clone()
.try_get_matches_from(&["opt", "--global", "global"])
.unwrap();
assert_eq!(m.subcommand_name().unwrap(), "global");
assert!(m.is_present("global"));
let m = cmd
.clone()
.try_get_matches_from(&["opt", "--global"])
.unwrap();
assert!(m.subcommand_name().is_none());
assert!(m.is_present("global"));
let m = cmd.try_get_matches_from(&["opt", "global"]).unwrap();
assert_eq!(m.subcommand_name().unwrap(), "global");
assert!(!m.is_present("global"));
}
#[test]
fn subcommand_not_recognized() {
let cmd = Command::new("fake")
.subcommand(Command::new("sub"))
.disable_help_subcommand(true)
.infer_subcommands(true);
utils::assert_output(
cmd,
"fake help",
"error: The subcommand 'help' wasn't recognized
USAGE:
fake [SUBCOMMAND]
For more information try --help
",
true,
);
}
#[cfg(feature = "unstable-multicall")]
#[test]
fn busybox_like_multicall() {
fn applet_commands() -> [Command<'static>; 2] {
[Command::new("true"), Command::new("false")]
}
let cmd = Command::new("busybox")
.multicall(true)
.subcommand(Command::new("busybox").subcommands(applet_commands()))
.subcommands(applet_commands());
let m = cmd
.clone()
.try_get_matches_from(&["busybox", "true"])
.unwrap();
assert_eq!(m.subcommand_name(), Some("busybox"));
assert_eq!(m.subcommand().unwrap().1.subcommand_name(), Some("true"));
let m = cmd.clone().try_get_matches_from(&["true"]).unwrap();
assert_eq!(m.subcommand_name(), Some("true"));
let m = cmd.clone().try_get_matches_from(&["a.out"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnrecognizedSubcommand);
}
#[cfg(feature = "unstable-multicall")]
#[test]
fn hostname_like_multicall() {
let mut cmd = Command::new("hostname")
.multicall(true)
.subcommand(Command::new("hostname"))
.subcommand(Command::new("dnsdomainname"));
let m = cmd.clone().try_get_matches_from(&["hostname"]).unwrap();
assert_eq!(m.subcommand_name(), Some("hostname"));
let m = cmd
.clone()
.try_get_matches_from(&["dnsdomainname"])
.unwrap();
assert_eq!(m.subcommand_name(), Some("dnsdomainname"));
let m = cmd.clone().try_get_matches_from(&["a.out"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnrecognizedSubcommand);
let m = cmd.try_get_matches_from_mut(&["hostname", "hostname"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
let m = cmd.try_get_matches_from(&["hostname", "dnsdomainname"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
}
#[cfg(feature = "unstable-multicall")]
#[test]
fn bad_multicall_command_error() {
let cmd = Command::new("repl")
.version("1.0.0")
.propagate_version(true)
.multicall(true)
.subcommand(Command::new("foo"))
.subcommand(Command::new("bar"));
let err = cmd.clone().try_get_matches_from(&["world"]).unwrap_err();
assert_eq!(err.kind(), ErrorKind::UnrecognizedSubcommand);
static HELLO_EXPECTED: &str = "\
error: The subcommand 'world' wasn't recognized
USAGE:
<SUBCOMMAND>
For more information try help
";
utils::assert_eq(HELLO_EXPECTED, err.to_string());
let err = cmd.clone().try_get_matches_from(&["baz"]).unwrap_err();
assert_eq!(err.kind(), ErrorKind::InvalidSubcommand);
static BAZ_EXPECTED: &str = "\
error: The subcommand 'baz' wasn't recognized
\tDid you mean 'bar'?
If you believe you received this message in error, try re-running with ' -- baz'
USAGE:
<SUBCOMMAND>
For more information try help
";
utils::assert_eq(BAZ_EXPECTED, err.to_string());
// Verify whatever we did to get the above to work didn't disable `--help` and `--version`.
let err = cmd
.clone()
.try_get_matches_from(&["foo", "--help"])
.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayHelp);
let err = cmd
.clone()
.try_get_matches_from(&["foo", "--version"])
.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
}
#[cfg(feature = "unstable-multicall")]
#[test]
#[should_panic = "Command repl: Arguments like oh-no cannot be set on a multicall command"]
fn cant_have_args_with_multicall() {
let mut cmd = Command::new("repl")
.version("1.0.0")
.propagate_version(true)
.multicall(true)
.subcommand(Command::new("foo"))
.subcommand(Command::new("bar"))
.arg(Arg::new("oh-no"));
cmd.build();
}
#[cfg(feature = "unstable-multicall")]
#[test]
fn multicall_help_flag() {
static EXPECTED: &str = "\
foo-bar 1.0.0
USAGE:
foo bar [value]
ARGS:
<value>
OPTIONS:
-h, --help Print help information
-V, --version Print version information
";
let cmd = Command::new("repl")
.version("1.0.0")
.propagate_version(true)
.multicall(true)
.subcommand(Command::new("foo").subcommand(Command::new("bar").arg(Arg::new("value"))));
utils::assert_output(cmd, "foo bar --help", EXPECTED, false);
}
#[cfg(feature = "unstable-multicall")]
#[test]
fn multicall_help_subcommand() {
static EXPECTED: &str = "\
foo-bar 1.0.0
USAGE:
foo bar [value]
ARGS:
<value>
OPTIONS:
-h, --help Print help information
-V, --version Print version information
";
let cmd = Command::new("repl")
.version("1.0.0")
.propagate_version(true)
.multicall(true)
.subcommand(Command::new("foo").subcommand(Command::new("bar").arg(Arg::new("value"))));
utils::assert_output(cmd, "help foo bar", EXPECTED, false);
}
#[cfg(feature = "unstable-multicall")]
#[test]
fn multicall_render_help() {
static EXPECTED: &str = "\
foo-bar 1.0.0
USAGE:
foo bar [value]
ARGS:
<value>
OPTIONS:
-h, --help Print help information
-V, --version Print version information
";
let mut cmd = Command::new("repl")
.version("1.0.0")
.propagate_version(true)
.multicall(true)
.subcommand(Command::new("foo").subcommand(Command::new("bar").arg(Arg::new("value"))));
cmd.build();
let subcmd = cmd.find_subcommand_mut("foo").unwrap();
let subcmd = subcmd.find_subcommand_mut("bar").unwrap();
let mut buf = Vec::new();
subcmd.write_help(&mut buf).unwrap();
utils::assert_eq(EXPECTED, String::from_utf8(buf).unwrap());
}

View file

@ -1,149 +0,0 @@
use super::utils;
use clap::{arg, Command};
static EXAMPLE1_TMPL_S: &str = "{bin} {version}
{author}
{about}
USAGE:
{usage}
{all-args}";
static EXAMPLE1_TMPS_F: &str = "{bin} {version}
{author}
{about}
USAGE:
{usage}
OPTIONS:
{options}
ARGS:
{positionals}
SUBCOMMANDS:
{subcommands}";
static CUSTOM_TEMPL_HELP: &str = "MyApp 1.0
Kevin K. <kbknapp@gmail.com>
Does awesome things
USAGE:
MyApp [OPTIONS] <output> [SUBCOMMAND]
OPTIONS:
-c, --config <FILE> Sets a custom config file
-d Turn debugging information on
-h, --help Print help information
-V, --version Print version information
ARGS:
<output> Sets an optional output file
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test does testing things
";
static SIMPLE_TEMPLATE: &str = "MyApp 1.0
Kevin K. <kbknapp@gmail.com>
Does awesome things
USAGE:
MyApp [OPTIONS] <output> [SUBCOMMAND]
ARGS:
<output> Sets an optional output file
OPTIONS:
-c, --config <FILE> Sets a custom config file
-d Turn debugging information on
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test does testing things
";
#[test]
fn with_template() {
let cmd = get_app().help_template(EXAMPLE1_TMPL_S);
utils::assert_output(cmd, "MyApp --help", SIMPLE_TEMPLATE, false);
}
#[test]
fn custom_template() {
let cmd = get_app().help_template(EXAMPLE1_TMPS_F);
utils::assert_output(cmd, "MyApp --help", CUSTOM_TEMPL_HELP, false);
}
#[test]
fn template_empty() {
let cmd = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.help_template("");
utils::assert_output(cmd, "MyApp --help", "\n", false);
}
#[test]
fn template_notag() {
let cmd = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.help_template("test no tag test");
utils::assert_output(cmd, "MyApp --help", "test no tag test\n", false);
}
#[test]
fn template_unknowntag() {
let cmd = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.help_template("test {unknown_tag} test");
utils::assert_output(cmd, "MyApp --help", "test {unknown_tag} test\n", false);
}
#[test]
fn template_author_version() {
let cmd = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.help_template("{author}\n{version}\n{about}\n{bin}");
utils::assert_output(
cmd,
"MyApp --help",
"Kevin K. <kbknapp@gmail.com>\n1.0\nDoes awesome things\nMyApp\n",
false,
);
}
// ----------
fn get_app() -> Command<'static> {
Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(
arg!(
-c --config <FILE> "Sets a custom config file"
)
.required(false),
)
.arg(arg!(
<output> "Sets an optional output file"
))
.arg(arg!(
d: -d ... "Turn debugging information on"
))
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "lists test values")),
)
}

View file

@ -1,426 +0,0 @@
use super::utils;
use std::io::Write;
use std::str;
use clap::{Arg, Command};
static SCF2OP: &str = "flag present 2 times
option NOT present
positional NOT present
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option NOT present
positional NOT present
subcmd present
flag present 2 times
scoption present with value: some
An scoption: some
scpositional present with value: value
";
static SCFOP: &str = "flag present 1 times
option NOT present
positional NOT present
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option NOT present
positional NOT present
subcmd present
flag present 1 times
scoption present with value: some
An scoption: some
scpositional present with value: value
";
static O2P: &str = "flag NOT present
option present 2 times with value: some
An option: some
An option: other
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 2 times with value: some
An option: some
An option: other
positional present with value: value
subcmd NOT present
";
static F2OP: &str = "flag present 2 times
option present 1 times with value: some
An option: some
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 1 times with value: some
An option: some
positional present with value: value
subcmd NOT present
";
static FOP: &str = "flag present 1 times
option present 1 times with value: some
An option: some
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 1 times with value: some
An option: some
positional present with value: value
subcmd NOT present
";
pub fn check_complex_output(args: &str, out: &str) {
let mut w = vec![];
let matches = utils::complex_app()
.try_get_matches_from(args.split(' ').collect::<Vec<_>>())
.unwrap();
if matches.is_present("flag") {
writeln!(w, "flag present {} times", matches.occurrences_of("flag")).unwrap();
} else {
writeln!(w, "flag NOT present").unwrap();
}
if matches.is_present("option") {
if let Some(v) = matches.value_of("option") {
writeln!(
w,
"option present {} times with value: {}",
matches.occurrences_of("option"),
v
)
.unwrap();
}
if let Some(ov) = matches.values_of("option") {
for o in ov {
writeln!(w, "An option: {}", o).unwrap();
}
}
} else {
writeln!(w, "option NOT present").unwrap();
}
if let Some(p) = matches.value_of("positional") {
writeln!(w, "positional present with value: {}", p).unwrap();
} else {
writeln!(w, "positional NOT present").unwrap();
}
if matches.is_present("flag2") {
writeln!(w, "flag2 present").unwrap();
writeln!(
w,
"option2 present with value of: {}",
matches.value_of("long-option-2").unwrap()
)
.unwrap();
writeln!(
w,
"positional2 present with value of: {}",
matches.value_of("positional2").unwrap()
)
.unwrap();
} else {
writeln!(w, "flag2 NOT present").unwrap();
writeln!(
w,
"option2 maybe present with value of: {}",
matches.value_of("long-option-2").unwrap_or("Nothing")
)
.unwrap();
writeln!(
w,
"positional2 maybe present with value of: {}",
matches.value_of("positional2").unwrap_or("Nothing")
)
.unwrap();
}
let _ = match matches.value_of("option3").unwrap_or("") {
"fast" => writeln!(w, "option3 present quickly"),
"slow" => writeln!(w, "option3 present slowly"),
_ => writeln!(w, "option3 NOT present"),
};
let _ = match matches.value_of("positional3").unwrap_or("") {
"vi" => writeln!(w, "positional3 present in vi mode"),
"emacs" => writeln!(w, "positional3 present in emacs mode"),
_ => writeln!(w, "positional3 NOT present"),
};
if matches.is_present("option") {
if let Some(v) = matches.value_of("option") {
writeln!(
w,
"option present {} times with value: {}",
matches.occurrences_of("option"),
v
)
.unwrap();
}
if let Some(ov) = matches.values_of("option") {
for o in ov {
writeln!(w, "An option: {}", o).unwrap();
}
}
} else {
writeln!(w, "option NOT present").unwrap();
}
if let Some(p) = matches.value_of("positional") {
writeln!(w, "positional present with value: {}", p).unwrap();
} else {
writeln!(w, "positional NOT present").unwrap();
}
if let Some("subcmd") = matches.subcommand_name() {
writeln!(w, "subcmd present").unwrap();
if let Some(matches) = matches.subcommand_matches("subcmd") {
if matches.is_present("flag") {
writeln!(w, "flag present {} times", matches.occurrences_of("flag")).unwrap();
} else {
writeln!(w, "flag NOT present").unwrap();
}
if matches.is_present("option") {
if let Some(v) = matches.value_of("option") {
writeln!(w, "scoption present with value: {}", v).unwrap();
}
if let Some(ov) = matches.values_of("option") {
for o in ov {
writeln!(w, "An scoption: {}", o).unwrap();
}
}
} else {
writeln!(w, "scoption NOT present").unwrap();
}
if let Some(p) = matches.value_of("scpositional") {
writeln!(w, "scpositional present with value: {}", p).unwrap();
}
}
} else {
writeln!(w, "subcmd NOT present").unwrap();
}
let res = str::from_utf8(&w).unwrap();
assert_eq!(res, out);
}
#[test]
fn create_app() {
let _ = Command::new("test")
.version("1.0")
.author("kevin")
.about("does awesome things")
.try_get_matches_from(vec![""])
.unwrap();
}
#[test]
fn add_multiple_arg() {
let _ = Command::new("test")
.args(&[Arg::new("test").short('s'), Arg::new("test2").short('l')])
.try_get_matches_from(vec![""])
.unwrap();
}
#[test]
fn flag_x2_opt() {
check_complex_output(
"clap-test value -f -f -o some",
"flag present 2 times
option present 1 times with value: some
An option: some
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 1 times with value: some
An option: some
positional present with value: value
subcmd NOT present
",
);
}
#[test]
fn long_opt_x2_pos() {
check_complex_output("clap-test value --option some --option other", O2P);
}
#[test]
fn long_opt_eq_x2_pos() {
check_complex_output("clap-test value --option=some --option=other", O2P);
}
#[test]
fn short_opt_x2_pos() {
check_complex_output("clap-test value -o some -o other", O2P);
}
#[test]
fn short_opt_eq_x2_pos() {
check_complex_output("clap-test value -o=some -o=other", O2P);
}
#[test]
fn short_flag_x2_comb_short_opt_pos() {
check_complex_output("clap-test value -ff -o some", F2OP);
}
#[test]
fn short_flag_short_opt_pos() {
check_complex_output("clap-test value -f -o some", FOP);
}
#[test]
fn long_flag_long_opt_pos() {
check_complex_output("clap-test value --flag --option some", FOP);
}
#[test]
fn long_flag_long_opt_eq_pos() {
check_complex_output("clap-test value --flag --option=some", FOP);
}
#[test]
fn sc_long_flag_long_opt() {
check_complex_output("clap-test subcmd value --flag --option some", SCFOP);
}
#[test]
fn sc_long_flag_short_opt_pos() {
check_complex_output("clap-test subcmd value --flag -o some", SCFOP);
}
#[test]
fn sc_long_flag_long_opt_eq_pos() {
check_complex_output("clap-test subcmd value --flag --option=some", SCFOP);
}
#[test]
fn sc_short_flag_long_opt_pos() {
check_complex_output("clap-test subcmd value -f --option some", SCFOP);
}
#[test]
fn sc_short_flag_short_opt_pos() {
check_complex_output("clap-test subcmd value -f -o some", SCFOP);
}
#[test]
fn sc_short_flag_short_opt_eq_pos() {
check_complex_output("clap-test subcmd value -f -o=some", SCFOP);
}
#[test]
fn sc_short_flag_long_opt_eq_pos() {
check_complex_output("clap-test subcmd value -f --option=some", SCFOP);
}
#[test]
fn sc_short_flag_x2_comb_long_opt_pos() {
check_complex_output("clap-test subcmd value -ff --option some", SCF2OP);
}
#[test]
fn sc_short_flag_x2_comb_short_opt_pos() {
check_complex_output("clap-test subcmd value -ff -o some", SCF2OP);
}
#[test]
fn sc_short_flag_x2_comb_long_opt_eq_pos() {
check_complex_output("clap-test subcmd value -ff --option=some", SCF2OP);
}
#[test]
fn sc_short_flag_x2_comb_short_opt_eq_pos() {
check_complex_output("clap-test subcmd value -ff -o=some", SCF2OP);
}
#[test]
fn sc_long_flag_x2_long_opt_pos() {
check_complex_output("clap-test subcmd value --flag --flag --option some", SCF2OP);
}
#[test]
fn sc_long_flag_x2_short_opt_pos() {
check_complex_output("clap-test subcmd value --flag --flag -o some", SCF2OP);
}
#[test]
fn sc_long_flag_x2_short_opt_eq_pos() {
check_complex_output("clap-test subcmd value --flag --flag -o=some", SCF2OP);
}
#[test]
fn sc_long_flag_x2_long_opt_eq_pos() {
check_complex_output("clap-test subcmd value --flag --flag --option=some", SCF2OP);
}
#[test]
fn sc_short_flag_x2_long_opt_pos() {
check_complex_output("clap-test subcmd value -f -f --option some", SCF2OP);
}
#[test]
fn sc_short_flag_x2_short_opt_pos() {
check_complex_output("clap-test subcmd value -f -f -o some", SCF2OP);
}
#[test]
fn sc_short_flag_x2_short_opt_eq_pos() {
check_complex_output("clap-test subcmd value -f -f -o=some", SCF2OP);
}
#[test]
fn sc_short_flag_x2_long_opt_eq_pos() {
check_complex_output("clap-test subcmd value -f -f --option=some", SCF2OP);
}
#[test]
fn mut_arg_all() {
let mut cmd = utils::complex_app();
let arg_names = cmd
.get_arguments()
.map(|a| a.get_id())
.filter(|a| *a != "version" && *a != "help")
.collect::<Vec<_>>();
for arg_name in arg_names {
cmd = cmd.mut_arg(arg_name, |arg| arg.hide_possible_values(true));
}
}
#[test]
fn issue_3669_command_build_recurses() {
let mut cmd = Command::new("ctest").subcommand(
Command::new("subcmd").subcommand(
Command::new("multi")
.about("tests subcommands")
.author("Kevin K. <kbknapp@gmail.com>")
.version("0.1")
.arg(clap::arg!(
<FLAG> "tests flags"
)),
),
);
cmd.build();
}

View file

@ -1,18 +0,0 @@
#![cfg(feature = "unicode")]
#[test]
fn possible_values_ignore_case() {
let m = clap::Command::new("pv")
.arg(
clap::Arg::new("option")
.short('o')
.long("option")
.takes_value(true)
.possible_value("ä")
.ignore_case(true),
)
.try_get_matches_from(vec!["pv", "--option", "Ä"]);
assert!(m.is_ok(), "{}", m.unwrap_err());
assert!(m.unwrap().value_of("option").is_some());
}

View file

@ -1,32 +0,0 @@
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument names must be unique, but 'arg1' is in use by more than one argument or group"]
fn unique_arg_names() {
use clap::{Arg, Command};
let _ = Command::new("some")
.args(&[Arg::new("arg1").short('a'), Arg::new("arg1").short('b')])
.try_get_matches();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Short option names must be unique for each argument, but '-a' is in use by both 'arg1' and 'arg2'"]
fn unique_arg_shorts() {
use clap::{Arg, Command};
let _ = Command::new("some")
.args(&[Arg::new("arg1").short('a'), Arg::new("arg2").short('a')])
.try_get_matches();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Long option names must be unique for each argument, but '--long' is in use by both 'arg1' and 'arg2'"]
fn unique_arg_longs() {
use clap::{Arg, Command};
let _ = Command::new("some")
.args(&[Arg::new("arg1").long("long"), Arg::new("arg2").long("long")])
.try_get_matches();
}

View file

@ -1,169 +0,0 @@
//! These Windows-only tests are ported from the Unix-only tests in
//! tests/utf16.rs. The tests that use StrictUtf8 mode are omitted here,
//! because that's a Unix-only feature.
#![cfg(windows)]
use clap::{arg, Command};
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
// Take a slice of ASCII bytes, convert them to UTF-16, and then append a
// dangling surrogate character to make the result invalid UTF-16.
fn bad_osstring(ascii: &[u8]) -> OsString {
let mut wide_chars: Vec<u16> = ascii.iter().map(|&c| c as u16).collect();
// UTF-16 surrogate characters are only valid in pairs.
let surrogate_char: u16 = 0xDC00;
wide_chars.push(surrogate_char);
let os = OsString::from_wide(&wide_chars);
assert!(os.to_str().is_none(), "invalid Unicode");
os
}
#[test]
fn invalid_utf16_lossy_positional() {
let r = Command::new("bad_utf16")
.arg(arg!(<arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![OsString::from(""), bad_osstring(b"")]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf16_lossy_option_short_space() {
let r = Command::new("bad_utf16")
.arg(arg!(-a --arg <arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("-a"),
bad_osstring(b""),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf16_lossy_option_short_equals() {
let r = Command::new("bad_utf16")
.arg(arg!(-a --arg <arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![OsString::from(""), bad_osstring(b"-a=")]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf16_lossy_option_short_no_space() {
let r = Command::new("bad_utf16")
.arg(arg!(-a --arg <arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![OsString::from(""), bad_osstring(b"-a")]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf16_lossy_option_long_space() {
let r = Command::new("bad_utf16")
.arg(arg!(-a --arg <arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("--arg"),
bad_osstring(b""),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf16_lossy_option_long_equals() {
let r = Command::new("bad_utf16")
.arg(arg!(-a --arg <arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![OsString::from(""), bad_osstring(b"--arg=")]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf16_positional() {
let r = Command::new("bad_utf16")
.arg(arg!(<arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![OsString::from(""), bad_osstring(b"")]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_os("arg").unwrap(), &*bad_osstring(b""));
}
#[test]
fn invalid_utf16_option_short_space() {
let r = Command::new("bad_utf16")
.arg(arg!(-a --arg <arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("-a"),
bad_osstring(b""),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_os("arg").unwrap(), &*bad_osstring(b""));
}
#[test]
fn invalid_utf16_option_short_equals() {
let r = Command::new("bad_utf16")
.arg(arg!(-a --arg <arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![OsString::from(""), bad_osstring(b"-a=")]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_os("arg").unwrap(), &*bad_osstring(b""));
}
#[test]
fn invalid_utf16_option_short_no_space() {
let r = Command::new("bad_utf16")
.arg(arg!(-a --arg <arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![OsString::from(""), bad_osstring(b"-a")]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_os("arg").unwrap(), &*bad_osstring(b""));
}
#[test]
fn invalid_utf16_option_long_space() {
let r = Command::new("bad_utf16")
.arg(arg!(-a --arg <arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("--arg"),
bad_osstring(b""),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_os("arg").unwrap(), &*bad_osstring(b""));
}
#[test]
fn invalid_utf16_option_long_equals() {
let r = Command::new("bad_utf16")
.arg(arg!(-a --arg <arg> "some arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![OsString::from(""), bad_osstring(b"--arg=")]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_os("arg").unwrap(), &*bad_osstring(b""));
}

View file

@ -1,480 +0,0 @@
#![cfg(not(windows))]
use clap::{arg, error::ErrorKind, Arg, Command};
use std::ffi::OsString;
use std::os::unix::ffi::OsStringExt;
#[test]
fn invalid_utf8_strict_positional() {
let m = Command::new("bad_utf8")
.arg(Arg::new("arg"))
.try_get_matches_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
}
#[test]
fn invalid_utf8_strict_option_short_space() {
let m = Command::new("bad_utf8")
.arg(Arg::new("arg").short('a').long("arg").takes_value(true))
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("-a"),
OsString::from_vec(vec![0xe9]),
]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
}
#[test]
fn invalid_utf8_strict_option_short_equals() {
let m = Command::new("bad_utf8")
.arg(Arg::new("arg").short('a').long("arg").takes_value(true))
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9]),
]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
}
#[test]
fn invalid_utf8_strict_option_short_no_space() {
let m = Command::new("bad_utf8")
.arg(Arg::new("arg").short('a').long("arg").takes_value(true))
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0x2d, 0x61, 0xe9]),
]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
}
#[test]
fn invalid_utf8_strict_option_long_space() {
let m = Command::new("bad_utf8")
.arg(Arg::new("arg").short('a').long("arg").takes_value(true))
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("--arg"),
OsString::from_vec(vec![0xe9]),
]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
}
#[test]
fn invalid_utf8_strict_option_long_equals() {
let m = Command::new("bad_utf8")
.arg(Arg::new("arg").short('a').long("arg").takes_value(true))
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9]),
]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
}
#[test]
fn invalid_utf8_lossy_positional() {
let r = Command::new("bad_utf8")
.arg(Arg::new("arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf8_lossy_option_short_space() {
let r = Command::new("bad_utf8")
.arg(
Arg::new("arg")
.short('a')
.long("arg")
.takes_value(true)
.allow_invalid_utf8(true),
)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("-a"),
OsString::from_vec(vec![0xe9]),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf8_lossy_option_short_equals() {
let r = Command::new("bad_utf8")
.arg(
Arg::new("arg")
.short('a')
.long("arg")
.takes_value(true)
.allow_invalid_utf8(true),
)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9]),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf8_lossy_option_short_no_space() {
let r = Command::new("bad_utf8")
.arg(
Arg::new("arg")
.short('a')
.long("arg")
.takes_value(true)
.allow_invalid_utf8(true),
)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0x2d, 0x61, 0xe9]),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf8_lossy_option_long_space() {
let r = Command::new("bad_utf8")
.arg(
Arg::new("arg")
.short('a')
.long("arg")
.takes_value(true)
.allow_invalid_utf8(true),
)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("--arg"),
OsString::from_vec(vec![0xe9]),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf8_lossy_option_long_equals() {
let r = Command::new("bad_utf8")
.arg(
Arg::new("arg")
.short('a')
.long("arg")
.takes_value(true)
.allow_invalid_utf8(true),
)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9]),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
}
#[test]
fn invalid_utf8_positional() {
let r = Command::new("bad_utf8")
.arg(Arg::new("arg").allow_invalid_utf8(true))
.try_get_matches_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(
&*m.value_of_os("arg").unwrap(),
&*OsString::from_vec(vec![0xe9])
);
}
#[test]
fn invalid_utf8_option_short_space() {
let r = Command::new("bad_utf8")
.arg(
Arg::new("arg")
.short('a')
.long("arg")
.takes_value(true)
.allow_invalid_utf8(true),
)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("-a"),
OsString::from_vec(vec![0xe9]),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(
&*m.value_of_os("arg").unwrap(),
&*OsString::from_vec(vec![0xe9])
);
}
#[test]
fn invalid_utf8_option_short_equals() {
let r = Command::new("bad_utf8")
.arg(
Arg::new("arg")
.short('a')
.long("arg")
.takes_value(true)
.allow_invalid_utf8(true),
)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9]),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(
&*m.value_of_os("arg").unwrap(),
&*OsString::from_vec(vec![0xe9])
);
}
#[test]
fn invalid_utf8_option_short_no_space() {
let r = Command::new("bad_utf8")
.arg(
Arg::new("arg")
.short('a')
.long("arg")
.takes_value(true)
.allow_invalid_utf8(true),
)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0x2d, 0x61, 0xe9]),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(
&*m.value_of_os("arg").unwrap(),
&*OsString::from_vec(vec![0xe9])
);
}
#[test]
fn invalid_utf8_option_long_space() {
let r = Command::new("bad_utf8")
.arg(
Arg::new("arg")
.short('a')
.long("arg")
.takes_value(true)
.allow_invalid_utf8(true),
)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("--arg"),
OsString::from_vec(vec![0xe9]),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(
&*m.value_of_os("arg").unwrap(),
&*OsString::from_vec(vec![0xe9])
);
}
#[test]
fn invalid_utf8_option_long_equals() {
let r = Command::new("bad_utf8")
.arg(
Arg::new("arg")
.short('a')
.long("arg")
.takes_value(true)
.allow_invalid_utf8(true),
)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9]),
]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(
&*m.value_of_os("arg").unwrap(),
&*OsString::from_vec(vec![0xe9])
);
}
#[test]
fn refuse_invalid_utf8_subcommand_with_allow_external_subcommands() {
let m = Command::new("bad_utf8")
.allow_external_subcommands(true)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0xe9]),
OsString::from("normal"),
]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
}
#[test]
fn refuse_invalid_utf8_subcommand_when_args_are_allowed_with_allow_external_subcommands() {
let m = Command::new("bad_utf8")
.allow_external_subcommands(true)
.allow_invalid_utf8_for_external_subcommands(true)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from_vec(vec![0xe9]),
OsString::from("normal"),
]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
}
#[test]
fn refuse_invalid_utf8_subcommand_args_with_allow_external_subcommands() {
let m = Command::new("bad_utf8")
.allow_external_subcommands(true)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("subcommand"),
OsString::from("normal"),
OsString::from_vec(vec![0xe9]),
OsString::from("--another_normal"),
]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
}
#[test]
fn allow_invalid_utf8_subcommand_args_with_allow_external_subcommands() {
let m = Command::new("bad_utf8")
.allow_external_subcommands(true)
.allow_invalid_utf8_for_external_subcommands(true)
.try_get_matches_from(vec![
OsString::from(""),
OsString::from("subcommand"),
OsString::from("normal"),
OsString::from_vec(vec![0xe9]),
OsString::from("--another_normal"),
]);
assert!(m.is_ok(), "{}", m.unwrap_err());
let m = m.unwrap();
let (subcommand, args) = m.subcommand().unwrap();
let args = args.values_of_os("").unwrap().collect::<Vec<_>>();
assert_eq!(subcommand, OsString::from("subcommand"));
assert_eq!(
args,
vec![
OsString::from("normal"),
OsString::from_vec(vec![0xe9]),
OsString::from("--another_normal"),
]
);
}
#[test]
fn allow_validated_utf8_value_of() {
let a = Command::new("test").arg(arg!(--name <NAME>));
let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap();
let _ = m.value_of("name");
}
#[test]
#[should_panic = "Must use `Arg::allow_invalid_utf8` with `_os` lookups at `name`"]
fn panic_validated_utf8_value_of_os() {
let a = Command::new("test").arg(arg!(--name <NAME>));
let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap();
let _ = m.value_of_os("name");
}
#[test]
#[should_panic = "Must use `Arg::allow_invalid_utf8` with `_os` lookups at `value`"]
fn panic_validated_utf8_with_defaults() {
let a = Command::new("test").arg(arg!(--value <VALUE>).required(false).default_value("foo"));
let m = a.try_get_matches_from(["test"]).unwrap();
let _ = m.value_of("value");
let _ = m.value_of_os("value");
}
#[test]
fn allow_invalid_utf8_value_of_os() {
let a = Command::new("test").arg(arg!(--name <NAME>).allow_invalid_utf8(true));
let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap();
let _ = m.value_of_os("name");
}
#[test]
#[should_panic = "Must use `_os` lookups with `Arg::allow_invalid_utf8` at `name`"]
fn panic_invalid_utf8_value_of() {
let a = Command::new("test").arg(arg!(--name <NAME>).allow_invalid_utf8(true));
let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap();
let _ = m.value_of("name");
}
#[test]
#[should_panic = "Must use `_os` lookups with `Arg::allow_invalid_utf8` at `value`"]
fn panic_invalid_utf8_with_defaults() {
let a = Command::new("test").arg(
arg!(--value <VALUE>)
.required(false)
.default_value("foo")
.allow_invalid_utf8(true),
);
let m = a.try_get_matches_from(["test"]).unwrap();
let _ = m.value_of("value");
let _ = m.value_of_os("value");
}
#[test]
fn allow_validated_utf8_external_subcommand_values_of() {
let a = Command::new("test").allow_external_subcommands(true);
let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap();
let (_ext, args) = m.subcommand().unwrap();
let _ = args.values_of("").unwrap_or_default().count();
}
#[test]
#[should_panic = "Must use `Arg::allow_invalid_utf8` with `_os` lookups"]
fn panic_validated_utf8_external_subcommand_values_of_os() {
let a = Command::new("test").allow_external_subcommands(true);
let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap();
let (_ext, args) = m.subcommand().unwrap();
let _ = args.values_of_os("").unwrap_or_default().count();
}
#[test]
fn allow_invalid_utf8_external_subcommand_values_of_os() {
let a = Command::new("test")
.allow_external_subcommands(true)
.allow_invalid_utf8_for_external_subcommands(true);
let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap();
let (_ext, args) = m.subcommand().unwrap();
let _ = args.values_of_os("").unwrap_or_default().count();
}
#[test]
#[should_panic = "Must use `_os` lookups with `Arg::allow_invalid_utf8`"]
fn panic_invalid_utf8_external_subcommand_values_of() {
let a = Command::new("test")
.allow_external_subcommands(true)
.allow_invalid_utf8_for_external_subcommands(true);
let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap();
let (_ext, args) = m.subcommand().unwrap();
let _ = args.values_of("").unwrap_or_default().count();
}

View file

@ -1,107 +0,0 @@
#![allow(unused_imports, dead_code)]
use std::io::{BufRead, Cursor, Write};
use std::str;
use regex::Regex;
use clap::{arg, Arg, ArgGroup, Command};
#[track_caller]
pub fn assert_eq<S, S2>(expected: S, actual: S2)
where
S: AsRef<str>,
S2: AsRef<str>,
{
let expected = expected.as_ref();
let actual = actual.as_ref();
snapbox::assert_eq(expected, actual);
}
#[track_caller]
pub fn assert_output(l: Command, args: &str, expected: &str, stderr: bool) {
let mut buf = Cursor::new(Vec::with_capacity(50));
let res = l.try_get_matches_from(args.split(' ').collect::<Vec<_>>());
let err = res.unwrap_err();
write!(&mut buf, "{}", err).unwrap();
let actual = buf.into_inner();
let actual = String::from_utf8(actual).unwrap();
assert_eq!(
stderr,
err.use_stderr(),
"Should Use STDERR failed. Should be {} but is {}",
stderr,
err.use_stderr()
);
assert_eq(expected, actual)
}
// Legacy tests from the python script days
pub fn complex_app() -> Command<'static> {
let opt3_vals = ["fast", "slow"];
let pos3_vals = ["vi", "emacs"];
Command::new("clap-test")
.version("v1.4.8")
.about("tests clap library")
.author("Kevin K. <kbknapp@gmail.com>")
.arg(
arg!(
-o --option <opt> "tests options"
)
.required(false)
.multiple_values(true)
.multiple_occurrences(true),
)
.arg(arg!([positional] "tests positionals"))
.arg(arg!(-f --flag ... "tests flags").global(true))
.args(&[
arg!(flag2: -F "tests flags with exclusions")
.conflicts_with("flag")
.requires("long-option-2"),
arg!(--"long-option-2" <option2> "tests long options with exclusions")
.required(false)
.conflicts_with("option")
.requires("positional2"),
arg!([positional2] "tests positionals with exclusions"),
arg!(-O --option3 <option3> "specific vals")
.required(false)
.possible_values(opt3_vals),
arg!([positional3] ... "tests specific values").possible_values(pos3_vals),
arg!(--multvals "Tests multiple values, not mult occs")
.value_names(&["one", "two"])
.required(false),
arg!(--multvalsmo ... "Tests multiple values, and mult occs")
.value_names(&["one", "two"])
.required(false),
arg!(--minvals2 <minvals> "Tests 2 min vals")
.required(false)
.min_values(2),
arg!(--maxvals3 <maxvals> "Tests 3 max vals")
.required(false)
.max_values(3),
arg!(--optvaleq <optval> "Tests optional value, require = sign")
.required(false)
.min_values(0)
.number_of_values(1)
.require_equals(true),
arg!(--optvalnoeq <optval> "Tests optional value")
.required(false)
.min_values(0)
.number_of_values(1),
])
.subcommand(
Command::new("subcmd")
.about("tests subcommands")
.version("0.1")
.author("Kevin K. <kbknapp@gmail.com>")
.arg(
arg!(-o --option <scoption> "tests options")
.required(false)
.multiple_values(true),
)
.arg(arg!(-s --subcmdarg <subcmdarg> "tests other args").required(false))
.arg(arg!([scpositional] "tests positionals")),
)
}

View file

@ -1,66 +0,0 @@
use clap::{Arg, Command};
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument 'test' has both `validator` and `validator_os` set which is not allowed"]
fn both_validator_and_validator_os() {
let _ = Command::new("test")
.arg(
Arg::new("test")
.validator(|val| val.parse::<u32>().map_err(|e| e.to_string()))
.validator_os(|val| {
val.to_str()
.unwrap()
.parse::<u32>()
.map_err(|e| e.to_string())
}),
)
.try_get_matches_from(&["cmd", "1"]);
}
#[test]
fn test_validator_fromstr_trait() {
use std::str::FromStr;
let matches = Command::new("test")
.arg(Arg::new("from_str").validator(u32::from_str))
.try_get_matches_from(&["cmd", "1234"])
.expect("match failed");
assert_eq!(matches.value_of_t::<u32>("from_str").ok(), Some(1234));
}
#[test]
fn test_validator_msg_newline() {
let res = Command::new("test")
.arg(Arg::new("test").validator(|val| val.parse::<u32>().map_err(|e| e.to_string())))
.try_get_matches_from(&["cmd", "f"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert!(
err.to_string()
.contains("Invalid value \"f\" for '<test>': invalid digit found in string"),
"{}",
err
);
// This message is the only thing that gets printed -- make sure it ends with a newline
let msg = format!("{}", err);
assert!(msg.ends_with('\n'));
}
#[test]
fn stateful_validator() {
let mut state = false;
Command::new("test")
.arg(Arg::new("test").validator(|val| {
state = true;
val.parse::<u32>().map_err(|e| e.to_string())
}))
.try_get_matches_from(&["cmd", "10"])
.unwrap();
assert!(state);
}

View file

@ -1,235 +0,0 @@
use super::utils;
use std::str;
use clap::{error::ErrorKind, AppSettings, Arg, Command};
fn common() -> Command<'static> {
Command::new("foo")
}
fn with_version() -> Command<'static> {
common().version("3.0")
}
fn with_long_version() -> Command<'static> {
common().long_version("3.0 (abcdefg)")
}
fn with_subcommand() -> Command<'static> {
with_version().subcommand(Command::new("bar").subcommand(Command::new("baz")))
}
#[test]
fn no_version_flag_short() {
let res = common().try_get_matches_from("foo -V".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument);
}
#[test]
fn no_version_flag_long() {
let res = common().try_get_matches_from("foo --version".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument);
}
#[test]
fn version_flag_from_version_short() {
let res = with_version().try_get_matches_from("foo -V".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
assert_eq!(err.to_string(), "foo 3.0\n");
}
#[test]
fn version_flag_from_version_long() {
let res = with_version().try_get_matches_from("foo --version".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
assert_eq!(err.to_string(), "foo 3.0\n");
}
#[test]
fn version_flag_from_long_version_short() {
let res = with_long_version().try_get_matches_from("foo -V".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
assert_eq!(err.to_string(), "foo 3.0 (abcdefg)\n");
}
#[test]
fn version_flag_from_long_version_long() {
let res = with_long_version().try_get_matches_from("foo --version".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
assert_eq!(err.to_string(), "foo 3.0 (abcdefg)\n");
}
#[test]
fn override_version_long_with_user_flag() {
let res = with_version()
.arg(Arg::new("ver").long("version"))
.try_get_matches_from("foo --version".split(' '));
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("ver"));
}
#[test]
fn override_version_long_with_user_flag_no_version_flag() {
let res = with_version()
.arg(Arg::new("ver").long("version"))
.try_get_matches_from("foo -V".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::UnknownArgument);
}
#[test]
fn override_version_short_with_user_flag() {
let res = with_version()
.arg(Arg::new("ver").short('V'))
.try_get_matches_from("foo -V".split(' '));
assert!(res.is_ok(), "{}", res.unwrap_err());
let m = res.unwrap();
assert!(m.is_present("ver"));
}
#[test]
fn override_version_short_with_user_flag_long_still_works() {
let res = with_version()
.arg(Arg::new("ver").short('V'))
.try_get_matches_from("foo --version".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
}
#[test]
fn mut_version_short() {
let res = with_version()
.mut_arg("version", |a| a.short('z'))
.try_get_matches_from("foo -z".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
}
#[test]
fn mut_version_long() {
let res = with_version()
.mut_arg("version", |a| a.long("qux"))
.try_get_matches_from("foo --qux".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
}
static VERSION_ABOUT_MULTI_SC: &str = "foo-bar-baz 3.0
USAGE:
foo bar baz
OPTIONS:
-h, --help Print help information
-V, --version Print custom version about text
";
#[test]
fn version_about_multi_subcmd() {
let cmd = with_subcommand()
.mut_arg("version", |a| a.help("Print custom version about text"))
.propagate_version(true);
utils::assert_output(cmd, "foo bar baz -h", VERSION_ABOUT_MULTI_SC, false);
}
#[test]
fn no_propagation_by_default_long() {
// Version Flag should not be propagated to subcommands
let res = with_subcommand().try_get_matches_from("foo bar --version".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::UnknownArgument);
}
#[test]
fn no_propagation_by_default_short() {
let res = with_subcommand().try_get_matches_from("foo bar -V".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::UnknownArgument);
}
#[test]
fn propagate_version_long() {
let res = with_subcommand()
.propagate_version(true)
.try_get_matches_from("foo bar --version".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
}
#[test]
fn propagate_version_short() {
let res = with_subcommand()
.propagate_version(true)
.try_get_matches_from("foo bar -V".split(' '));
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "`ArgAction::Version` used without providing Command::version or Command::long_version"]
fn mut_arg_version_panic() {
let _res = common()
.mut_arg("version", |v| v.short('z'))
.try_get_matches_from("foo -z".split(' '));
}
#[test]
fn mut_arg_version_no_auto_version() {
let res = common()
.mut_arg("version", |v| v.short('z'))
.setting(AppSettings::NoAutoVersion)
.try_get_matches_from("foo -z".split(' '));
assert!(res.is_ok(), "{}", res.unwrap_err());
assert!(res.unwrap().is_present("version"));
}
#[cfg(debug_assertions)]
#[test]
#[should_panic = "No version information via Command::version or Command::long_version to propagate"]
fn propagate_version_no_version_info() {
let _res = common()
.propagate_version(true)
.subcommand(Command::new("bar"))
.try_get_matches_from("foo".split(' '));
}

View file

@ -1,12 +1,10 @@
#![allow(clippy::bool_assert_comparison)]
mod action;
mod app_from_crate;
mod app_settings;
mod arg_aliases;
mod arg_aliases_short;
mod arg_matcher_assertions;
mod arg_settings;
mod borrowed;
mod cargo;
mod command;
@ -30,7 +28,6 @@ mod help_env;
mod hidden_args;
mod ignore_errors;
mod indices;
mod legacy;
mod multiple_occurrences;
mod multiple_values;
mod opts;
@ -38,7 +35,6 @@ mod positionals;
mod posix_compatible;
mod possible_values;
mod propagate_globals;
mod regex;
mod require;
mod subcommands;
mod template_help;
@ -48,5 +44,4 @@ mod unique_args;
mod utf16;
mod utf8;
mod utils;
mod validators;
mod version;

View file

@ -1,37 +0,0 @@
#![cfg(feature = "regex")]
#![allow(deprecated)]
use clap::{error::ErrorKind, Arg, Command};
use regex::{Regex, RegexSet};
#[test]
fn validator_regex() {
let priority = Regex::new(r"[A-C]").unwrap();
let m = Command::new("prog")
.arg(
Arg::new("priority")
.index(1)
.validator_regex(priority, "A, B or C are allowed"),
)
.try_get_matches_from(vec!["prog", "12345"]);
assert!(m.is_err());
assert_eq!(m.err().unwrap().kind(), ErrorKind::ValueValidation)
}
#[test]
fn validator_regex_with_regex_set() {
let priority = RegexSet::new(&[r"[A-C]", r"[X-Z]"]).unwrap();
let m = Command::new("prog")
.arg(
Arg::new("priority")
.index(1)
.validator_regex(priority, "A, B, C, X, Y or Z are allowed"),
)
.try_get_matches_from(vec!["prog", "12345"]);
assert!(m.is_err());
assert_eq!(m.err().unwrap().kind(), ErrorKind::ValueValidation)
}

View file

@ -287,57 +287,6 @@ fn allow_validated_utf8_value_of() {
let _ = m.get_one::<String>("name").map(|v| v.as_str());
}
#[test]
#[should_panic = "Must use `Arg::allow_invalid_utf8` with `_os` lookups at `name`"]
fn panic_validated_utf8_value_of_os() {
#![allow(deprecated)]
let a = Command::new("test").arg(arg!(--name <NAME>));
let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap();
let _ = m.value_of_os("name");
}
#[test]
#[should_panic = "Must use `Arg::allow_invalid_utf8` with `_os` lookups at `value`"]
fn panic_validated_utf8_with_defaults() {
#![allow(deprecated)]
let a = Command::new("test").arg(arg!(--value <VALUE>).required(false).default_value("foo"));
let m = a.try_get_matches_from(["test"]).unwrap();
let _ = m.get_one::<String>("value").map(|v| v.as_str());
let _ = m.value_of_os("value");
}
#[test]
fn allow_invalid_utf8_value_of_os() {
#![allow(deprecated)]
let a = Command::new("test").arg(arg!(--name <NAME>).allow_invalid_utf8(true));
let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap();
let _ = m.value_of_os("name");
}
#[test]
#[should_panic = "Mismatch between definition and access of `name`. Could not downcast to alloc::string::String, need to downcast to std::ffi::os_str::OsString"]
fn panic_invalid_utf8_value_of() {
#![allow(deprecated)]
let a = Command::new("test").arg(arg!(--name <NAME>).allow_invalid_utf8(true));
let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap();
let _ = m.get_one::<String>("name").map(|v| v.as_str());
}
#[test]
#[should_panic = "Mismatch between definition and access of `value`. Could not downcast to alloc::string::String, need to downcast to std::ffi::os_str::OsString"]
fn panic_invalid_utf8_with_defaults() {
#![allow(deprecated)]
let a = Command::new("test").arg(
arg!(--value <VALUE>)
.required(false)
.default_value("foo")
.allow_invalid_utf8(true),
);
let m = a.try_get_matches_from(["test"]).unwrap();
let _ = m.value_of_os("value");
let _ = m.get_one::<String>("value").map(|v| v.as_str());
}
#[test]
fn allow_validated_utf8_external_subcommand_values_of() {
let a = Command::new("test").allow_external_subcommands(true);

View file

@ -3,8 +3,6 @@
use std::io::{BufRead, Cursor, Write};
use std::str;
use regex::Regex;
use clap::{arg, Arg, ArgAction, ArgGroup, Command};
#[track_caller]

View file

@ -1,68 +0,0 @@
#![allow(deprecated)]
use clap::{Arg, Command};
#[cfg(debug_assertions)]
#[test]
#[should_panic = "Argument 'test' has both `validator` and `validator_os` set which is not allowed"]
fn both_validator_and_validator_os() {
let _ = Command::new("test")
.arg(
Arg::new("test")
.validator(|val| val.parse::<u32>().map_err(|e| e.to_string()))
.validator_os(|val| {
val.to_str()
.unwrap()
.parse::<u32>()
.map_err(|e| e.to_string())
}),
)
.try_get_matches_from(&["cmd", "1"]);
}
#[test]
fn test_validator_fromstr_trait() {
use std::str::FromStr;
let matches = Command::new("test")
.arg(Arg::new("from_str").validator(u32::from_str))
.try_get_matches_from(&["cmd", "1234"])
.expect("match failed");
assert_eq!(matches.value_of_t::<u32>("from_str").ok(), Some(1234));
}
#[test]
fn test_validator_msg_newline() {
let res = Command::new("test")
.arg(Arg::new("test").validator(|val| val.parse::<u32>().map_err(|e| e.to_string())))
.try_get_matches_from(&["cmd", "f"]);
assert!(res.is_err());
let err = res.unwrap_err();
assert!(
err.to_string()
.contains("Invalid value \"f\" for '<test>': invalid digit found in string"),
"{}",
err
);
// This message is the only thing that gets printed -- make sure it ends with a newline
let msg = format!("{}", err);
assert!(msg.ends_with('\n'));
}
#[test]
fn stateful_validator() {
let mut state = false;
Command::new("test")
.arg(Arg::new("test").validator(|val| {
state = true;
val.parse::<u32>().map_err(|e| e.to_string())
}))
.try_get_matches_from(&["cmd", "10"])
.unwrap();
assert!(state);
}

View file

@ -16,7 +16,6 @@
use clap::Parser;
use std::ffi::CString;
use std::num::ParseIntError;
use std::path::PathBuf;
@ -204,116 +203,3 @@ fn test_parser_occurrences() {
.unwrap()
);
}
#[test]
fn test_custom_bool() {
fn parse_bool(s: &str) -> Result<bool, String> {
match s {
"true" => Ok(true),
"false" => Ok(false),
_ => Err(format!("invalid bool {}", s)),
}
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(short, parse(try_from_str = parse_bool))]
debug: bool,
#[clap(
short,
default_value = "false",
parse(try_from_str = parse_bool)
)]
verbose: bool,
#[clap(short, parse(try_from_str = parse_bool))]
tribool: Option<bool>,
#[clap(short, parse(try_from_str = parse_bool), multiple_occurrences(true))]
bitset: Vec<bool>,
}
assert!(Opt::try_parse_from(&["test"]).is_err());
assert!(Opt::try_parse_from(&["test", "-d"]).is_err());
assert!(Opt::try_parse_from(&["test", "-dfoo"]).is_err());
assert_eq!(
Opt {
debug: false,
verbose: false,
tribool: None,
bitset: vec![],
},
Opt::try_parse_from(&["test", "-dfalse"]).unwrap()
);
assert_eq!(
Opt {
debug: true,
verbose: false,
tribool: None,
bitset: vec![],
},
Opt::try_parse_from(&["test", "-dtrue"]).unwrap()
);
assert_eq!(
Opt {
debug: true,
verbose: false,
tribool: None,
bitset: vec![],
},
Opt::try_parse_from(&["test", "-dtrue", "-vfalse"]).unwrap()
);
assert_eq!(
Opt {
debug: true,
verbose: true,
tribool: None,
bitset: vec![],
},
Opt::try_parse_from(&["test", "-dtrue", "-vtrue"]).unwrap()
);
assert_eq!(
Opt {
debug: true,
verbose: false,
tribool: Some(false),
bitset: vec![],
},
Opt::try_parse_from(&["test", "-dtrue", "-tfalse"]).unwrap()
);
assert_eq!(
Opt {
debug: true,
verbose: false,
tribool: Some(true),
bitset: vec![],
},
Opt::try_parse_from(&["test", "-dtrue", "-ttrue"]).unwrap()
);
assert_eq!(
Opt {
debug: true,
verbose: false,
tribool: None,
bitset: vec![false, true, false, false],
},
Opt::try_parse_from(&["test", "-dtrue", "-bfalse", "-btrue", "-bfalse", "-bfalse"])
.unwrap()
);
}
#[test]
fn test_cstring() {
#[derive(Parser)]
struct Opt {
#[clap(parse(try_from_str = CString::new))]
c_string: CString,
}
assert!(Opt::try_parse_from(&["test"]).is_err());
assert_eq!(
Opt::try_parse_from(&["test", "bla"])
.unwrap()
.c_string
.to_bytes(),
b"bla"
);
assert!(Opt::try_parse_from(&["test", "bla\0bla"]).is_err());
}

View file

@ -1,97 +0,0 @@
use clap::CommandFactory;
use clap::Parser;
#[test]
fn app_name_in_short_help_from_struct() {
#[derive(Parser)]
#[clap(name = "my-cmd")]
struct MyApp {}
let mut help = Vec::new();
MyApp::command().write_help(&mut help).unwrap();
let help = String::from_utf8(help).unwrap();
assert!(help.contains("my-cmd"));
}
#[test]
fn app_name_in_long_help_from_struct() {
#[derive(Parser)]
#[clap(name = "my-cmd")]
struct MyApp {}
let mut help = Vec::new();
MyApp::command().write_long_help(&mut help).unwrap();
let help = String::from_utf8(help).unwrap();
assert!(help.contains("my-cmd"));
}
#[test]
fn app_name_in_short_help_from_enum() {
#[derive(Parser)]
#[clap(name = "my-cmd")]
enum MyApp {}
let mut help = Vec::new();
MyApp::command().write_help(&mut help).unwrap();
let help = String::from_utf8(help).unwrap();
assert!(help.contains("my-cmd"));
}
#[test]
fn app_name_in_long_help_from_enum() {
#[derive(Parser)]
#[clap(name = "my-cmd")]
enum MyApp {}
let mut help = Vec::new();
MyApp::command().write_long_help(&mut help).unwrap();
let help = String::from_utf8(help).unwrap();
assert!(help.contains("my-cmd"));
}
#[test]
fn app_name_in_short_version_from_struct() {
#[derive(Parser)]
#[clap(name = "my-cmd")]
struct MyApp {}
let version = MyApp::command().render_version();
assert!(version.contains("my-cmd"));
}
#[test]
fn app_name_in_long_version_from_struct() {
#[derive(Parser)]
#[clap(name = "my-cmd")]
struct MyApp {}
let version = MyApp::command().render_long_version();
assert!(version.contains("my-cmd"));
}
#[test]
fn app_name_in_short_version_from_enum() {
#[derive(Parser)]
#[clap(name = "my-cmd")]
enum MyApp {}
let version = MyApp::command().render_version();
assert!(version.contains("my-cmd"));
}
#[test]
fn app_name_in_long_version_from_enum() {
#[derive(Parser)]
#[clap(name = "my-cmd")]
enum MyApp {}
let version = MyApp::command().render_long_version();
assert!(version.contains("my-cmd"));
}

View file

@ -1,526 +0,0 @@
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <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::Parser;
#[test]
fn basic() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
Foo,
Bar,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum)]
arg: ArgChoice,
}
assert_eq!(
Opt {
arg: ArgChoice::Foo
},
Opt::try_parse_from(&["", "foo"]).unwrap()
);
assert_eq!(
Opt {
arg: ArgChoice::Bar
},
Opt::try_parse_from(&["", "bar"]).unwrap()
);
assert!(Opt::try_parse_from(&["", "fOo"]).is_err());
}
#[test]
fn default_value() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
Foo,
Bar,
}
impl Default for ArgChoice {
fn default() -> Self {
Self::Bar
}
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum, default_value_t)]
arg: ArgChoice,
}
assert_eq!(
Opt {
arg: ArgChoice::Foo
},
Opt::try_parse_from(&["", "foo"]).unwrap()
);
assert_eq!(
Opt {
arg: ArgChoice::Bar
},
Opt::try_parse_from(&["", "bar"]).unwrap()
);
assert_eq!(
Opt {
arg: ArgChoice::Bar
},
Opt::try_parse_from(&[""]).unwrap()
);
}
#[test]
fn multi_word_is_renamed_kebab() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
#[allow(non_camel_case_types)]
enum ArgChoice {
FooBar,
BAR_BAZ,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum)]
arg: ArgChoice,
}
assert_eq!(
Opt {
arg: ArgChoice::FooBar
},
Opt::try_parse_from(&["", "foo-bar"]).unwrap()
);
assert_eq!(
Opt {
arg: ArgChoice::BAR_BAZ
},
Opt::try_parse_from(&["", "bar-baz"]).unwrap()
);
assert!(Opt::try_parse_from(&["", "FooBar"]).is_err());
}
#[test]
fn variant_with_defined_casing() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
#[clap(rename_all = "screaming_snake")]
FooBar,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum)]
arg: ArgChoice,
}
assert_eq!(
Opt {
arg: ArgChoice::FooBar
},
Opt::try_parse_from(&["", "FOO_BAR"]).unwrap()
);
assert!(Opt::try_parse_from(&["", "FooBar"]).is_err());
}
#[test]
fn casing_is_propagated_from_parent() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
#[clap(rename_all = "screaming_snake")]
enum ArgChoice {
FooBar,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum)]
arg: ArgChoice,
}
assert_eq!(
Opt {
arg: ArgChoice::FooBar
},
Opt::try_parse_from(&["", "FOO_BAR"]).unwrap()
);
assert!(Opt::try_parse_from(&["", "FooBar"]).is_err());
}
#[test]
fn casing_propagation_is_overridden() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
#[clap(rename_all = "screaming_snake")]
enum ArgChoice {
#[clap(rename_all = "camel")]
FooBar,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum)]
arg: ArgChoice,
}
assert_eq!(
Opt {
arg: ArgChoice::FooBar
},
Opt::try_parse_from(&["", "fooBar"]).unwrap()
);
assert!(Opt::try_parse_from(&["", "FooBar"]).is_err());
assert!(Opt::try_parse_from(&["", "FOO_BAR"]).is_err());
}
#[test]
fn ignore_case() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
Foo,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum, ignore_case(true))]
arg: ArgChoice,
}
assert_eq!(
Opt {
arg: ArgChoice::Foo
},
Opt::try_parse_from(&["", "foo"]).unwrap()
);
assert_eq!(
Opt {
arg: ArgChoice::Foo
},
Opt::try_parse_from(&["", "fOo"]).unwrap()
);
}
#[test]
fn ignore_case_set_to_false() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
Foo,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum, ignore_case(false))]
arg: ArgChoice,
}
assert_eq!(
Opt {
arg: ArgChoice::Foo
},
Opt::try_parse_from(&["", "foo"]).unwrap()
);
assert!(Opt::try_parse_from(&["", "fOo"]).is_err());
}
#[test]
fn alias() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
#[clap(alias = "TOTP")]
Totp,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum, ignore_case(false))]
arg: ArgChoice,
}
assert_eq!(
Opt {
arg: ArgChoice::Totp
},
Opt::try_parse_from(&["", "totp"]).unwrap()
);
assert_eq!(
Opt {
arg: ArgChoice::Totp
},
Opt::try_parse_from(&["", "TOTP"]).unwrap()
);
}
#[test]
fn multiple_alias() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
#[clap(alias = "TOTP", alias = "t")]
Totp,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum, ignore_case(false))]
arg: ArgChoice,
}
assert_eq!(
Opt {
arg: ArgChoice::Totp
},
Opt::try_parse_from(&["", "totp"]).unwrap()
);
assert_eq!(
Opt {
arg: ArgChoice::Totp
},
Opt::try_parse_from(&["", "TOTP"]).unwrap()
);
assert_eq!(
Opt {
arg: ArgChoice::Totp
},
Opt::try_parse_from(&["", "t"]).unwrap()
);
}
#[test]
fn skip_variant() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
#[allow(dead_code)] // silence warning about `Baz` being unused
enum ArgChoice {
Foo,
Bar,
#[clap(skip)]
Baz,
}
assert_eq!(
<ArgChoice as clap::ArgEnum>::value_variants()
.iter()
.map(clap::ArgEnum::to_possible_value)
.map(Option::unwrap)
.collect::<Vec<_>>(),
vec![
clap::PossibleValue::new("foo"),
clap::PossibleValue::new("bar")
]
);
{
use clap::ArgEnum;
assert!(ArgChoice::from_str("foo", true).is_ok());
assert!(ArgChoice::from_str("bar", true).is_ok());
assert!(ArgChoice::from_str("baz", true).is_err());
}
}
#[test]
fn skip_non_unit_variant() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
#[allow(dead_code)] // silence warning about `Baz` being unused
enum ArgChoice {
Foo,
Bar,
#[clap(skip)]
Baz(usize),
}
assert_eq!(
<ArgChoice as clap::ArgEnum>::value_variants()
.iter()
.map(clap::ArgEnum::to_possible_value)
.map(Option::unwrap)
.collect::<Vec<_>>(),
vec![
clap::PossibleValue::new("foo"),
clap::PossibleValue::new("bar")
]
);
{
use clap::ArgEnum;
assert!(ArgChoice::from_str("foo", true).is_ok());
assert!(ArgChoice::from_str("bar", true).is_ok());
assert!(ArgChoice::from_str("baz", true).is_err());
}
}
#[test]
fn from_str_invalid() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
Foo,
}
{
use clap::ArgEnum;
assert!(ArgChoice::from_str("bar", true).is_err());
}
}
#[test]
fn option_type() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
Foo,
Bar,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum)]
arg: Option<ArgChoice>,
}
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&[""]).unwrap());
assert_eq!(
Opt {
arg: Some(ArgChoice::Foo)
},
Opt::try_parse_from(&["", "foo"]).unwrap()
);
assert_eq!(
Opt {
arg: Some(ArgChoice::Bar)
},
Opt::try_parse_from(&["", "bar"]).unwrap()
);
assert!(Opt::try_parse_from(&["", "fOo"]).is_err());
}
#[test]
fn option_option_type() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
Foo,
Bar,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum, long)]
arg: Option<Option<ArgChoice>>,
}
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&[""]).unwrap());
assert_eq!(
Opt { arg: Some(None) },
Opt::try_parse_from(&["", "--arg"]).unwrap()
);
assert_eq!(
Opt {
arg: Some(Some(ArgChoice::Foo))
},
Opt::try_parse_from(&["", "--arg", "foo"]).unwrap()
);
assert_eq!(
Opt {
arg: Some(Some(ArgChoice::Bar))
},
Opt::try_parse_from(&["", "--arg", "bar"]).unwrap()
);
assert!(Opt::try_parse_from(&["", "--arg", "fOo"]).is_err());
}
#[test]
fn vec_type() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
Foo,
Bar,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum, short, long)]
arg: Vec<ArgChoice>,
}
assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&[""]).unwrap());
assert_eq!(
Opt {
arg: vec![ArgChoice::Foo]
},
Opt::try_parse_from(&["", "-a", "foo"]).unwrap()
);
assert_eq!(
Opt {
arg: vec![ArgChoice::Foo, ArgChoice::Bar]
},
Opt::try_parse_from(&["", "-a", "foo", "-a", "bar"]).unwrap()
);
assert!(Opt::try_parse_from(&["", "-a", "fOo"]).is_err());
}
#[test]
fn option_vec_type() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
Foo,
Bar,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(arg_enum, short, long)]
arg: Option<Vec<ArgChoice>>,
}
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&[""]).unwrap());
assert_eq!(
Opt {
arg: Some(vec![ArgChoice::Foo])
},
Opt::try_parse_from(&["", "-a", "foo"]).unwrap()
);
assert_eq!(
Opt {
arg: Some(vec![ArgChoice::Foo, ArgChoice::Bar])
},
Opt::try_parse_from(&["", "-a", "foo", "-a", "bar"]).unwrap()
);
assert!(Opt::try_parse_from(&["", "-a", "fOo"]).is_err());
}
#[test]
fn vec_type_default_value() {
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
enum ArgChoice {
Foo,
Bar,
Baz,
}
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(
arg_enum,
short,
long,
default_value = "foo,bar",
value_delimiter = ','
)]
arg: Vec<ArgChoice>,
}
assert_eq!(
Opt {
arg: vec![ArgChoice::Foo, ArgChoice::Bar]
},
Opt::try_parse_from(&[""]).unwrap()
);
assert_eq!(
Opt {
arg: vec![ArgChoice::Foo, ArgChoice::Baz]
},
Opt::try_parse_from(&["", "-a", "foo,baz"]).unwrap()
);
}

View file

@ -1,120 +0,0 @@
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <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.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.
use clap::CommandFactory;
use clap::Parser;
#[test]
fn required_argument() {
#[derive(Parser, PartialEq, Debug)]
struct Opt {
arg: i32,
}
assert_eq!(
Opt { arg: 42 },
Opt::try_parse_from(&["test", "42"]).unwrap()
);
assert!(Opt::try_parse_from(&["test"]).is_err());
assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err());
}
#[test]
fn argument_with_default() {
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(default_value = "42")]
arg: i32,
}
assert_eq!(
Opt { arg: 24 },
Opt::try_parse_from(&["test", "24"]).unwrap()
);
assert_eq!(Opt { arg: 42 }, Opt::try_parse_from(&["test"]).unwrap());
assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err());
}
#[test]
fn auto_value_name() {
#[derive(Parser, PartialEq, Debug)]
struct Opt {
my_special_arg: i32,
}
let mut help = Vec::new();
Opt::command().write_help(&mut help).unwrap();
let help = String::from_utf8(help).unwrap();
assert!(help.contains("MY_SPECIAL_ARG"));
// Ensure the implicit `num_vals` is just 1
assert_eq!(
Opt { my_special_arg: 10 },
Opt::try_parse_from(&["test", "10"]).unwrap()
);
}
#[test]
fn explicit_value_name() {
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[clap(value_name = "BROWNIE_POINTS")]
my_special_arg: i32,
}
let mut help = Vec::new();
Opt::command().write_help(&mut help).unwrap();
let help = String::from_utf8(help).unwrap();
assert!(help.contains("BROWNIE_POINTS"));
assert!(!help.contains("MY_SPECIAL_ARG"));
// Ensure the implicit `num_vals` is just 1
assert_eq!(
Opt { my_special_arg: 10 },
Opt::try_parse_from(&["test", "10"]).unwrap()
);
}
#[test]
fn option_type_is_optional() {
#[derive(Parser, PartialEq, Debug)]
struct Opt {
arg: Option<i32>,
}
assert_eq!(
Opt { arg: Some(42) },
Opt::try_parse_from(&["test", "42"]).unwrap()
);
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap());
assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err());
}
#[test]
fn vec_type_is_multiple_values() {
#[derive(Parser, PartialEq, Debug)]
struct Opt {
arg: Vec<i32>,
}
assert_eq!(
Opt { arg: vec![24] },
Opt::try_parse_from(&["test", "24"]).unwrap()
);
assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap());
assert_eq!(
Opt { arg: vec![24, 42] },
Opt::try_parse_from(&["test", "24", "42"]).unwrap()
);
assert_eq!(
clap::ErrorKind::ValueValidation,
Opt::try_parse_from(&["test", "NOPE"]).err().unwrap().kind()
);
}

Some files were not shown because too many files have changed in this diff Show more