diff --git a/CHANGELOG.md b/CHANGELOG.md index 542ab4d8..0f6dbf00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,365 +1,197 @@ -## Unreleased +# Change Log +All notable changes to this project will be documented in this file. -TODO: Structopt and traits -TODO: `YamlLoader` +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). - -## v3.0.0-rc.0 + +## [Unreleased] - ReleaseDate +**Note:** clap v3 has been in development for several years and has changed +hands multiple times. Unfortunately, our changelog might be incomplete, +whether in changes or their motivation. - -## v3.0.0-beta.5 (2021-10-18) +TBD: +- `AppSettings::ColoredHelp`: we are now relying solely on the `color` feature flag and `App::color` method +- Rename of `StructOpt` +- Rename of `structopt` -#### BREAKING CHANGES +### BREAKING CHANGES -* **Renamed Features** - * `unicode_help` to `unicode` to encompass more functionality -* **Gated behind features** - * `App::replace` is now gated behind `unstable-replace` -* **Removed `derive` requirement** - * `clap::ArgEnum` - * `clap::Args` - * `clap::FromArgMatches` - * `clap::IntoApp` - * `clap::Subcommand` -* **Renamed Traits** - * `clap::Clap` => `clap::Parser` -* **Renamed Methods** - * `App::generate_usage` => `App::render_usage` -* **Removed Settings** - * `AppSettings::DisableVersionForSubcommands` is now default behaviour - * `AppSettings::ColoredHelp`: we are now relying solely on the `color` feature flag and `App::color` method - * `AppSettings::StrictUtf8` is now default behaviour - * `AppSettings::AllowInvalidUtf8` in favor of `ArgSettings::AllowInvalidUtf8` - * `AppSettings::UnifiedHelpMessage` is now default behaviour - * `AppSettings::ColorAlways` in favor of `App::color` - * `AppSettings::ColorNever` in favor of `App::color` - * `AppSettings::ColorAuto` in favor of `App::color` -* **Removed methods** - * **App** - * `App::get_flags` - * `App::get_positionals_with_no_heading` - * `App::get_flags_with_no_heading` - * `App::get_opts_with_no_heading` - * `App::stop_custom_headings` in favor of `App:help_heading(None)` - * **Error** - * `Error::with_description` in favor of `App::error` - * **ArgEnum** - * `ArgEnum::as_arg` in favor of `ArgEnum::to_arg_value` - * **clap_generate::Generator** - * `Generator::all_subcommands` - * `Generator::find_subcommand_with_path` - * `Generator::subcommands` - * `Generator::shorts_and_visible_aliases` - * `Generator::longs_and_visible_aliases` - * `Generator::flags` -* **Removed** - * `ArgEnum::VARIANTS` in favor of `ArgEnum::value_variants` -* **Deprecated** - * `clap::clap_app!` in favor of other builders -* **Changed** - * `App::get_possible_values` returns `Option<&[ArgValue]>` now - * `RegexRef` is now an enum also allowing `RegexSet` to be used - * `clap_generate::Generator::file_name` and `clap_generate::Generator::generate` now take `&self` - * `clap_generate::generate` and `clap_generate::generate_to` now takes `Generator` as first argument +**From clap 2** -#### Features +Subtle changes (i.e. compiler won't catch): +- `AppSettings::UnifiedHelpMessage` is now default behaviour + - `{flags}` and `{unified}` will assert if present in `App::help_template` + - See [clap-rs/clap#2807](https://github.com/clap-rs/clap/issues/2807) +- `App::override_usage` no longer implies a leading `\t`, allowing multi lined usages +- `Arg::require_equals` no longer implies `ArgSettings::ForbidEmptyValues` ([#2233](https://github.com/clap-rs/clap/issues/2233)) +- `Arg::require_delimiter` no longer implies `ArgSettings::TakesValue` and `ArgSettings::UseValueDelimiter` ([#2233](https://github.com/clap-rs/clap/issues/2233)) +- `Arg::env`, `Arg::env_os`, `Arg::last`, `Arg::require_equals`, `Arg::allow_hyphen_values`, + `Arg::hide_possible_values`, `Arg::hide_default_value`, `Arg::hide_env_values`, + `Arg::case_insensitive` and `Arg::multiple_values` no longer imply `ArgSettings::TakesValue` ([#2233](https://github.com/clap-rs/clap/issues/2233)) +- Removed support for `{n}` as a newline in help text +- `ArgMatches::is_present` now longer checks subcommand names +- Some env variable values are now considered false for flags, not just "not-present" ([clap-rs/clap#2539](https://github.com/clap-rs/clap/issues/2539)) +- Changed `...`s meaning in usage parser. Before, it always meant `multiple` which is still true for `--option [val]...`. Now `[name]... --option [val]` results in `ArgSettings::MultipleOccurrences`. -* **Added** - * `clap::ArgValue` to denote information about possible values for args - * `clap::ColorChoice` to specify color setting for the app -* **Added Settings** - * `AppSettings::AllowInvalidUtf8ForExternalSubcommands` - * `AppSettings::Multicall` behind `unstable-multicall` feature - * `ArgSettings::AllowInvalidUtf8` -* **Added Methods** - * **ArgEnum** - * `ArgEnum::value_variants` - * `ArgEnum::to_arg_value` - * **App** - * `App::color` - * `App::error` - * `App::get_long_about` - * `App::get_help_heading` - * **Arg** - * `Arg::is_positional` -* Allow positionals to occur multiple times - - -## v3.0.0-beta.4 (2021-08-14) - -#### Minimum Required Rust -* As of this release, `clap` requires `rustc 1.54.0` or greater. - -#### BREAKING CHANGES - -Added `unicode_help`, `env` features. - -* **Gated behind `env`**: - * **Arg** - * `Arg::env` - * `Arg::env_os` - * `Arg::hide_env_values` - * **ArgSettings** - * `ArgSettings::HideEnvValues` -* **Removed Methods** - * **Arg** - * `Arg::settings` in favor of `Arg::setting(Setting1 | Setting2)` - * `Arg::multiple` in favour of `Arg::multiple_values` and `Arg::multiple_occurrences` -* **Renamed Settings** - * `AppSettings::DisableHelpFlags` => `AppSettings::DisableHelpFlag` - * `AppSettings::DisableVersion` => `AppSettings::DisableVersionFlag` - * `AppSettings::VersionlessSubcommands` => `AppSettings::DisableVersionForSubcommands` (changed again 3.0.0-beta.5) -* **Renamed Variants** - * **ErrorKind** - * `ErrorKind::MissingArgumentOrSubcommand` => `ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand` -* **Changed** - * Allowing empty values is the default again with `ArgSettings::AllowEmptyValues` changing to - `ArgSettings::ForbidEmptyValues` - * `AppSettings::GlobalVersion` renamed to `AppSettings::PropagateVersion` and it is not applied - globally anymore - * `Arg::env`, `Arg::env_os`, `Arg::last`, `Arg::require_equals`, `Arg::allow_hyphen_values`, - `Arg::hide_possible_values`, `Arg::hide_default_value`, `Arg::hide_env_values`, - `Arg::case_insensitive` and `Arg::multiple_values` does not set `ArgSettings::TakesValue` anymore - * `Arg::require_delimiter` does not set `ArgSettings::TakesValue` and `ArgSettings::UseValueDelimiter` - anymore - * `Arg::require_equals` does not disallow empty values anymore - * `Arg::default_value_if`, `Arg::default_value_if_os`, `Arg::default_value_ifs`, - `Arg::default_value_ifs_os` now takes the default value parameter as an option - * `Arg::index`, `Arg::number_of_values`, `Arg::min_values`, `Arg::max_values` now takes `usize` - * `Arg::value_delimiter` now accepts `char` instead of `&str` - * `ArgMatches::is_present` does not handle subcommand names anymore - * Some env var values are considered the same as env var not being present when the arg does not have - `ArgSettings::TakesValue` - * `clap_generate::generate_to` now returns `Result` - * `@group` in `clap_app!` now needs `:` instead of `=>` - * `app` and `arg` objects in `yaml` now allow unknown keys if `_has_metadata` is set - -#### Features - -* **Added** - * `clap_generate::Shell` - * `clap::Args` behind `derive` feature -* **Added Methods** - * **App** - * `App::license` - * **Arg** - * `Arg::get_long_about` - * `Arg::get_env` - * `Arg::get_default_values` - * `Arg::hide_env` - * `Arg::required_if_eq_all` - * `Arg::forbid_empty_values` - * `Arg::max_occurrences` - * **ArgMatches** - * `ArgMatches::grouped_values_of` - * **Macros** - * `crate_license!` - * **Error** - * `Error::print` -* **Added Settings** - * `AppSettings::UseLongFormatForHelpSubcommand` - * `AppSettings::IgnoreErrors` - * `AppSettings::InferLongArgs` - * `ArgSettings::HideEnv` - -#### Enhancements - -* Better completion scripts -* Multiple bug fixes, performance improvements and error message improvements - - - -## v3.0.0-beta.2 (2020-09-18) - -#### BREAKING CHANGES - -* **Removed** - * `From<&yaml_rust::yaml::Hash>` for `ArgGroup` - * **App** - * `App::write_version` in favor of `write!(w, App::render_version)` - * `App::write_long_version` in favor of `write!(w, App::render_long_version)` - * **Error** - * `Error::cause` in favor of `::to_string` - * **Macros** - * `_clap_count_exprs!` -* **Renamed Methods** - * **App** - * `App::set_term_width` => `App::term_width` - * **Arg** - * `Arg::from_yaml` => `Arg::from` - * `Arg::with_name` => `Arg::new` - * `Arg::required_if` => `Arg::required_if_eq` - * `Arg::required_ifs` => `Arg::required_if_eq_any` - * `Arg::required_unless` => `Arg::required_unless_present` - * `Arg::required_unless_one` => `Arg::required_unless_present_any` - * `Arg::required_unless_all` => `Arg::required_unless_present_all` - * **ArgGroup** - * `ArgGroup::from_yaml` => `ArgGroup::from` - * `ArgGroup::with_name` => `ArgGroup::new` -* **Renamed Variants** - * **ErrorKind** - * `ErrorKind::HelpDisplayed` => `ErrorKind::DisplayHelp` - * `ErrorKind::VersionDisplayed` => `ErrorKind::DisplayVersion` -* **Changed** - * `App::print_help` & `App::print_long_help` now return `std::io::Result` - * `App::write_help` & `App::write_long_help` now return `std::io::Result` - * `Error::info` now is of type `Vec` instead of `Option>` - * `ArgMatches::subcommand` now returns `Option<(&str, &ArgMatches)>` - * `short` in `#[clap()]` now accepts `char` instead of `&str` - -#### Features - -* Added support for subcommands that are flags (pacman style) -* Added `Indices` that is returned by `ArgMatches::indices_of` -* Added `@global_setting` for app's macro builder -* **Added Methods** - * **Arg** - * `Arg::default_missing_value` - * `Arg::default_missing_value_os` - * `Arg::default_missing_values` - * `Arg::default_missing_values_os` - * `Arg::short_alias` - * `Arg::short_aliases` - * `Arg::visible_short_alias` - * `Arg::visible_short_aliases` - * `Arg::value_hint` - * `Arg::validator_regex` (gated behind `regex` feature) - * **App** - * `App::subcommand_placeholder` - * `App::before_long_help` - * `App::after_long_help` -* TODO: List App::get_* methods - -#### Enhancements - -* `help_heading` defined on `Arg` now has higher priority than `App` -* Limited default text wrapping to 100 when `wrap_help` feature is not enabled -* Multiple bug fixes and error message improvements -* Size and Performance improvements - - - -## v3.0.0-beta.1 (2020-05-03) - -#### Minimum Required Rust - -* As of this release, `clap` requires `rustc 1.40.0` or greater. - -#### BREAKING CHANGES - -Added `std`, `cargo`, `derive` features. - -* **Gated behind `cargo`**: - * **Macros** - * `crate_name!` - * `crate_version!` - * `crate_authors!` - * `crate_description!` - * `app_from_crate!` - -* **Removed** - * `SubCommand` in favor of `App` - * `SubCommand::with_name` => `App::new` - * `SubCommand::from_yaml` => `App::from` - * `Shell` (changed again in 3.0.0-beta.4) - * **App** - * `App::with_defaults` - * `App::version_message` in favor of `App::mut_arg` - * `App::version_short` in favor of `App::mut_arg` - * `App::help_message` in favor of `App::mut_arg` - * `App::help_short` in favor of `App::mut_arg` - * `App::arg_from_usage` in favor of `App::arg` - * `App::args_from_usage` in favor of `App::args` - * `App::settings` in favor of `App::setting(Setting1 | Setting2)` - * `App::unset_settings` in favor of `App::unset_setting(Setting1 | Setting2)` - * `App::global_settings` in favor of `App::global_setting(Setting1 | Setting2)` - * `App::gen_completions` in favor of TODO: - * `App::gen_completions_to` in favor of TODO: - * **Arg** - * `Arg::empty_values` in favor of TODO: - * **ArgMatches** - * `ArgMatches::usage` in favor of `App::generate_usage` - * **Macros** - * `arg_enum!` in favor of `ArgEnum` derive macro. - * `value_t!` in favor of `ArgMatches::value_of_t` - * `value_t_or_exit!` in favor of `ArgMatches::value_of_t_or_exit` - * `values_t!` in favor of `ArgMatches::values_of_t` - * `values_t_or_exit!` in favor of `ArgMatches::values_of_t_or_exit` -* **Removed Settings** - * `AppSettings::PropagateGlobalValuesDown` - * `ArgSettings::Global` in favor of `Arg::global` method - * `ArgSettings::Multiple` in favor of `ArgSettings::MultipleValues` and `ArgSettings::MultipleOccurrences` -* **Renamed Methods** - * **App** - * `App::from_yaml` => `App::from` - * `App::arg_from_usage` => `App::arg` - * `App::help` => `App::override_help` - * `App::usage` => `App::override_usage` - * `App::template` => `App::help_template` - * `App::get_matches_safe` => `App::try_get_matches` - * `App::get_matches_from_safe` => `App::try_get_matches_from` - * `App::get_matches_from_safe_borrow` => `App::try_get_matches_from_mut` - * **Arg** - * `Arg::help` => `Arg::about` - * `Arg::from_usage` => `Arg::from` - * `Arg::set` => `Arg::setting` - * `Arg::unset` => `Arg::unset_setting` -* **Renamed Settings** - * `ArgSettings::CaseInsensitive` => `ArgSettings::IgnoreCase` - * `ArgSettings::AllowLeadingHyphen` => `ArgSettings::AllowHyphenValues` - * `ArgSettings::EmptyValues` => `ArgSettings::AllowEmptyValues` -* **Renamed Fields** - * `Error::message` => `Error::cause` -* **Changed** - * `App::write_help` is now a mutable reference instance method (takes `&mut self`) - * `Arg::short` now accepts `char` instead of `&str` - * `Arg::validator` now takes first argument as `Fn(&str) -> Result` instead of +Easier to catch changes: +- When using `no-default-features`, you now have to specify the `std` feature (reserved for future work) +- Gated env support behind `env` feature flag + - Impacts `Arg::env`, `Arg::env_os`, `Arg::hide_env_values`, `ArgSettings::HideEnvValues` + - See [clap-rs/clap#2694](https://github.com/clap-rs/clap/pull/2694) +- Gated crate information behind `cargo` feature flag + - Impacts `crate_name!`, `crate_version!`, `crate_authors!`, `crate_description!`, `app_from_crate!` +- `AppSettings::StrictUtf8` is now default behaviour and asserts if + `AppSettings::AllowInvalidUtf8ForExternalSubcommands` and + `ArgSettings::AllowInvalidUtf8` and `ArgMatches::value_of_os` aren't used + together + - `AppSettings::AllowInvalidUtf8` has been removed + - [clap-rs/clap#751](https://github.com/clap-rs/clap/issues/751) +- `Arg::short` and `Arg::value_delimiter` now take a `char` instead of a `&str` +- `ArgMatches` panics on unknown arguments +- Removed `VersionlessSubcommands`, making it the default (see [clap-rs/clap#2812](https://github.com/clap-rs/clap/issues/2812)) +- Completion generation has been split out into [clap_generate](./clap_generate). +- Removed `ArgSettings::EmptyValues` in favor of `ArgSettings::ForbidEmptyValues` +- Validator signatures have been loosed: + - `Arg::validator` now takes first argument as `Fn(&str) -> Result` instead of `Fn(String) -> Result<(), String>` - * `Arg::validator_os` now takes first argument as `Fn(&OsStr) -> Result` instead of + - `Arg::validator_os` now takes first argument as `Fn(&OsStr) -> Result` instead of `Fn(&OsStr) -> Result<(), OsString>` -* Removed support for `{n}` in help text -* In usage parser, for options `[name]... --option [val]` results in `ArgSettings::MultipleOccurrences` - but `--option [val]...` results in `ArgSettings::MultipleValues` *and* `ArgSettings::MultipleOccurrences`. - Before both resulted in the same thing. -* `App` and `Arg` now need only one lifetime -* Allowing empty values is no longer the default (changed again in 3.0.0-beta.4) -* `UseValueDelimiter` is no longer the default -* `App::override_usage` no longer implies `\t` which allows multi lined usages +- `Arg::value_name` now sets, rather than appends (see [clap-rs/clap#2634](https://github.com/clap-rs/clap/issues/2634)) +- Upgrade `yaml-rust` from 0.3 to 0.4 +- Replaced `ArgGroup::from(BTreeMap)` to `ArgGroup::from(yaml)` +- Replaced `ArgMatches::usage` with `App::generate_usage` +- Replaced `Arg::settings` with `Arg::setting(Setting1 | Setting2)` +- `App` and `Arg` now need only one lifetime +- Removed deprecated `App::with_defaults`, replaced with `app_from_crate` +- Removed deprecated `AppSettings::PropagateGlobalValuesDown` (now the default) +- Some `App` functions, like `App::write_help` now take `&mut self` instead of `&self` +- `Error::message` is now private, use `Error::to_string` +- `Arg::default_value_if`, `Arg::default_value_if_os`, `Arg::default_value_ifs`, + `Arg::default_value_ifs_os` now takes the default value parameter as an option ([clap-rs/clap#1406](https://github.com/clap-rs/clap/issues/1406)) +- Changed `App::print_help` & `App::print_long_help` to now return `std::io::Result` +- Changed `App::write_help` & `App::write_long_help` to now return `std::io::Result` +- Changed `Arg::index`, `Arg::number_of_values`, `Arg::min_values`, `Arg::max_values` to taking `usize` instead of u64 +- Changed `Error::info` to type `Vec` instead of `Option>` +- Changed `ArgMatches::subcommand` to now return `Option<(&str, &ArgMatches)>` +- Renamed `ErrorKind::MissingArgumentOrSubcommand` to `ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand` +- Renamed `ErrorKind::HelpDisplayed` to `ErrorKind::DisplayHelp` +- Renamed `ErrorKind::VersionDisplayed` to `ErrorKind::DisplayVersion` -#### Features +**From structopt 0.3.25** -* **Added Methods** - * **App** - * `App::replace` - * `App::get_matches_mut` - * `App::mut_arg` - * `App::unset_global_setting` - * `App::help_heading` - * `App::stop_custom_headings` - * **Arg** - * `Arg::exclusive` - * `Arg::multiple_values` - * `Arg::multiple_occurrences` - * `Arg::help_heading` - * `Arg::settings` (changed again in 3.0.0-beta.4) -* **Added Settings** - * `AppSettings::HelpRequired` - * `AppSettings::NoAutoHelp` - * `AppSettings::NoAutoVersion` - * `AppSettings::SubcommandPrecedenceOverArg` +- By default, the `App` isn't initialized with crate information anymore. Now opt-in via `#[clap(author)]`, `#[clap(about)]`, `#[clap(version)]` ([clap-rs/clap#3034](https://github.com/clap-rs/clap/issues/3034)) +- `#[clap(default_value)]` is replaced with `#[clap(default_value_t)]` ([clap-rs/clap#1694](https://github.com/clap-rs/clap/issues/1694)) +- Subcommands nested under subcommands now needs a `#[clap(subcommand)]` attribute ([clap-rs/clap#2587](https://github.com/clap-rs/clap/pull/2587)) +- `Vec<_>` and `Option>` have changed from `multiple` to `multiple_occurrences` -#### Enhancements +On top of the clap 2 changes -* Made `App::arg` and `App::args` more generic -* Improvements to `clap_app!` macro to make it support more wider use cases -* Colors now work correctly on Windows Console -* Multiple bug fixes and error message improvements -* Improvements to parsing logic and help messages +### Deprecations +While a lot of deprecations have been added to clean up the API (overloaded meaning of `Arg::multiple`) or make things more consistent, some particular highlights are: +- `clap_app!` has been deprecated in favor of the builder API with `arg!` ([clap-rs/clap#2835](https://github.com/clap-rs/clap/issues/2835)) +- `Arg::from_usage` has been deprecated in favor of `arg!` +- The YAML API has been deprecated in favor the builder or derive APIs - -## v2.33.0 (2019-04-06) +### Performance + +**From clap 2** + +- Split out non-default `unicode` feature flag for faster builds and smaller binaries for ASCII-only CLIs. +- Split out non-default `env` feature flag for faster builds and smaller binaries. + +### Features + +**From clap 2** + +- Integration of `structopt::StructOpt` via `clap::Parser` (requires `derive` feature flag) +- Custom help headings + - `App::help_heading` (apply to all future args) + - `Arg::help_heading` (apply to current arg) + - `App::subcommand_help_heading` along with `App::subcommand_value_name` (apply to subcommands) + - See [clap-rs/clap#805](https://github.com/clap-rs/clap/issues/805) + - `AppSettings::UnifiedHelpMessage` is now default behaviour ([clap-rs/clap#2807](https://github.com/clap-rs/clap/issues/2807)) +- Deriving of `ArgEnum` for generating `Arg::possible_values` (requires `derive` feature flag) +- Disable built-in help/version behavior with `AppSettings::NoAutoHelp` and `AppSettings::NoAutoVersion` +- Change an existing arg with new builder method `mut_arg` (particularly helpful for `--help` and `--version`) +- Provide extra context in long help messages (`--help`) with `before_long_help` and `after_long_help` ([clap-rs/clap#1903](https://github.com/clap-rs/clap/issues/1903)) +- Detect missing help descriptions via debug asserts by enabling `AppSettings::HelpExpected` +- Aliases for short flags ([clap-rs/clap#1896](https://github.com/clap-rs/clap/issues/1896)) +- Validate UTF-8 values, rather than panicing during `ArgMatches::value_of` thanks to `AppSettings::AllowInvalidUtf8ForExternalSubcommands` and `ArgSettings::AllowInvalidUtf8` + - Debug builds will assert when the `ArgMatches` calls do not match the UTF-8 setting. + - See [clap-rs/clap#751](https://github.com/clap-rs/clap/issues/751) +- `clap::PossibleValue` to allow + - Hiding ([clap-rs/clap#2756](https://github.com/clap-rs/clap/issues/2756)) + - Completion help for possible values for args ([clap-rs/clap#2731](https://github.com/clap-rs/clap/issues/2731)) +- Allow arguments to conflict with all others via `Arg::exclusive` ([clap-rs/clap#1583](https://github.com/clap-rs/clap/issues/1583)) +- Validate arguments with a regex (required `regex` feature flag) + - See [clap-rs/clap](https://github.com/clap-rs/clap/issues/1968) +- `Arg::default_missing_value` for cases like `--color[=]` ([clap-rs/clap#1587](https://github.com/clap-rs/clap/pull/1587)) +- `clap::App::color` / `clap::ColorChoice` to specify color setting for the app +- Custom error reporting with `App::error` +- Replace `Arg::multiple(bool)` with `Arg::multiple_values` / `Arg::multiple_occurrences` + - Positionals can be either +- Added support for flag subcommands like pacman ([clap-rs/clap#1361](https://github.com/clap-rs/clap/issues/1361)) +- Partial parsing via `AppSettings::IgnoreErrors` ([clap-rs/clap#1880](https://github.com/clap-rs/clap/issues/1880)) +- Enable `cmd help` to print long help (`--help` instead of `-h`) with `AppSettings::UseLongFormatForHelpSubcommand` ([clap-rs/clap#2435](https://github.com/clap-rs/clap/issues/2435)) +- Allow long arg abbreviations like we do with subcommands via `AppSettings::InferLongArgs` ([clap-rs/clap#2435](https://github.com/clap-rs/clap/issues/2435)) +- Detect subcommands among positional arguments with `AppSettings::SubcommandPrecedenceOverArg` +- Give completion scripts hints with `Arg::value_hint` ([clap-rs/clap#1793](https://github.com/clap-rs/clap/pull/1793)) +- Allow unsetting defaults with +- `Arg::default_value_if`, `Arg::default_value_if_os`, `Arg::default_value_ifs`, + `Arg::default_value_ifs_os` ([clap-rs/clap#1406](https://github.com/clap-rs/clap/issues/1406)) +- Interpret some env variable values as `false` for flags, in addition to "not-present" ([clap-rs/clap#2539](https://github.com/clap-rs/clap/issues/2539)) + - `n`, `no`, `f`, `false`, `off`, `0` +- Added `arg!` macro for creating an `Arg` from a compile-time usage parser + +- *(Experimental)* Busybox-like multi-call support + - See `AppSettings::Multicall` behind `unstable-multicall` feature flag + - See [clap-rs/clap#1120](https://github.com/clap-rs/clap/issues/1120) +- *(Experimental)* Alias an argument to anything group of arguments + - See `App::replace` behind `unstable-replace` feature flag + - See [clap-rs#1603](https://github.com/clap-rs/clap/issues/1603) +- *(Experimental)* Grouping of multiple values within multiple occurrences + - See `ArgMatches::grouped_values_of` behind `unstable-grouped` feature flag + - See [clap-rs/clap#1026](https://github.com/clap-rs/clap/issues/1026) + +**From structopt 0.3.25** + +- Allow defaulting with native types via new `default_value_t [= ]` attribute ([clap-rs/clap#1694](https://github.com/clap-rs/clap/issues/1694)) +- New `update` API +- New `arg_enum` attribute for integrating with `ArgEnum` trait + +On top of the clap 2 changes + +### Fixes + +**From clap 2** + +- Correctly handle colored output on Windows +- Only generate version flags when `App::version`, `App::long_version` are set + (see [clap-rs/clap#2812](https://github.com/clap-rs/clap/issues/2812)) +- General completion script improvements +- Limited default help text wrapping to 100 when `wrap_help` feature is not enabled +- Be more specific than `Arg::multiple` with `Arg::multiple_values` and `Arg::multiple_occurrences` +- `app_from_crate!` defaults to separating multiple authors with `", "` +- Ensure all examples work +- `IgnoreCase` is now unicode aware (requires `unicode` feature flag) +- Always respect `ColorChoice::Never`, even if that means we skip colors in some cases +- `ArgMatches` panics on unknown arguments + +**From structopt 0.3.25** + +- Support `SubcommandsNegateReqs` by allowing required `Option<_>`s ([clap-rs/clap#2255](https://github.com/clap-rs/clap/issues/2255)) +- Infer `AllowInvalidUtf8` based on parser ([clap-rs/clap#751](https://github.com/clap-rs/clap/issues/2255)) + +On top of the clap 2 changes + +### Minimum Required Rust + +- As of this release, `clap` requires `rustc 1.54.0` or greater. + +## [v2.33.0] (2019-04-06) #### New Sponsor @@ -399,7 +231,6 @@ Added `std`, `cargo`, `derive` features. * As of this release, `clap` requires `rustc 1.31.0` or greater. - ## v2.32.0 (2018-06-26) #### Minimum Required Rust @@ -427,7 +258,6 @@ Added `std`, `cargo`, `derive` features. - ### v2.31.2 (2018-03-19) #### Bug Fixes @@ -439,7 +269,6 @@ Added `std`, `cargo`, `derive` features. * Fixes some typos in the `README.md` ([c8e685d7](https://github.com/kbknapp/clap-rs/commit/c8e685d76adee2a3cc06cac6952ffcf6f9548089)) - ### v2.31.1 (2018-03-06) @@ -448,7 +277,6 @@ Added `std`, `cargo`, `derive` features. * **AllowMissingPositional:** improves the ability of AllowMissingPositional to allow 'skipping' to the last positional arg with '--' ([df20e6e2](https://github.com/kbknapp/clap-rs/commit/df20e6e24b4e782be0b423b484b9798e3e2efe2f)) - ## v2.31.0 (2018-03-04) @@ -473,7 +301,6 @@ Added `std`, `cargo`, `derive` features. * Uses the short help tool-tip for PowerShell completion scripts ([ecda22ce](https://github.com/kbknapp/clap-rs/commit/ecda22ce7210ce56d7b2d1a5445dd1b8a2959656)) - ## v2.30.0 (2018-02-13) #### Bug Fixes @@ -487,7 +314,6 @@ Added `std`, `cargo`, `derive` features. * **Help Message:** changes the `[values: foo bar baz]` array to `[possible values: foo bar baz]` for consistency with the API ([414707e4e97](https://github.com/kbknapp/clap-rs/pull/1176/commits/414707e4e979d07bfe555247e5d130c546673708), closes [#1160](https://github.com/kbknapp/clap-rs/issues/1160)) - ### v2.29.4 (2018-02-06) @@ -497,7 +323,6 @@ Added `std`, `cargo`, `derive` features. - ### v2.29.3 (2018-02-05) @@ -516,7 +341,6 @@ Added `std`, `cargo`, `derive` features. - ## v2.29.2 (2018-01-16) @@ -537,7 +361,6 @@ Added `std`, `cargo`, `derive` features. - ### 2.29.1 (2018-01-09) @@ -558,7 +381,6 @@ Added `std`, `cargo`, `derive` features. * **completions/zsh.rs:** Fix completion of long option values ([46365cf8](https://github.com/kbknapp/clap-rs/commit/46365cf8be5331ba04c895eb183e2f230b5aad51)) - ## 2.29.0 (2017-12-02) @@ -568,7 +390,6 @@ Added `std`, `cargo`, `derive` features. - ## 2.28.0 (2017-11-28) The minimum required Rust is now 1.20. This was done to start using bitflags 1.0 and having >1.0 deps is a *very good* thing! @@ -601,7 +422,6 @@ The minimum required Rust is now 1.20. This was done to start using bitflags 1.0 - ## v2.27.1 (2017-10-24) @@ -609,7 +429,6 @@ The minimum required Rust is now 1.20. This was done to start using bitflags 1.0 * Adds `term_size` as an optional dependency (with feature `wrap_help`) to fix compile bug - ## v2.27.0 (2017-10-24) ** This release raises the minimum required version of Rust to 1.18 ** @@ -655,7 +474,6 @@ See the commit [0c223f54](https://github.com/kbknapp/clap-rs/commit/0c223f54ed46 - ### v2.26.2 (2017-09-14) @@ -669,7 +487,6 @@ See the commit [0c223f54](https://github.com/kbknapp/clap-rs/commit/0c223f54ed46 - ### v2.26.1 (2017-09-14) @@ -687,7 +504,6 @@ See the commit [0c223f54](https://github.com/kbknapp/clap-rs/commit/0c223f54ed46 - ## v2.26.0 (2017-07-29) Minimum version of Rust is now v1.13.0 (Stable) @@ -705,7 +521,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.25.1 (2017-07-21) #### Improvements @@ -716,7 +531,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * Various documentation typos and grammar fixes - ### v2.25.0 (2017-06-20) @@ -743,7 +557,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.24.2 (2017-05-15) @@ -761,7 +574,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.24.0 (2017-05-07) @@ -773,7 +585,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v2.24.0 (2017-05-05) @@ -787,7 +598,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **arg_matches.rs:** Added a Default implementation for Values and OsValues iterators. ([0a4384e3](https://github.com/kbknapp/clap-rs/commit/0a4384e350eed74c2a4dc8964c203f21ac64897f)) - ### v2.23.2 (2017-04-19) @@ -804,7 +614,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * Fix a typo the minimum rust version required ([71dabba3](https://github.com/kbknapp/clap-rs/commit/71dabba3ea0a17c88b0e2199c9d99f0acbf3bc17)) - ### v2.23.1 (2017-04-05) @@ -813,7 +622,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * fixes a missing newline character in the autogenerated help and version messages in some instances ([5ae9007d](https://github.com/kbknapp/clap-rs/commit/5ae9007d984ae94ae2752df51bcbaeb0ec89bc15)) - ## v2.23.0 (2017-04-05) @@ -844,7 +652,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.22.2 (2017-03-30) @@ -854,7 +661,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.22.1 (2017-03-24) @@ -862,7 +668,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **usage:** fixes a big regression with custom usage strings ([2c41caba](https://github.com/kbknapp/clap-rs/commit/2c41caba3c7d723a2894e315d04da796b0e97759)) - ## v2.22.0 (2017-03-23) #### API Additions @@ -871,7 +676,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Arg::hide_default_value:** adds ability to hide the default value of an argument from the help string ([89e6ea86](https://github.com/kbknapp/clap-rs/commit/89e6ea861e16a1ad56757ca12f6b32d02253e44a), closes [#902](https://github.com/kbknapp/clap-rs/issues/902)) - ### v2.21.3 (2017-03-23) #### Bug Fixes @@ -879,7 +683,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **yaml:** adds support for loading author info from yaml ([e04c390c](https://github.com/kbknapp/clap-rs/commit/e04c390c597a55fa27e724050342f16c42f1c5c9)) - ### v2.21.2 (2017-03-17) @@ -895,7 +698,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.21.1 (2017-03-12) @@ -906,7 +708,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v2.21.0 (2017-03-09) #### Performance @@ -949,7 +750,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.20.5 (2017-02-18) @@ -958,7 +758,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **clap_app!:** fixes a critical bug of a missing fragment specifier when using `!property` style tags. ([5635c1f94](https://github.com/kbknapp/clap-rs/commit/5e9b9cf4dd80fa66a624374fd04e6545635c1f94)) - ### v2.20.4 (2017-02-15) @@ -971,7 +770,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * Fix examples link in CONTRIBUTING.md ([60cf875d](https://github.com/kbknapp/clap-rs/commit/60cf875d67a252e19bb85054be57696fac2c57a1)) - ### v2.20.3 (2017-02-03) @@ -989,7 +787,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.20.2 (2017-02-03) #### Bug Fixes @@ -1001,7 +798,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * adds ArgGroup::multiple to the supported YAML fields for building ArgGroups from YAML ([d8590037](https://github.com/kbknapp/clap-rs/commit/d8590037ce07dafd8cd5b26928aa4a9fd3018288), closes [#840](https://github.com/kbknapp/clap-rs/issues/840)) - ### v2.20.1 (2017-01-31) #### Bug Fixes @@ -1019,7 +815,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * fix link from app_from_crate! to crate_authors! (#822) ([5b29be9b](https://github.com/kbknapp/clap-rs/commit/5b29be9b073330ab1f7227cdd19fe4aab39d5dcb)) * fix spelling of "guaranteed" ([4f30a65b](https://github.com/kbknapp/clap-rs/commit/4f30a65b9c03eb09607eb91a929a6396637dc105)) - #### New Settings @@ -1073,7 +868,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **README.md:** fix some typos ([f22c21b4](https://github.com/kbknapp/clap-rs/commit/f22c21b422d5b287d1a1ac183a379ee02eebf54f)) * **src/app/mod.rs:** fix some typos ([5c9b0d47](https://github.com/kbknapp/clap-rs/commit/5c9b0d47ca78dea285c5b9dec79063d24c3e451a)) - ### v2.19.3 (2016-12-28) @@ -1083,7 +877,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.19.2 (2016-12-08) #### Bug Fixes @@ -1097,7 +890,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.19.1 (2016-12-01) @@ -1110,7 +902,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Bash Completion:** allows bash completion to fall back to traditional bash completion upon no matching completing function ([b1b16d56](https://github.com/kbknapp/clap-rs/commit/b1b16d56d8fddf819bdbe24b3724bb6a9f3fa613))) - ## v2.19.0 (2016-11-21) #### Features @@ -1134,7 +925,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Compatibility Policy:** adds an official compatibility policy to ([760d66dc](https://github.com/kbknapp/clap-rs/commit/760d66dc17310b357f257776624151da933cd25d), closes [#740](https://github.com/kbknapp/clap-rs/issues/740)) * **Contributing:** updates the readme to improve the readability and contributing sections ([eb51316c](https://github.com/kbknapp/clap-rs/commit/eb51316cdfdc7258d287ba13b67ef2f42bd2b8f6)) - ## v2.18.0 (2016-11-05) @@ -1144,7 +934,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.17.1 (2016-11-02) @@ -1154,7 +943,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v2.17.0 (2016-11-01) @@ -1164,7 +952,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.16.4 (2016-10-31) @@ -1184,7 +971,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.16.3 (2016-10-28) @@ -1195,7 +981,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.16.2 (2016-10-25) @@ -1204,7 +989,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Fish Completions:** fixes a bug where single quotes are not escaped ([780b4a18](https://github.com/kbknapp/clap-rs/commit/780b4a18281b6f7f7071e1b9db2290fae653c406), closes [#704](https://github.com/kbknapp/clap-rs/issues/704)) - ### v2.16.1 (2016-10-24) @@ -1214,7 +998,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v2.16.0 (2016-10-23) @@ -1224,7 +1007,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v2.15.0 (2016-10-21) @@ -1237,7 +1019,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **app/settings.rs:** moves variants to roughly alphabetical order ([9ed4d4d7](https://github.com/kbknapp/clap-rs/commit/9ed4d4d7957a23357aef60081e45639ab9e3905f)) - ### v2.14.1 (2016-10-20) @@ -1264,7 +1045,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v2.14.0 (2016-10-05) @@ -1282,7 +1062,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * typo ([bac417fa](https://github.com/kbknapp/clap-rs/commit/bac417fa1cea3d32308334c7cccfcf54546cd9d8)) - ## v2.13.0 (2016-09-18) @@ -1298,7 +1077,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.12.1 (2016-09-13) @@ -1308,7 +1086,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v2.12.0 (2016-09-13) @@ -1341,7 +1118,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.11.3 (2016-09-07) @@ -1359,7 +1135,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.11.2 (2016-09-06) #### Improvements @@ -1367,7 +1142,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Help Wrapping:** makes some minor changes to when next line help is automatically used ([5658b117](https://github.com/kbknapp/clap-rs/commit/5658b117aec3e03adff9c8c52a4c4bc1fcb4e1ff)) - ### v2.11.1 (2016-09-05) @@ -1385,7 +1159,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.11.0 (2016-08-28) @@ -1409,7 +1182,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.10.4 (2016-08-25) @@ -1419,7 +1191,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.10.3 (2016-08-25) #### Features @@ -1436,7 +1207,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.10.2 (2016-08-22) @@ -1446,7 +1216,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.10.1 (2016-08-21) @@ -1460,7 +1229,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v2.10.0 (2016-07-29) @@ -1482,7 +1250,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### 2.9.3 (2016-07-24) @@ -1497,7 +1264,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Settings:** Add unset_setting and unset_settings fns to App (#598) ([0ceba231](https://github.com/kbknapp/clap-rs/commit/0ceba231c6767cd6d88fdb1feeeea41deadf77ff), closes [#590](https://github.com/kbknapp/clap-rs/issues/590)) - ### 2.9.2 (2016-07-03) @@ -1511,7 +1277,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### 2.9.1 (2016-07-02) @@ -1520,7 +1285,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Completions:** allows multiple completions to be built by namespacing with bin name ([57484b2d](https://github.com/kbknapp/clap-rs/commit/57484b2daeaac01c1026e8c84efc8bf099e0eb31)) - ## v2.9.0 (2016-07-01) @@ -1542,7 +1306,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **AllowLeadingHyphen:** fixes an issue where isn't ignored like it should be with this setting ([96c24c9a](https://github.com/kbknapp/clap-rs/commit/96c24c9a8fa1f85e06138d3cdd133e51659e19d2), closes [#558](https://github.com/kbknapp/clap-rs/issues/558)) - ## v2.8.0 (2016-06-30) @@ -1560,7 +1323,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.7.1 (2016-06-29) @@ -1572,7 +1334,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v2.7.0 (2016-06-28) @@ -1600,7 +1361,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v2.6.0 (2016-06-14) @@ -1633,7 +1393,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.5.2 (2016-05-31) @@ -1654,7 +1413,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * inter-links all types and pages ([3312893d](https://github.com/kbknapp/clap-rs/commit/3312893ddaef3f44d68d8d26ed3d08010be50d97), closes [#505](https://github.com/kbknapp/clap-rs/issues/505)) * makes all publicly available types viewable in docs ([52ca6505](https://github.com/kbknapp/clap-rs/commit/52ca6505b4fec7b5c2d53d160c072d395eb21da6)) - ### v2.5.1 (2016-05-11) @@ -1662,7 +1420,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Subcommand Aliases**: fixes lifetime issue when setting multiple aliases at once ([ac42f6cf0](https://github.com/kbknapp/clap-rs/commit/ac42f6cf0de6c4920f703807d63061803930b18d)) - ## v2.5.0 (2016-05-10) @@ -1675,7 +1432,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **SubCommands:** adds support for subcommand aliases ([66b4dea6](https://github.com/kbknapp/clap-rs/commit/66b4dea65c44d8f77ff522238a9237aed1bcab6d), closes [#469](https://github.com/kbknapp/clap-rs/issues/469)) - ### v2.4.3 (2016-05-10) @@ -1692,17 +1448,14 @@ Minimum version of Rust is now v1.13.0 (Stable) * moves positionals to standard <> formatting ([03dfe5ce](https://github.com/kbknapp/clap-rs/commit/03dfe5ceff1d63f172788ff688567ddad9fe119b)) * default help subcommand string has been shortened ([5b7fe8e4](https://github.com/kbknapp/clap-rs/commit/5b7fe8e4161e43ab19e2e5fcf55fbe46791134e9), closes [#494](https://github.com/kbknapp/clap-rs/issues/494)) - ### v2.4.3 (2016-05-10) * Ghost Release - ### v2.4.3 (2016-05-10) * Ghost Release - ## v2.4.0 (2016-05-02) @@ -1721,7 +1474,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Required Args:** fixes issue where missing required args are sometimes duplicated in error messages ([3beebd81](https://github.com/kbknapp/clap-rs/commit/3beebd81e7bc2faa4115ac109cf570e512c5477f), closes [#492](https://github.com/kbknapp/clap-rs/issues/492)) - ## v2.3.0 (2016-04-18) @@ -1746,7 +1498,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **HELP:** Adjust Help to semantic changes introduced in 6933b84 ([8d23806b](https://github.com/kbknapp/clap-rs/commit/8d23806bd67530ad412c34a1dcdcb1435555573d)) - ### v2.2.6 (2016-04-11) #### Bug Fixes @@ -1754,7 +1505,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Arg Groups**: fixes bug where arg name isn't printed properly ([3019a685](https://github.com/kbknapp/clap-rs/commit/3019a685eee747ccbe6be09ad5dddce0b1d1d4db), closes [#476](https://github.com/kbknapp/clap-rs/issues/476)) - ### v2.2.5 (2016-04-03) @@ -1764,7 +1514,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Help Message:** fixes bug where arg name is printed twice ([71acf1d5](https://github.com/kbknapp/clap-rs/commit/71acf1d576946658b8bbdb5ae79e6716c43a030f), closes [#472](https://github.com/kbknapp/clap-rs/issues/472)) - ### v2.2.4 (2016-03-30) @@ -1775,7 +1524,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v2.2.3 (2016-03-28) @@ -1783,7 +1531,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Help Subcommand:** fixes issue where help and version flags weren't properly displayed ([205b07bf](https://github.com/kbknapp/clap-rs/commit/205b07bf2e6547851f1290f8cd6b169145e144f1), closes [#466](https://github.com/kbknapp/clap-rs/issues/466)) - ### v2.2.2 (2016-03-27) @@ -1793,7 +1540,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Usage Strings:** fixes small bug where -- would appear needlessly in usage strings ([6933b849](https://github.com/kbknapp/clap-rs/commit/6933b8491c2a7e28cdb61b47dcf10caf33c2f78a), closes [#461](https://github.com/kbknapp/clap-rs/issues/461)) - ### 2.2.1 (2016-03-16) @@ -1806,7 +1552,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Help Message:** fixes a bug where small terminal sizes causing a loop ([1d73b035](https://github.com/kbknapp/clap-rs/commit/1d73b0355236923aeaf6799abc759762ded7e1d0), closes [#453](https://github.com/kbknapp/clap-rs/issues/453)) - ## v2.2.0 (2016-03-15) @@ -1826,7 +1571,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Groups:** explains required ArgGroups better ([4ff0205b](https://github.com/kbknapp/clap-rs/commit/4ff0205b85a45151b59bbaf090a89df13438380f), closes [#439](https://github.com/kbknapp/clap-rs/issues/439)) - ### v2.1.2 (2016-02-24) #### Bug Fixes @@ -1834,7 +1578,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Nightly:** fixes failing nightly build ([d752c170](https://github.com/kbknapp/clap-rs/commit/d752c17029598b19037710f204b7943f0830ae75), closes [#434](https://github.com/kbknapp/clap-rs/issues/434)) - ### v2.1.1 (2016-02-19) @@ -1848,7 +1591,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Help:** adds setting for next line help by arg ([066df748](https://github.com/kbknapp/clap-rs/commit/066df7486e684cf50a8479a356a12ba972c34ce1), closes [#427](https://github.com/kbknapp/clap-rs/issues/427)) - ## v2.1.0 (2016-02-10) @@ -1861,7 +1603,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Default Values:** adds better examples and notes for default values ([9facd74f](https://github.com/kbknapp/clap-rs/commit/9facd74f843ef3807c5d35259558a344e6c25905)) - ### v2.0.6 (2016-02-09) @@ -1870,7 +1611,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Positional Arguments:** now displays value name if appropriate ([f0a99916](https://github.com/kbknapp/clap-rs/commit/f0a99916c59ce675515c6dcdfe9a40b130510908), closes [#420](https://github.com/kbknapp/clap-rs/issues/420)) - ### v2.0.5 (2016-02-05) @@ -1879,7 +1619,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Multiple Values:** fixes bug where number_of_values wasn't respected ([72c387da](https://github.com/kbknapp/clap-rs/commit/72c387da0bb8a6f526f863770f08bb8ca0d3de03)) - ### v2.0.4 (2016-02-04) @@ -1889,7 +1628,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * Stop lonely hyphens from causing panic ([85b11468](https://github.com/kbknapp/clap-rs/commit/85b11468b0189d5cc15f1cfac5db40d17a0077dc), closes [#410](https://github.com/kbknapp/clap-rs/issues/410)) * **AppSettings:** fixes bug where subcmds didn't receive parent ver ([a62e4527](https://github.com/kbknapp/clap-rs/commit/a62e452754b3b0e3ac9a15aa8b5330636229ead1)) - ### v2.0.3 (2016-02-02) @@ -1907,7 +1645,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **value_t_or_exit:** fixes typo which causes value_t_or_exit to return a Result ([ee96baff](https://github.com/kbknapp/clap-rs/commit/ee96baffd306cb8d20ddc5575cf739bb1a6354e8)) - ### v2.0.2 (2016-01-31) @@ -1922,7 +1659,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * **Usage Parser:** fixes a bug where literal single quotes weren't allowed in help strings ([0bcc7120](https://github.com/kbknapp/clap-rs/commit/0bcc71206478074769e311479b34a9f74fe80f5c), closes [#406](https://github.com/kbknapp/clap-rs/issues/406)) - ### v2.0.1 (2016-01-30) @@ -1931,7 +1667,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * fixes cargo features to NOT require nightly with unstable features ([dcbcc60c](https://github.com/kbknapp/clap-rs/commit/dcbcc60c9ba17894be636472ea4b07a82d86a9db), closes [#402](https://github.com/kbknapp/clap-rs/issues/402)) - ## v2.0.0 (2016-01-28) @@ -2008,7 +1743,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * Using the `clap_app!` macro requires compiling with the `unstable` feature because the syntax could change slightly in the future - ### v1.5.5 (2016-01-04) @@ -2019,7 +1753,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * fixes an intentional panic issue discovered via clippy ([ea83a3d4](https://github.com/kbknapp/clap-rs/commit/ea83a3d421ea8856d4cac763942834d108b71406)) - ### v1.5.4 (2015-12-18) @@ -2038,7 +1771,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * ArgRequiredElseHelp setting now takes precedence over missing required args ([faad83fb](https://github.com/kbknapp/clap-rs/commit/faad83fbef6752f3093b6e98fca09a9449b830f4), closes [#362](https://github.com/kbknapp/clap-rs/issues/362)) - ### v1.5.3 (2015-11-20) @@ -2049,7 +1781,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.5.2 (2015-11-14) @@ -2059,7 +1790,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.5.1 (2015-11-13) @@ -2069,7 +1799,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v1.5.0 (2015-11-13) @@ -2099,7 +1828,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.4.7 (2015-11-03) @@ -2114,7 +1842,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.4.6 (2015-10-29) @@ -2137,7 +1864,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.4.5 (2015-10-06) @@ -2147,7 +1873,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.4.4 (2015-10-06) @@ -2174,7 +1899,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.4.3 (2015-09-30) @@ -2193,7 +1917,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.4.2 (2015-09-23) @@ -2203,7 +1926,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.4.1 (2015-09-22) @@ -2228,7 +1950,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v1.4.0 (2015-09-09) @@ -2241,7 +1962,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.3.2 (2015-09-08) @@ -2261,7 +1981,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.3.1 (2015-09-04) @@ -2276,7 +1995,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v1.3.0 (2015-09-01) @@ -2302,7 +2020,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.2.5 (2015-08-27) @@ -2317,7 +2034,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.2.4 (2015-08-26) @@ -2327,7 +2043,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.2.3 (2015-08-24) @@ -2337,7 +2052,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.2.2 (2015-08-23) @@ -2348,7 +2062,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.2.1 (2015-08-20) @@ -2372,7 +2085,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.2.0 (2015-08-15) @@ -2397,7 +2109,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.1.6 (2015-08-01) @@ -2407,14 +2118,12 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.1.5 (2015-07-29) #### Performance * removes some unneeded allocations ([93e915df](https://github.com/kbknapp/clap-rs/commit/93e915dfe300f7b7d6209ca93323c6a46f89a8c1)) - ### v1.1.4 (2015-07-20) @@ -2429,7 +2138,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.1.3 (2015-07-18) @@ -2443,7 +2151,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.1.2 (2015-07-17) @@ -2453,7 +2160,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v1.1.1 (2015-07-17) @@ -2463,7 +2169,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v1.1.0 (2015-07-16) @@ -2488,7 +2193,6 @@ Minimum version of Rust is now v1.13.0 (Stable) * fix incorrect code example for `App::subcommand_required` ([8889689d](https://github.com/kbknapp/clap-rs/commit/8889689dc6336ccc45b2c9f2cf8e2e483a639e93)) - ### v1.0.3 (2015-07-11) @@ -2502,7 +2206,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.0.2 (2015-07-09) @@ -2512,7 +2215,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v1.0.1 (2015-07-08) @@ -2522,7 +2224,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v1.0.0 (2015-07-08) @@ -2537,7 +2238,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v1.0.0-beta (2015-06-30) @@ -2556,7 +2256,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.11.0 (2015-06-17) - BREAKING CHANGE @@ -2570,7 +2269,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v0.10.5 (2015-06-06) @@ -2580,7 +2278,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v0.10.4 (2015-06-06) @@ -2590,7 +2287,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v0.10.3 (2015-05-31) @@ -2600,7 +2296,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v0.10.2 (2015-05-30) @@ -2614,7 +2309,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ### v0.10.1 (2015-05-26) @@ -2624,7 +2318,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.10.0 (2015-05-23) @@ -2646,7 +2339,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.9.2 (2015-05-20) @@ -2656,7 +2348,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.9.1 (2015-05-18) @@ -2666,7 +2357,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.9.0 (2015-05-17) @@ -2683,7 +2373,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.8.6 (2015-05-17) @@ -2693,7 +2382,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.8.5 (2015-05-15) @@ -2709,7 +2397,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.8.4 (2015-05-12) @@ -2719,7 +2406,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.8.3 (2015-05-10) @@ -2733,7 +2419,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.8.2 (2015-05-08) @@ -2743,7 +2428,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.8.1 (2015-05-06) @@ -2758,7 +2442,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.8.0 (2015-05-06) @@ -2792,7 +2475,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.7.6 (2015-05-05) @@ -2815,7 +2497,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.7.5 (2015-05-04) @@ -2825,7 +2506,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.7.4 (2015-05-03) @@ -2835,7 +2515,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.7.3 (2015-05-03) @@ -2850,7 +2529,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.7.2 (2015-05-03) @@ -2860,7 +2538,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.7.1 (2015-05-01) @@ -2870,7 +2547,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.7.0 (2015-04-30) - BREAKING CHANGE @@ -2889,7 +2565,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.6.9 (2015-04-29) @@ -2899,7 +2574,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## 0.6.8 (2015-04-27) @@ -2914,7 +2588,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.6.7 (2015-04-22) @@ -2928,7 +2601,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.6.6 (2015-04-19) @@ -2942,7 +2614,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.6.5 (2015-04-19) @@ -2952,7 +2623,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.6.4 (2015-04-17) @@ -2962,7 +2632,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.6.3 (2015-04-16) @@ -2972,7 +2641,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.6.2 (2015-04-14) @@ -2986,7 +2654,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.6.1 (2015-04-13) @@ -2996,7 +2663,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.6.0 (2015-04-13) @@ -3011,7 +2677,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.14 (2015-04-10) @@ -3027,7 +2692,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.13 (2015-04-09) @@ -3038,7 +2702,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.12 (2015-04-08) @@ -3048,7 +2711,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.11 (2015-04-08) @@ -3058,7 +2720,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.10 (2015-04-08) @@ -3068,7 +2729,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.9 (2015-04-08) @@ -3080,7 +2740,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.8 (2015-04-08) @@ -3095,7 +2754,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.7 (2015-04-08) @@ -3105,7 +2763,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.6 (2015-04-08) @@ -3115,7 +2772,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.5 (2015-04-08) @@ -3125,7 +2781,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.4 (2015-04-08) @@ -3135,7 +2790,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.3 (2015-04-08) @@ -3147,7 +2801,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.2 (2015-04-08) @@ -3157,7 +2810,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.1 (2015-04-08) @@ -3167,7 +2819,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.5.0 (2015-04-08) @@ -3177,7 +2828,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.4.18 (2015-04-08) @@ -3191,7 +2841,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.4.17 (2015-04-08) @@ -3201,7 +2850,6 @@ Minimum version of Rust is now v1.13.0 (Stable) - ## v0.4.16 (2015-04-08) @@ -3213,3 +2861,7 @@ Minimum version of Rust is now v1.13.0 (Stable) #### Features * **arg** allow lifetimes other than 'static in arguments ([9e8c1fb9](https://github.com/kbknapp/clap-rs/commit/9e8c1fb9406f8448873ca58bab07fe905f1551e5)) + + +[Unreleased]: https://github.com/clap-rs/clap/compare/v2.33.0...HEAD +[2.32.0]: https://github.com/clap-rs/clap/compare/v2.32.0...v2.33.0 diff --git a/src/build/app/debug_asserts.rs b/src/build/app/debug_asserts.rs index 805bb8d7..48149286 100644 --- a/src/build/app/debug_asserts.rs +++ b/src/build/app/debug_asserts.rs @@ -210,7 +210,7 @@ pub(crate) fn assert_app(app: &App) { } assert!( - !(arg.is_set(ArgSettings::Required) && arg.global), + !(arg.is_set(ArgSettings::Required) && arg.get_global()), "Global arguments cannot be required.\n\n\t'{}' is marked as both global and required", arg.name ); diff --git a/src/build/app/mod.rs b/src/build/app/mod.rs index 5096850d..af7f30a1 100644 --- a/src/build/app/mod.rs +++ b/src/build/app/mod.rs @@ -290,7 +290,7 @@ impl<'help> App<'help> { /// this `App`. pub fn get_arg_conflicts_with(&self, arg: &Arg) -> Vec<&Arg<'help>> // FIXME: This could probably have been an iterator { - if arg.global { + if arg.get_global() { self.get_global_arg_conflicts_with(arg) } else { arg.blacklist @@ -422,34 +422,26 @@ impl<'help> App<'help> { ) }; - let mut has_metadata = false; - for (k, v) in yaml { a = match k.as_str().expect("App fields must be strings") { - "_has_metadata" => { - has_metadata = true; - a - } - "bin_name" => yaml_to_str!(a, v, bin_name), "version" => yaml_to_str!(a, v, version), "long_version" => yaml_to_str!(a, v, long_version), "author" => yaml_to_str!(a, v, author), + "bin_name" => yaml_to_str!(a, v, bin_name), "about" => yaml_to_str!(a, v, about), + "long_about" => yaml_to_str!(a, v, long_about), "before_help" => yaml_to_str!(a, v, before_help), - "before_long_help" => yaml_to_str!(a, v, before_long_help), "after_help" => yaml_to_str!(a, v, after_help), - "after_long_help" => yaml_to_str!(a, v, after_long_help), - "help_heading" => yaml_to_str!(a, v, help_heading), - "help_template" => yaml_to_str!(a, v, help_template), - "override_help" => yaml_to_str!(a, v, override_help), - "override_usage" => yaml_to_str!(a, v, override_usage), + "template" => yaml_to_str!(a, v, help_template), + "usage" => yaml_to_str!(a, v, override_usage), + "help" => yaml_to_str!(a, v, override_help), + "help_message" => yaml_to_str!(a, v, help_message), + "version_message" => yaml_to_str!(a, v, version_message), "alias" => yaml_to_str!(a, v, alias), "aliases" => yaml_vec_or_str!(a, v, alias), "visible_alias" => yaml_to_str!(a, v, visible_alias), "visible_aliases" => yaml_vec_or_str!(a, v, visible_alias), "display_order" => yaml_to_usize!(a, v, display_order), - "term_width" => yaml_to_usize!(a, v, term_width), - "max_term_width" => yaml_to_usize!(a, v, max_term_width), "args" => { if let Some(vec) = v.as_vec() { for arg_yaml in vec { @@ -486,13 +478,7 @@ impl<'help> App<'help> { "global_setting" | "global_settings" => { yaml_to_setting!(a, v, global_setting, AppSettings, "AppSetting", err) } - "name" => continue, - s => { - if !has_metadata { - panic!("Unknown setting '{}' in YAML file for {}", s, err) - } - continue; - } + _ => a, } } @@ -869,6 +855,30 @@ impl<'help> App<'help> { self.override_help(help) } + /// Deprecated, replaced with [`App::mut_arg`] + #[deprecated(since = "3.0.0", note = "Replaced with `App::mut_arg`")] + pub fn help_short(self, c: char) -> Self { + self.mut_arg("help", |a| a.short(c)) + } + + /// Deprecated, replaced with [`App::mut_arg`] + #[deprecated(since = "3.0.0", note = "Replaced with `App::mut_arg`")] + pub fn version_short(self, c: char) -> Self { + self.mut_arg("version", |a| a.short(c)) + } + + /// Deprecated, replaced with [`App::mut_arg`] + #[deprecated(since = "3.0.0", note = "Replaced with `App::mut_arg`")] + pub fn help_message(self, s: impl Into<&'help str>) -> Self { + self.mut_arg("help", |a| a.help(s.into())) + } + + /// Deprecated, replaced with [`App::mut_arg`] + #[deprecated(since = "3.0.0", note = "Replaced with `App::mut_arg`")] + pub fn version_message(self, s: impl Into<&'help str>) -> Self { + self.mut_arg("version", |a| a.help(s.into())) + } + /// Sets the help template to be used, overriding the default format. /// /// **NOTE:** The template system is by design very simple. Therefore, the @@ -954,6 +964,15 @@ impl<'help> App<'help> { self } + /// Deprecated, replaced with [`App::setting(a| b)`] + #[deprecated(since = "3.0.0", note = "Replaced with `App::setting(a | b)`")] + pub fn settings(mut self, settings: &[AppSettings]) -> Self { + for s in settings { + self.settings.insert((*s).into()); + } + self + } + /// Remove a setting for the current command or subcommand. /// /// See [`AppSettings`] for a full list of possibilities and examples. @@ -983,6 +1002,15 @@ impl<'help> App<'help> { self } + /// Deprecated, replaced with [`App::unset_setting(a| b)`] + #[deprecated(since = "3.0.0", note = "Replaced with `App::unset_setting(a | b)`")] + pub fn unset_settings(mut self, settings: &[AppSettings]) -> Self { + for s in settings { + self.settings.remove((*s).into()); + } + self + } + /// Apply a setting for the current command and all subcommands. /// /// See [`App::setting`] to apply a setting only to this command. @@ -1004,6 +1032,16 @@ impl<'help> App<'help> { self } + /// Deprecated, replaced with [`App::global_setting(a| b)`] + #[deprecated(since = "3.0.0", note = "Replaced with `App::global_setting(a | b)`")] + pub fn global_settings(mut self, settings: &[AppSettings]) -> Self { + for s in settings { + self.settings.insert((*s).into()); + self.g_settings.insert((*s).into()); + } + self + } + /// Remove a setting and stop propagating down to subcommands. /// /// See [`AppSettings`] for a full list of possibilities and examples. @@ -1983,6 +2021,12 @@ impl<'help> App<'help> { self._render_version(false) } + /// Deprecated, replaced with [`App::render_version`] + #[deprecated(since = "3.0.0", note = "Replaced with `App::render_version`")] + pub fn write_version(&self, w: &mut W) -> ClapResult<()> { + write!(w, "{}", self.render_version()).map_err(From::from) + } + /// Version message rendered as if the user ran `--version`. /// /// See also [`App::render_version`]. @@ -2007,6 +2051,12 @@ impl<'help> App<'help> { self._render_version(true) } + /// Deprecated, replaced with [`App::render_long_version`] + #[deprecated(since = "3.0.0", note = "Replaced with `App::render_long_version`")] + pub fn write_long_version(&self, w: &mut W) -> ClapResult<()> { + write!(w, "{}", self.render_long_version()).map_err(From::from) + } + /// Usage statement /// /// ### Examples @@ -2465,7 +2515,7 @@ impl<'help> App<'help> { let global_args: Vec<_> = self .args .args() - .filter(|a| a.global) + .filter(|a| a.get_global()) .map(|ga| ga.id.clone()) .collect(); if let Some(used_subcommand) = matcher.0.subcommand.as_ref() { @@ -2608,7 +2658,7 @@ impl<'help> App<'help> { debug!("App::_propagate_global_args:{}", self.name); for sc in &mut self.subcommands { - for a in self.args.args().filter(|a| a.global) { + for a in self.args.args().filter(|a| a.get_global()) { let mut propagate = false; let is_generated = matches!( a.provider, diff --git a/src/build/app/settings.rs b/src/build/app/settings.rs index c36f34b6..148dddea 100644 --- a/src/build/app/settings.rs +++ b/src/build/app/settings.rs @@ -103,11 +103,11 @@ impl_settings! { AppSettings, AppFlags, => Flags::DISABLE_HELP_SC, DisableHelpFlag("disablehelpflag") => Flags::DISABLE_HELP_FLAG, - DisableHelpFlags("disablehelpflag") + DisableHelpFlags("disablehelpflags") => Flags::DISABLE_HELP_FLAG, DisableVersionFlag("disableversionflag") => Flags::DISABLE_VERSION_FLAG, - DisableVersion("disableversionflag") + DisableVersion("disableversion") => Flags::DISABLE_VERSION_FLAG, PropagateVersion("propagateversion") => Flags::PROPAGATE_VERSION, diff --git a/src/build/arg/mod.rs b/src/build/arg/mod.rs index e3d81089..9268d86d 100644 --- a/src/build/arg/mod.rs +++ b/src/build/arg/mod.rs @@ -23,10 +23,6 @@ use std::{ #[cfg(feature = "env")] use std::{env, ffi::OsString}; -// Third Party -#[cfg(feature = "regex")] -use ::regex::Regex; - #[cfg(feature = "yaml")] use yaml_rust::Yaml; @@ -119,7 +115,6 @@ pub struct Arg<'help> { pub(crate) terminator: Option<&'help str>, pub(crate) index: Option, pub(crate) help_heading: Option>, - pub(crate) global: bool, pub(crate) exclusive: bool, pub(crate) value_hint: ValueHint, } @@ -268,7 +263,7 @@ impl<'help> Arg<'help> { /// Get information on if this argument is global or not pub fn get_global(&self) -> bool { - self.global + self.is_set(ArgSettings::Global) } /// Get the environment variable name specified for this argument, if any @@ -356,6 +351,7 @@ impl<'help> Arg<'help> { note = "Maybe clap::Parser would fit your use case? (Issue #9)" )] pub fn from_yaml(y: &'help Yaml) -> Self { + #![allow(deprecated)] let yaml_file_hash = y.as_hash().expect("YAML file must be a hash"); // We WANT this to panic on error...so expect() is good. let (name_yaml, yaml) = yaml_file_hash @@ -365,34 +361,21 @@ impl<'help> Arg<'help> { let name_str = name_yaml.as_str().expect("Arg name must be a string"); let mut a = Arg::new(name_str); - let mut has_metadata = false; - for (k, v) in yaml.as_hash().expect("Arg must be a hash") { a = match k.as_str().expect("Arg fields must be strings") { - "_has_metadata" => { - has_metadata = true; - a - } "short" => yaml_to_char!(a, v, short), "long" => yaml_to_str!(a, v, long), - "alias" => yaml_to_str!(a, v, alias), "aliases" => yaml_vec_or_str!(a, v, alias), - "short_alias" => yaml_to_str!(a, v, alias), - "short_aliases" => yaml_to_chars!(a, v, short_aliases), "help" => yaml_to_str!(a, v, help), "long_help" => yaml_to_str!(a, v, long_help), "required" => yaml_to_bool!(a, v, required), - "required_if_eq" => yaml_tuple2!(a, v, required_if_eq), - "required_if_eq_any" => yaml_array_tuple2!(a, v, required_if_eq_any), - "required_if_eq_all" => yaml_array_tuple2!(a, v, required_if_eq_all), + "required_if" => yaml_tuple2!(a, v, required_if_eq), + "required_ifs" => yaml_tuple2!(a, v, required_if_eq), "takes_value" => yaml_to_bool!(a, v, takes_value), "index" => yaml_to_usize!(a, v, index), "global" => yaml_to_bool!(a, v, global), - "multiple_occurrences" => yaml_to_bool!(a, v, multiple_occurrences), - "multiple_values" => yaml_to_bool!(a, v, multiple_values), - "hide" => yaml_to_bool!(a, v, hide), - "hide_long_help" => yaml_to_bool!(a, v, hide_long_help), - "hide_short_help" => yaml_to_bool!(a, v, hide_short_help), + "multiple" => yaml_to_bool!(a, v, multiple), + "hidden" => yaml_to_bool!(a, v, hide), "next_line_help" => yaml_to_bool!(a, v, next_line_help), "group" => yaml_to_str!(a, v, group), "number_of_values" => yaml_to_usize!(a, v, number_of_values), @@ -401,17 +384,14 @@ impl<'help> Arg<'help> { "value_name" => yaml_to_str!(a, v, value_name), "use_delimiter" => yaml_to_bool!(a, v, use_delimiter), "allow_hyphen_values" => yaml_to_bool!(a, v, allow_hyphen_values), - "raw" => yaml_to_bool!(a, v, raw), - "require_equals" => yaml_to_bool!(a, v, require_equals), + "last" => yaml_to_bool!(a, v, last), "require_delimiter" => yaml_to_bool!(a, v, require_delimiter), - "value_terminator" => yaml_to_str!(a, v, value_terminator), "value_delimiter" => yaml_to_char!(a, v, value_delimiter), - "required_unless_present" => yaml_to_str!(a, v, required_unless_present), + "required_unless" => yaml_to_str!(a, v, required_unless_present), "display_order" => yaml_to_usize!(a, v, display_order), "default_value" => yaml_to_str!(a, v, default_value), "default_value_if" => yaml_tuple3!(a, v, default_value_if), "default_value_ifs" => yaml_tuple3!(a, v, default_value_if), - "default_missing_value" => yaml_to_str!(a, v, default_missing_value), #[cfg(feature = "env")] "env" => yaml_to_str!(a, v, env), "value_names" => yaml_vec_or_str!(a, v, value_name), @@ -420,62 +400,16 @@ impl<'help> Arg<'help> { "requires_if" => yaml_tuple2!(a, v, requires_if), "requires_ifs" => yaml_tuple2!(a, v, requires_if), "conflicts_with" => yaml_vec_or_str!(a, v, conflicts_with), - "exclusive" => yaml_to_bool!(a, v, exclusive), - "last" => yaml_to_bool!(a, v, last), - "help_heading" => yaml_to_str!(a, v, help_heading), - "value_hint" => yaml_str_parse!(a, v, value_hint), - "hide_default_value" => yaml_to_bool!(a, v, hide_default_value), - #[cfg(feature = "env")] - "hide_env" => yaml_to_bool!(a, v, hide_env), - #[cfg(feature = "env")] - "hide_env_values" => yaml_to_bool!(a, v, hide_env_values), - "hide_possible_values" => yaml_to_bool!(a, v, hide_possible_values), "overrides_with" => yaml_to_str!(a, v, overrides_with), - "overrides_with_all" => yaml_vec_or_str!(a, v, overrides_with), - "possible_value" => yaml_to_str!(a, v, possible_value), "possible_values" => yaml_vec_or_str!(a, v, possible_value), - "ignore_case" => yaml_to_bool!(a, v, ignore_case), - "required_unless_present_any" => yaml_vec!(a, v, required_unless_present_any), - "required_unless_present_all" => yaml_vec!(a, v, required_unless_present_all), - "visible_alias" => yaml_to_str!(a, v, visible_alias), - "visible_aliases" => yaml_vec_or_str!(a, v, visible_alias), - "visible_short_alias" => yaml_to_char!(a, v, visible_short_alias), - "visible_short_aliases" => yaml_to_chars!(a, v, visible_short_aliases), - #[cfg(feature = "regex")] - "validator_regex" => { - if let Some(vec) = v.as_vec() { - debug_assert_eq!(2, vec.len()); - let regex = yaml_str!(vec[0]); - - match Regex::new(regex) { - Err(e) => panic!( - "Failed to convert \"{}\" into regular expression: {}", - regex, e - ), - Ok(regex) => a.validator_regex(regex, yaml_str!(vec[1])), - } - } else { - panic!("Failed to convert YAML value to vector") - } - } - "setting" | "settings" => { - yaml_to_setting!( - a, - v, - setting, - ArgSettings, - "ArgSetting", - format!("arg '{}'", name_str) - ) - } + "case_insensitive" => yaml_to_bool!(a, v, ignore_case), + "required_unless_one" => yaml_vec!(a, v, required_unless_present_any), + "required_unless_all" => yaml_vec!(a, v, required_unless_present_all), s => { - if !has_metadata { - panic!( - "Unknown setting '{}' in YAML file for arg '{}'", - s, name_str - ) - } - continue; + panic!( + "Unknown setting '{}' in YAML file for arg '{}'", + s, name_str + ) } } } @@ -1113,7 +1047,7 @@ impl<'help> Arg<'help> { since = "3.0.0", note = "Replaced with `Arg::required_unless_present_any`" )] - pub fn required_unless_any(self, names: I) -> Self + pub fn required_unless_one(self, names: I) -> Self where I: IntoIterator, T: Key, @@ -3020,6 +2954,8 @@ impl<'help> Arg<'help> { /// If `val` is set to `None`, `arg` only needs to be present. If `val` is set to `"some-val"` /// then `arg` must be present at runtime **and** have the value `val`. /// + /// If `default` is set to `None`, `default_value` will be removed. + /// /// **NOTE:** This setting is perfectly compatible with [`Arg::default_value`] but slightly /// different. `Arg::default_value` *only* takes effect when the user has not provided this arg /// at runtime. This setting however only takes effect when the user has not provided a value at @@ -3791,9 +3727,12 @@ impl<'help> Arg<'help> { /// [`Subcommand`]: crate::Subcommand /// [`ArgMatches::is_present("flag")`]: ArgMatches::is_present() #[inline] - pub fn global(mut self, yes: bool) -> Self { - self.global = yes; - self + pub fn global(self, yes: bool) -> Self { + if yes { + self.setting(ArgSettings::Global) + } else { + self.unset_setting(ArgSettings::Global) + } } /// Specifies that *multiple values* may only be set using the delimiter. @@ -5082,7 +5021,6 @@ impl<'help> fmt::Debug for Arg<'help> { .field("terminator", &self.terminator) .field("index", &self.index) .field("help_heading", &self.help_heading) - .field("global", &self.global) .field("exclusive", &self.exclusive) .field("value_hint", &self.value_hint) .field("default_missing_vals", &self.default_missing_vals); diff --git a/src/build/arg/settings.rs b/src/build/arg/settings.rs index 015764ad..e1d688a0 100644 --- a/src/build/arg/settings.rs +++ b/src/build/arg/settings.rs @@ -52,7 +52,7 @@ impl_settings! { ArgSettings, ArgFlags, MultipleValues("multiplevalues") => Flags::MULTIPLE_VALS, Multiple("multiple") => Flags::MULTIPLE, ForbidEmptyValues("forbidemptyvalues") => Flags::NO_EMPTY_VALS, - EmptyValues("emptyvalues") => Flags::NO_OP, + Global("global") => Flags::GLOBAL, Hidden("hidden") => Flags::HIDDEN, TakesValue("takesvalue") => Flags::TAKES_VAL, UseValueDelimiter("usevaluedelimiter") => Flags::USE_DELIM, @@ -64,7 +64,7 @@ impl_settings! { ArgSettings, ArgFlags, RequireEquals("requireequals") => Flags::REQUIRE_EQUALS, Last("last") => Flags::LAST, IgnoreCase("ignorecase") => Flags::CASE_INSENSITIVE, - CaseInsensitive("ignorecase") => Flags::CASE_INSENSITIVE, + CaseInsensitive("caseinsensitive") => Flags::CASE_INSENSITIVE, #[cfg(feature = "env")] HideEnv("hideenv") => Flags::HIDE_ENV, #[cfg(feature = "env")] @@ -100,13 +100,8 @@ pub enum ArgSettings { Multiple, /// Forbids an arg from accepting empty values such as `""` ForbidEmptyValues, - /// Deprecated, this is now the default, see [`ArgSettings::ForbidEmptyValues`] for the - /// opposite. - #[deprecated( - since = "3.0.0", - note = "This is now the default see [`ArgSettings::ForbidEmptyValues`] for the opposite." - )] - EmptyValues, + /// Sets an arg to be global (i.e. exist in all subcommands) + Global, /// Hides an arg from the help message Hidden, /// Allows an argument to take a value (such as `--option value`) diff --git a/src/build/macros.rs b/src/build/macros.rs index 7ac3ea4f..5be4d205 100644 --- a/src/build/macros.rs +++ b/src/build/macros.rs @@ -17,25 +17,6 @@ macro_rules! yaml_tuple2 { }}; } -#[cfg(feature = "yaml")] -macro_rules! yaml_array_tuple2 { - ($a:ident, $v:ident, $c:ident) => {{ - if let Some(vec) = $v.as_vec() { - for ys in vec { - if let Some(tup) = ys.as_vec() { - debug_assert_eq!(2, tup.len()); - $a = $a.$c(&[(yaml_str!(tup[0]), yaml_str!(tup[1]))]); - } else { - panic!("Failed to convert YAML value to vec"); - } - } - } else { - panic!("Failed to convert YAML value to vec"); - } - $a - }}; -} - #[cfg(feature = "yaml")] macro_rules! yaml_tuple3 { ($a:ident, $v:ident, $c:ident) => {{ @@ -130,28 +111,6 @@ macro_rules! yaml_char { }}; } -#[cfg(feature = "yaml")] -macro_rules! yaml_chars { - ($v:expr) => {{ - &$v.as_vec() - .unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a list", $v)) - .into_iter() - .map(|s| { - s.as_str() - .unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", s)) - }) - .map(|s| { - let mut chars = s.chars(); - let c = chars.next().expect("short aliases must be a single char"); - if chars.next().is_some() { - panic!("short aliases must be a single char"); - } - c - }) - .collect::>() - }}; -} - #[cfg(feature = "yaml")] macro_rules! yaml_str { ($v:expr) => {{ @@ -160,17 +119,6 @@ macro_rules! yaml_str { }}; } -#[cfg(feature = "yaml")] -macro_rules! yaml_str_parse { - ($a:ident, $v:ident, $c:ident) => {{ - $a.$c($v - .as_str() - .unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v)) - .parse() - .unwrap_or_else(|err| panic!("{}", err))) - }}; -} - #[cfg(feature = "yaml")] macro_rules! yaml_to_char { ($a:ident, $v:ident, $c:ident) => {{ @@ -178,13 +126,6 @@ macro_rules! yaml_to_char { }}; } -#[cfg(feature = "yaml")] -macro_rules! yaml_to_chars { - ($a:ident, $v:ident, $c:ident) => {{ - $a.$c(yaml_chars!($v)) - }}; -} - #[cfg(feature = "yaml")] macro_rules! yaml_to_str { ($a:ident, $v:ident, $c:ident) => {{ diff --git a/src/macros.rs b/src/macros.rs index 67d2be8b..11c1af68 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -12,6 +12,166 @@ macro_rules! load_yaml { }; } +/// Deprecated, replaced with [`ArgMatches::value_of_t`][crate::ArgMatches::value_of_t] +#[macro_export] +#[deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::value_of_t`")] +macro_rules! value_t { + ($m:ident, $v:expr, $t:ty) => { + $crate::value_t!($m.value_of($v), $t) + }; + ($m:ident.value_of($v:expr), $t:ty) => { + $m.value_of_t::<$t>($v) + }; +} + +/// Deprecated, replaced with [`ArgMatches::value_of_t_or_exit`][crate::ArgMatches::value_of_t_or_exit] +#[macro_export] +#[deprecated( + since = "3.0.0", + note = "Replaced with `ArgMatches::value_of_t_or_exit`" +)] +macro_rules! value_t_or_exit { + ($m:ident, $v:expr, $t:ty) => { + value_t_or_exit!($m.value_of($v), $t) + }; + ($m:ident.value_of($v:expr), $t:ty) => { + $m.value_of_t_or_exit::<$t>($v) + }; +} + +/// Deprecated, replaced with [`ArgMatches::values_of_t`][crate::ArgMatches::value_of_t] +#[macro_export] +#[deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::values_of_t`")] +macro_rules! values_t { + ($m:ident, $v:expr, $t:ty) => { + values_t!($m.values_of($v), $t) + }; + ($m:ident.values_of($v:expr), $t:ty) => { + $m.values_of_t::<$t>($v) + }; +} + +/// Deprecated, replaced with [`ArgMatches::values_of_t_or_exit`][crate::ArgMatches::value_of_t_or_exit] +#[macro_export] +#[deprecated( + since = "3.0.0", + note = "Replaced with `ArgMatches::values_of_t_or_exit`" +)] +macro_rules! values_t_or_exit { + ($m:ident, $v:expr, $t:ty) => { + values_t_or_exit!($m.values_of($v), $t) + }; + ($m:ident.values_of($v:expr), $t:ty) => { + $m.values_of_t_or_exit::<$t>($v) + }; +} + +/// Deprecated, replaced with [`ArgEnum`][crate::ArgEnum] +#[deprecated(since = "3.0.0", note = "Replaced with `ArgEnum`")] +#[macro_export] +macro_rules! arg_enum { + (@as_item $($i:item)*) => ($($i)*); + (@impls ( $($tts:tt)* ) -> ($e:ident, $($v:ident),+)) => { + $crate::arg_enum!(@as_item + $($tts)* + + impl ::std::str::FromStr for $e { + type Err = String; + + fn from_str(s: &str) -> ::std::result::Result { + #[allow(deprecated, unused_imports)] + use ::std::ascii::AsciiExt; + match s { + $(stringify!($v) | + _ if s.eq_ignore_ascii_case(stringify!($v)) => Ok($e::$v)),+, + _ => Err({ + let v = vec![ + $(stringify!($v),)+ + ]; + format!("valid values: {}", + v.join(", ")) + }), + } + } + } + impl ::std::fmt::Display for $e { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match *self { + $($e::$v => write!(f, stringify!($v)),)+ + } + } + } + impl $e { + #[allow(dead_code)] + pub fn variants() -> [&'static str; $crate::_clap_count_exprs!($(stringify!($v)),+)] { + [ + $(stringify!($v),)+ + ] + } + }); + }; + ($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => { + $crate::arg_enum!(@impls + ($(#[$($m),+])+ + pub enum $e { + $($v$(=$val)*),+ + }) -> ($e, $($v),+) + ); + }; + ($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => { + $crate::arg_enum!(@impls + ($(#[$($m),+])+ + pub enum $e { + $($v$(=$val)*),+ + }) -> ($e, $($v),+) + ); + }; + ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => { + $crate::arg_enum!(@impls + ($(#[$($m),+])+ + enum $e { + $($v$(=$val)*),+ + }) -> ($e, $($v),+) + ); + }; + ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => { + $crate::arg_enum!(@impls + ($(#[$($m),+])+ + enum $e { + $($v$(=$val)*),+ + }) -> ($e, $($v),+) + ); + }; + (pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => { + $crate::arg_enum!(@impls + (pub enum $e { + $($v$(=$val)*),+ + }) -> ($e, $($v),+) + ); + }; + (pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => { + $crate::arg_enum!(@impls + (pub enum $e { + $($v$(=$val)*),+ + }) -> ($e, $($v),+) + ); + }; + (enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => { + $crate::arg_enum!(@impls + (enum $e { + $($v$(=$val)*),+ + }) -> ($e, $($v),+) + ); + }; + (enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => { + $crate::arg_enum!(@impls + (enum $e { + $($v$(=$val)*),+ + }) -> ($e, $($v),+) + ); + }; +} + /// Allows you to pull the version from your Cargo.toml at compile time as /// `MAJOR.MINOR.PATCH_PKGVERSION_PRE` /// @@ -464,13 +624,6 @@ macro_rules! clap_app { $($tt)* } }; - (@app ($builder:expr) (@arg $name:literal: $($tail:tt)*) $($tt:tt)*) => { - $crate::clap_app!{ @app - ($builder.arg( - $crate::clap_app!{ @arg ($crate::Arg::new(stringify!($name).trim_matches('"'))) (-) $($tail)* })) - $($tt)* - } - }; (@app ($builder:expr) (@arg $name:ident: $($tail:tt)*) $($tt:tt)*) => { $crate::clap_app!{ @app ($builder.arg( @@ -478,48 +631,35 @@ macro_rules! clap_app { $($tt)* } }; - // Global Settings - (@app ($builder:expr) (@global_setting $setting:ident) $($tt:tt)*) => { - $crate::clap_app!{ @app - ($builder.global_setting($crate::AppSettings::$setting)) - $($tt)* - } - }; - // Settings (@app ($builder:expr) (@setting $setting:ident) $($tt:tt)*) => { $crate::clap_app!{ @app ($builder.setting($crate::AppSettings::$setting)) $($tt)* } }; - // Treat the application builder as an argument to set its attributes +// Treat the application builder as an argument to set its attributes (@app ($builder:expr) (@attributes $($attr:tt)*) $($tt:tt)*) => { $crate::clap_app!{ @app ($crate::clap_app!{ @arg ($builder) $($attr)* }) $($tt)* } }; - // ArgGroup - (@app ($builder:expr) (@group $name:ident: $($attrs:tt)*) $($tt:tt)*) => { + (@app ($builder:expr) (@group $name:ident => $($tail:tt)*) $($tt:tt)*) => { $crate::clap_app!{ @app - ($crate::clap_app!{ @group ($builder, $crate::ArgGroup::new(stringify!($name))) $($attrs)* }) + ($crate::clap_app!{ @group ($builder, $crate::ArgGroup::new(stringify!($name))) $($tail)* }) $($tt)* } }; - // Handle subcommand creation - (@app ($builder:expr) (@subcommand ($name:expr) => $($tail:tt)*) $($tt:tt)*) => { + (@app ($builder:expr) (@group $name:ident !$ident:ident => $($tail:tt)*) $($tt:tt)*) => { $crate::clap_app!{ @app - ($builder.subcommand( - $crate::clap_app!{ @app ($crate::App::new($name)) $($tail)* } - )) + ($crate::clap_app!{ @group ($builder, $crate::ArgGroup::new(stringify!($name)).$ident(false)) $($tail)* }) $($tt)* } }; - (@app ($builder:expr) (@subcommand $name:literal => $($tail:tt)*) $($tt:tt)*) => { + (@app ($builder:expr) (@group $name:ident +$ident:ident => $($tail:tt)*) $($tt:tt)*) => { $crate::clap_app!{ @app - ($builder.subcommand( - $crate::clap_app!{ @app ($crate::App::new(stringify!($name).trim_matches('"'))) $($tail)* } - )) + ($crate::clap_app!{ @group ($builder, $crate::ArgGroup::new(stringify!($name)).$ident(true)) $($tail)* }) $($tt)* } }; +// Handle subcommand creation (@app ($builder:expr) (@subcommand $name:ident => $($tail:tt)*) $($tt:tt)*) => { $crate::clap_app!{ @app ($builder.subcommand( @@ -528,32 +668,20 @@ macro_rules! clap_app { $($tt)* } }; - // Yaml like function calls - used for setting various meta directly against the app +// Yaml like function calls - used for setting various meta directly against the app (@app ($builder:expr) ($ident:ident: $($v:expr),*) $($tt:tt)*) => { +// $crate::clap_app!{ @app ($builder.$ident($($v),*)) $($tt)* } $crate::clap_app!{ @app ($builder.$ident($($v),*)) $($tt)* } }; - // Add members to group and continue argument handling with the parent builder + +// Add members to group and continue argument handling with the parent builder (@group ($builder:expr, $group:expr)) => { $builder.group($group) }; // Treat the group builder as an argument to set its attributes (@group ($builder:expr, $group:expr) (@attributes $($attr:tt)*) $($tt:tt)*) => { - $crate::clap_app!{ @group ($builder, $group) $($attr)* $($tt)* } - }; - (@group ($builder:expr, $group:expr) (@arg ($name:expr): $($tail:tt)*) $($tt:tt)*) => { - $crate::clap_app!{ @group - ($crate::clap_app!{ @app ($builder) (@arg ($name): $($tail)*) }, - $group.arg($name)) - $($tt)* - } - }; - (@group ($builder:expr, $group:expr) (@arg $name:literal: $($tail:tt)*) $($tt:tt)*) => { - $crate::clap_app!{ @group - ($crate::clap_app!{ @app ($builder) (@arg $name: $($tail)*) }, - $group.arg(stringify!($name).trim_matches('"'))) - $($tt)* - } + $crate::clap_app!{ @group ($builder, $crate::clap_app!{ @arg ($group) (-) $($attr)* }) $($tt)* } }; (@group ($builder:expr, $group:expr) (@arg $name:ident: $($tail:tt)*) $($tt:tt)*) => { $crate::clap_app!{ @group @@ -562,50 +690,16 @@ macro_rules! clap_app { $($tt)* } }; - // Handle group attributes - (@group ($builder:expr, $group:expr) !$ident:ident $($tail:tt)*) => { - $crate::clap_app!{ @group ($builder, $group.$ident(false)) $($tail)* } - }; - (@group ($builder:expr, $group:expr) +$ident:ident $($tail:tt)*) => { - $crate::clap_app!{ @group ($builder, $group.$ident(true)) $($tail)* } - }; - (@group ($builder:expr, $group:expr) * $($tail:tt)*) => { - $crate::clap_app!{ @group ($builder, $group) +required $($tail)* } - }; - (@group ($builder:expr, $group:expr) ... $($tail:tt)*) => { - $crate::clap_app!{ @group ($builder, $group) +multiple $($tail)* } - }; - (@group ($builder:expr, $group:expr) $ident:ident[$($target:literal)*] $($tail:tt)*) => { - $crate::clap_app!{ @group ($builder, $group $( .$ident(stringify!($target).trim_matches('"')) )*) $($tail)* } - }; - (@group ($builder:expr, $group:expr) $ident:ident[$($target:ident)*] $($tail:tt)*) => { - $crate::clap_app!{ @group ($builder, $group $( .$ident(stringify!($target)) )*) $($tail)* } - }; - (@group ($builder:expr, $group:expr) $ident:ident($($expr:expr),*) $($tail:tt)*) => { - $crate::clap_app!{ @group ($builder, $group.$ident($($expr),*)) $($tail)* } - }; - (@group ($builder:expr, $group:expr) $ident:ident($($expr:expr,)*) $($tail:tt)*) => { - $crate::clap_app!{ @group ($builder, $group.$ident($($expr),*)) $($tail)* } - }; - // No more tokens to munch +// No more tokens to munch (@arg ($arg:expr) $modes:tt) => { $arg }; - // Shorthand tokens influenced by the usage_string +// Shorthand tokens influenced by the usage_string (@arg ($arg:expr) $modes:tt --($long:expr) $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg.long($long)) $modes $($tail)* } }; - (@arg ($arg:expr) $modes:tt --$long:literal $($tail:tt)*) => { - $crate::clap_app!{ @arg ($arg.long(stringify!($long).trim_matches('"'))) $modes $($tail)* } - }; (@arg ($arg:expr) $modes:tt --$long:ident $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg.long(stringify!($long))) $modes $($tail)* } }; - (@arg ($arg:expr) $modes:tt -($short:expr) $($tail:tt)*) => { - $crate::clap_app!{ @arg ($arg.short($short)) $modes $($tail)* } - }; - (@arg ($arg:expr) $modes:tt -$short:literal $($tail:tt)*) => { - $crate::clap_app!{ @arg ($arg.short($short.to_string().chars().next().expect(r#""" is not allowed here"#))) $modes $($tail)* } - }; (@arg ($arg:expr) $modes:tt -$short:ident $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg.short(stringify!($short).chars().next().unwrap())) $modes $($tail)* } }; @@ -622,62 +716,52 @@ macro_rules! clap_app { $crate::clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) $($tail)* } }; (@arg ($arg:expr) $modes:tt ... $($tail:tt)*) => { - $crate::clap_app!{ @arg ($arg) $modes +multiple_values +takes_value $($tail)* } + $crate::clap_app!{ @arg ($arg) $modes +multiple +takes_value $($tail)* } }; - // Shorthand magic +// Shorthand magic (@arg ($arg:expr) $modes:tt #{$n:expr, $m:expr} $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg) $modes min_values($n) max_values($m) $($tail)* } }; (@arg ($arg:expr) $modes:tt * $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg) $modes +required $($tail)* } }; - // !foo -> .foo(false) +// !foo -> .foo(false) (@arg ($arg:expr) $modes:tt !$ident:ident $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg.$ident(false)) $modes $($tail)* } }; - // +foo -> .foo(true) +// +foo -> .foo(true) (@arg ($arg:expr) $modes:tt +$ident:ident $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg.$ident(true)) $modes $($tail)* } }; - // Validator +// Validator (@arg ($arg:expr) $modes:tt {$fn_:expr} $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg.validator($fn_)) $modes $($tail)* } }; (@as_expr $expr:expr) => { $expr }; - // Help +// Help (@arg ($arg:expr) $modes:tt $desc:tt) => { $arg.help($crate::clap_app!{ @as_expr $desc }) }; - // Handle functions that need to be called multiple times for each argument - (@arg ($arg:expr) $modes:tt $ident:ident[$($target:literal)*] $($tail:tt)*) => { - $crate::clap_app!{ @arg ($arg $( .$ident(stringify!($target).trim_matches('"')) )*) $modes $($tail)* } - }; +// Handle functions that need to be called multiple times for each argument (@arg ($arg:expr) $modes:tt $ident:ident[$($target:ident)*] $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg $( .$ident(stringify!($target)) )*) $modes $($tail)* } }; - // Inherit builder's functions, e.g. `index(2)`, `requires_if("val", "arg")` +// Inherit builder's functions, e.g. `index(2)`, `requires_if("val", "arg")` (@arg ($arg:expr) $modes:tt $ident:ident($($expr:expr),*) $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg.$ident($($expr),*)) $modes $($tail)* } }; - // Inherit builder's functions with trailing comma, e.g. `index(2,)`, `requires_if("val", "arg",)` +// Inherit builder's functions with trailing comma, e.g. `index(2,)`, `requires_if("val", "arg",)` (@arg ($arg:expr) $modes:tt $ident:ident($($expr:expr,)*) $($tail:tt)*) => { $crate::clap_app!{ @arg ($arg.$ident($($expr),*)) $modes $($tail)* } }; - // Build a subcommand outside of an app. - (@subcommand ($name:expr) => $($tail:tt)*) => { - $crate::clap_app!{ @app ($crate::App::new($name)) $($tail)* } - }; - (@subcommand $name:literal => $($tail:tt)*) => { - $crate::clap_app!{ @app ($crate::App::new(stringify!($name).trim_matches('"'))) $($tail)* } - }; + +// Build a subcommand outside of an app. (@subcommand $name:ident => $($tail:tt)*) => { $crate::clap_app!{ @app ($crate::App::new(stringify!($name))) $($tail)* } }; - // Start the magic +// Start the magic (($name:expr) => $($tail:tt)*) => {{ $crate::clap_app!{ @app ($crate::App::new($name)) $($tail)*} }}; - ($name:literal => $($tail:tt)*) => {{ - $crate::clap_app!{ @app ($crate::App::new(stringify!($name).trim_matches('"'))) $($tail)*} - }}; + ($name:ident => $($tail:tt)*) => {{ $crate::clap_app!{ @app ($crate::App::new(stringify!($name))) $($tail)*} }}; @@ -819,57 +903,3 @@ macro_rules! debug { macro_rules! debug { ($($arg:tt)*) => {}; } - -/// Deprecated, replaced with [`ArgMatches::value_of_t`][crate::ArgMatches::value_of_t] -#[macro_export] -#[deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::value_of_t`")] -macro_rules! value_t { - ($m:ident, $v:expr, $t:ty) => { - clap::value_t!($m.value_of($v), $t) - }; - ($m:ident.value_of($v:expr), $t:ty) => { - $m.value_of_t::<$t>($v) - }; -} - -/// Deprecated, replaced with [`ArgMatches::value_of_t_or_exit`][crate::ArgMatches::value_of_t_or_exit] -#[macro_export] -#[deprecated( - since = "3.0.0", - note = "Replaced with `ArgMatches::value_of_t_or_exit`" -)] -macro_rules! value_t_or_exit { - ($m:ident, $v:expr, $t:ty) => { - value_t_or_exit!($m.value_of($v), $t) - }; - ($m:ident.value_of($v:expr), $t:ty) => { - $m.value_of_t_or_exit::<$t>($v) - }; -} - -/// Deprecated, replaced with [`ArgMatches::values_of_t`][crate::ArgMatches::value_of_t] -#[macro_export] -#[deprecated(since = "3.0.0", note = "Replaced with `ArgMatches::values_of_t`")] -macro_rules! values_t { - ($m:ident, $v:expr, $t:ty) => { - values_t!($m.values_of($v), $t) - }; - ($m:ident.values_of($v:expr), $t:ty) => { - $m.values_of_t::<$t>($v) - }; -} - -/// Deprecated, replaced with [`ArgMatches::values_of_t_or_exit`][crate::ArgMatches::value_of_t_or_exit] -#[macro_export] -#[deprecated( - since = "3.0.0", - note = "Replaced with `ArgMatches::values_of_t_or_exit`" -)] -macro_rules! values_t_or_exit { - ($m:ident, $v:expr, $t:ty) => { - values_t_or_exit!($m.values_of($v), $t) - }; - ($m:ident.values_of($v:expr), $t:ty) => { - $m.values_of_t_or_exit::<$t>($v) - }; -} diff --git a/tests/fixtures/app.yaml b/tests/app.yml similarity index 58% rename from tests/fixtures/app.yaml rename to tests/app.yml index 35ad9fc8..e58e5244 100644 --- a/tests/fixtures/app.yaml +++ b/tests/app.yml @@ -4,31 +4,26 @@ about: tests clap library author: Kevin K. settings: - ArgRequiredElseHelp +help_message: prints help with a nonstandard description args: - - help: - short: h - long: help - help: prints help with a nonstandard description - - option: + - opt: short: o long: option + multiple: true takes_value: true - multiple_values: true help: tests options - positional: help: tests positionals - index: 1 - positional2: help: tests positionals with exclusions - index: 2 default_value_if: - - [flag, null, some] - - [positional, other, something] + - [flag, Null, some] + - [postional, other, something] - flag: short: f long: flag + multiple: true takes_value: true - multiple_values: true help: tests flags global: true - flag2: @@ -41,13 +36,11 @@ args: - option2: long: long-option-2 help: tests long options with exclusions - conflicts_with: - - option requires: - positional2 - option3: short: O - long: option3 + long: Option help: tests options with specific value sets takes_value: true possible_values: @@ -56,7 +49,6 @@ args: requires_if: - [fast, flag] - positional3: - index: 3 help: tests positionals with specific values possible_values: [ vi, emacs ] - multvals: @@ -67,83 +59,49 @@ args: - two - multvalsmo: long: multvalsmo - multiple_values: true + multiple: true + takes_value: true help: Tests multiple values, not mult occs value_names: [one, two] - multvalsdelim: long: multvalsdelim help: Tests multiple values with required delimiter + multiple: true takes_value: true - multiple_occurrences: true - use_delimiter: true require_delimiter: true - - settings: - short: s - takes_value: true - multiple_values: true + value_delimiter: "," - singlealias: long: singlealias help: Tests single alias aliases: [alias] - required_if_eq: + required_if: - [multvalsmo, two] - multaliases: long: multaliases help: Tests multiple aliases aliases: [als1, als2, als3] - - singleshortalias: - long: singleshortalias - help: Tests single short alias - short_aliases: [a] - required_if_eq: - - [multvalsmo, two] - - multshortaliases: - long: multshortaliases - help: Tests multiple short aliases - short_aliases: [b, c] - minvals2: long: minvals2 - multiple_values: true + multiple: true + takes_value: true help: Tests 2 min vals min_values: 2 - maxvals3: long: maxvals3 - multiple_values: true + multiple: true + takes_value: true help: Tests 3 max vals max_values: 3 - - exclusive: - long: exclusive - help: Tests 3 exclusive - exclusive: true - - ignore_case: - index: 4 - help: Test ignore case + - case_insensitive: + help: Test case_insensitive possible_values: [test123, test321] - ignore_case: true - - value_hint: - long: value-hint - help: Test value_hint - value_hint: FilePath - - verbose: - short: v - multiple_occurrences: true - takes_value: false - help: Sets the level of verbosity - - visiblealiases: - long: visiblealiases - help: Tests visible aliases - visible_alias: visals1 - visible_aliases: [visals2, visals2, visals3] - - visibleshortaliases: - long: visibleshortaliases - help: Tests visible short aliases - visible_short_alias: e - visible_short_aliases: [l, m] -groups: + case_insensitive: true + +arg_groups: - test: args: - maxvals3 - - minvals2 + - minmals2 conflicts_with: - option3 requires: @@ -157,9 +115,8 @@ subcommands: - scoption: short: o long: option - multiple_values: true + multiple: true help: tests options takes_value: true - scpositional: help: tests positionals - index: 1 diff --git a/tests/fixtures/app_2space.yaml b/tests/fixtures/app_2space.yaml deleted file mode 100644 index 0000a26b..00000000 --- a/tests/fixtures/app_2space.yaml +++ /dev/null @@ -1,11 +0,0 @@ -name: claptests -version: "1.0" -about: tests clap library -author: Kevin K. -args: - - opt: - short: o - long: option - takes_value: true - multiple_values: true - help: tests options diff --git a/tests/fixtures/app_field_not_string.yaml b/tests/fixtures/app_field_not_string.yaml deleted file mode 100644 index 20c96e3e..00000000 --- a/tests/fixtures/app_field_not_string.yaml +++ /dev/null @@ -1,2 +0,0 @@ -name: claptests -1: "invalid" diff --git a/tests/fixtures/app_regex.yaml b/tests/fixtures/app_regex.yaml deleted file mode 100644 index 900c5a13..00000000 --- a/tests/fixtures/app_regex.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: clapregextest -version: "1.0" -about: tests clap regex functionality -author: Benjamin Kästner -args: - - filter: - index: 1 - validator_regex: ["^*\\.[a-z]+$", expected extension pattern] - help: file extension pattern diff --git a/tests/fixtures/app_regex_invalid.yaml b/tests/fixtures/app_regex_invalid.yaml deleted file mode 100644 index fad28fef..00000000 --- a/tests/fixtures/app_regex_invalid.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: clapregextest -version: "1.0" -about: tests clap regex functionality -author: Benjamin Kästner -args: - - filter: - index: 1 - validator_regex: [")", invalid regular expression] diff --git a/tests/fixtures/app_setting_invalid.yaml b/tests/fixtures/app_setting_invalid.yaml deleted file mode 100644 index 86a0ce1d..00000000 --- a/tests/fixtures/app_setting_invalid.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: claptests -version: "1.0" -about: tests clap extra fields -settings: - - random diff --git a/tests/fixtures/arg_field_not_string.yaml b/tests/fixtures/arg_field_not_string.yaml deleted file mode 100644 index 7007c5cb..00000000 --- a/tests/fixtures/arg_field_not_string.yaml +++ /dev/null @@ -1,2 +0,0 @@ -claptest-arg: - 6: false diff --git a/tests/fixtures/arg_not_hash.yaml b/tests/fixtures/arg_not_hash.yaml deleted file mode 100644 index 17a38d75..00000000 --- a/tests/fixtures/arg_not_hash.yaml +++ /dev/null @@ -1,4 +0,0 @@ -name: claptests -args: - - arg: - short: a diff --git a/tests/fixtures/arg_setting_invalid.yaml b/tests/fixtures/arg_setting_invalid.yaml deleted file mode 100644 index e81a11ea..00000000 --- a/tests/fixtures/arg_setting_invalid.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: claptests -version: "1.0" -about: tests clap extra fields -args: - - option: - long: option - settings: - - random diff --git a/tests/fixtures/extra_fields.yaml b/tests/fixtures/extra_fields.yaml deleted file mode 100644 index 1d11f4bb..00000000 --- a/tests/fixtures/extra_fields.yaml +++ /dev/null @@ -1,10 +0,0 @@ -_has_metadata: true -name: claptests -version: "1.0" -about: tests clap extra fields -random: This field is extra -args: - - option: - _has_metadata: true - long: option - random: This field is extra diff --git a/tests/fixtures/extra_fields_invalid_app.yaml b/tests/fixtures/extra_fields_invalid_app.yaml deleted file mode 100644 index 72ea4d0e..00000000 --- a/tests/fixtures/extra_fields_invalid_app.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: claptests -version: "1.0" -about: tests clap extra fields -subcommands: - - info: - random: This field is extra diff --git a/tests/fixtures/extra_fields_invalid_arg.yaml b/tests/fixtures/extra_fields_invalid_arg.yaml deleted file mode 100644 index 4b16c9cc..00000000 --- a/tests/fixtures/extra_fields_invalid_arg.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: claptests -version: "1.0" -about: tests clap extra fields -args: - - option: - long: option - random: This field is extra diff --git a/tests/fixtures/field_not_hash.yaml b/tests/fixtures/field_not_hash.yaml deleted file mode 100644 index fba9b084..00000000 --- a/tests/fixtures/field_not_hash.yaml +++ /dev/null @@ -1,3 +0,0 @@ -claptests: - - 5 - - 6 diff --git a/tests/fixtures/multiple_groups.yaml b/tests/fixtures/multiple_groups.yaml deleted file mode 100644 index 62a3c696..00000000 --- a/tests/fixtures/multiple_groups.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: app - -args: - - arg_1: - short: a - - arg_2: - short: b - - arg_3: - short: c - - arg_4: - short: d - -groups: - - group_1: - args: - - arg_1 - - arg_2 - - group_2: - args: - - arg_3 - - arg_4 diff --git a/tests/fixtures/name_not_string.yaml b/tests/fixtures/name_not_string.yaml deleted file mode 100644 index 19895315..00000000 --- a/tests/fixtures/name_not_string.yaml +++ /dev/null @@ -1 +0,0 @@ -100: "claptests" diff --git a/tests/fixtures/not_hash.yaml b/tests/fixtures/not_hash.yaml deleted file mode 100644 index eb2f5db0..00000000 --- a/tests/fixtures/not_hash.yaml +++ /dev/null @@ -1 +0,0 @@ -["clap", "tests"] diff --git a/tests/macros.rs b/tests/macros.rs index 6dc479fa..11297090 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -9,7 +9,6 @@ fn basic() { (version: "0.1") (about: "tests clap library") (author: "Kevin K. ") - (@global_setting AllowNegativeNumbers) (@arg opt: -o --option +takes_value ... "tests options") (@arg positional: index(1) "tests positionals") (@arg flag: -f --flag ... +global "tests flags") @@ -157,42 +156,6 @@ fn quoted_arg_name() { assert!(matches.is_present("option2")); } -#[test] -fn quoted_subcommand_name() { - #![allow(deprecated)] - clap::clap_app!(claptests => - (version: "0.1") - (about: "tests clap library") - (author: "Kevin K. ") - (@arg opt: -o --option +takes_value ... "tests options") - (@arg positional: index(1) "tests positionals") - (@arg flag: -f --flag ... +global "tests flags") - (@arg flag2: -F conflicts_with[flag] requires[option2] - "tests flags with exclusions") - (@arg option2: --long_option_2 conflicts_with[option] requires[positional2] - "tests long options with exclusions") - (@arg positional2: index(2) "tests positionals with exclusions") - (@arg option3: -O --Option +takes_value possible_value[fast slow] - "tests options with specific value sets") - (@arg positional3: index(3) ... possible_value[vi emacs] - "tests positionals with specific values") - (@arg multvals: --multvals +takes_value value_name[one two] - "Tests multiple values, not mult occs") - (@arg multvalsmo: --multvalsmo ... +takes_value value_name[one two] - "Tests multiple values, not mult occs") - (@arg minvals: --minvals2 min_values(1) ... +takes_value "Tests 2 min vals") - (@arg maxvals: --maxvals3 ... +takes_value max_values(3) "Tests 3 max vals") - (@subcommand subcmd => - (about: "tests subcommands") - (version: "0.1") - (author: "Kevin K. ") - (@arg scoption: -o --option ... +takes_value "tests options") - (@arg scpositional: index(1) "tests positionals")) - (@subcommand ("other-subcmd") => - (about: "some other subcommand")) - ); -} - #[test] fn group_macro() { #![allow(deprecated)] @@ -200,7 +163,7 @@ fn group_macro() { (version: "0.1") (about: "tests clap library") (author: "Kevin K. ") - (@group difficulty: + (@group difficulty => (@arg hard: -h --hard "Sets hard mode") (@arg normal: -n --normal "Sets normal mode") (@arg easy: -e --easy "Sets easy mode") @@ -221,7 +184,7 @@ fn group_macro_set_multiple() { (version: "0.1") (about: "tests clap library") (author: "Kevin K. ") - (@group difficulty: +multiple + (@group difficulty +multiple => (@arg hard: -h --hard "Sets hard mode") (@arg normal: -n --normal "Sets normal mode") (@arg easy: -e --easy "Sets easy mode") @@ -244,7 +207,7 @@ fn group_macro_set_not_multiple() { (version: "0.1") (about: "tests clap library") (author: "Kevin K. ") - (@group difficulty: !multiple + (@group difficulty !multiple => (@arg hard: -h --hard "Sets hard mode") (@arg normal: -n --normal "Sets normal mode") (@arg easy: -e --easy "Sets easy mode") @@ -264,7 +227,7 @@ fn group_macro_set_required() { (version: "0.1") (about: "tests clap library") (author: "Kevin K. ") - (@group difficulty: +required + (@group difficulty +required => (@arg hard: -h --hard "Sets hard mode") (@arg normal: -n --normal "Sets normal mode") (@arg easy: -e --easy "Sets easy mode") @@ -284,7 +247,7 @@ fn group_macro_set_not_required() { (version: "0.1") (about: "tests clap library") (author: "Kevin K. ") - (@group difficulty: !required + (@group difficulty !required => (@arg hard: -h --hard "Sets hard mode") (@arg normal: -n --normal "Sets normal mode") (@arg easy: -e --easy "Sets easy mode") @@ -297,145 +260,6 @@ fn group_macro_set_not_required() { assert!(!matches.is_present("difficulty")); } -#[test] -fn group_macro_attributes_alternative() { - #![allow(deprecated)] - let app = clap::clap_app!(claptests => - (version: "0.1") - (about: "tests clap library") - (author: "Kevin K. ") - (@group difficulty: - (@attributes +multiple +required) - (@arg hard: -h --hard "Sets hard mode") - (@arg normal: -n --normal "Sets normal mode") - (@arg easy: -e --easy "Sets easy mode") - ) - ); - - let result = app - .clone() - .try_get_matches_from(vec!["bin_name", "--hard", "--easy"]); - assert!(result.is_ok()); - let matches = result.expect("Expected to successfully match the given args."); - assert!(matches.is_present("difficulty")); - assert!(matches.is_present("hard")); - assert!(matches.is_present("easy")); - assert!(!matches.is_present("normal")); - - let result = app.try_get_matches_from(vec!["bin_name"]); - assert!(result.is_err()); - let err = result.unwrap_err(); - assert_eq!(err.kind, ErrorKind::MissingRequiredArgument); -} - -#[test] -fn group_macro_multiple_methods() { - #![allow(deprecated)] - let app = clap::clap_app!(claptests => - (version: "0.1") - (about: "tests clap library") - (author: "Kevin K. ") - (@group difficulty: +multiple +required - (@arg hard: -h --hard "Sets hard mode") - (@arg normal: -n --normal "Sets normal mode") - (@arg easy: -e --easy "Sets easy mode") - ) - ); - - let result = app - .clone() - .try_get_matches_from(vec!["bin_name", "--hard", "--easy"]); - assert!(result.is_ok()); - let matches = result.expect("Expected to successfully match the given args."); - assert!(matches.is_present("difficulty")); - assert!(matches.is_present("hard")); - assert!(matches.is_present("easy")); - assert!(!matches.is_present("normal")); - - let result = app.try_get_matches_from(vec!["bin_name"]); - assert!(result.is_err()); - let err = result.unwrap_err(); - assert_eq!(err.kind, ErrorKind::MissingRequiredArgument); -} - -#[test] -fn group_macro_multiple_methods_alternative() { - #![allow(deprecated)] - let app = clap::clap_app!(claptests => - (version: "0.1") - (about: "tests clap library") - (author: "Kevin K. ") - (@group difficulty: * ... - (@arg hard: -h --hard "Sets hard mode") - (@arg normal: -n --normal "Sets normal mode") - (@arg easy: -e --easy "Sets easy mode") - ) - ); - - let result = app - .clone() - .try_get_matches_from(vec!["bin_name", "--hard", "--easy"]); - assert!(result.is_ok()); - let matches = result.expect("Expected to successfully match the given args."); - assert!(matches.is_present("difficulty")); - assert!(matches.is_present("hard")); - assert!(matches.is_present("easy")); - assert!(!matches.is_present("normal")); - - let result = app.try_get_matches_from(vec!["bin_name"]); - assert!(result.is_err()); - let err = result.unwrap_err(); - assert_eq!(err.kind, ErrorKind::MissingRequiredArgument); -} - -#[test] -fn group_macro_multiple_invocations() { - #![allow(deprecated)] - let app = clap::clap_app!(claptests => - (version: "0.1") - (about: "tests clap library") - (author: "Kevin K. ") - (@arg foo: --foo) - (@arg bar: --bar) - (@group difficulty: conflicts_with[foo bar] - (@arg hard: -h --hard "Sets hard mode") - (@arg normal: -n --normal "Sets normal mode") - (@arg easy: -e --easy "Sets easy mode") - ) - ); - - let result = app - .clone() - .try_get_matches_from(vec!["bin_name", "--hard", "--foo"]); - assert!(result.is_err()); - let err = result.unwrap_err(); - assert_eq!(err.kind, ErrorKind::ArgumentConflict); - - let result = app.try_get_matches_from(vec!["bin_name", "--hard", "--bar"]); - assert!(result.is_err()); - let err = result.unwrap_err(); - assert_eq!(err.kind, ErrorKind::ArgumentConflict); -} - -#[test] -fn literals() { - #![allow(deprecated)] - clap::clap_app!("clap-tests" => - (version: "0.1") - (@arg "task-num": -"t-n" --"task-num" +takes_value possible_value["all" 0 1 2] - "Task number") - (@group priority: - (@arg "4": -4 --4 "Sets priority to 4") - (@arg ("5"): -('5') --5 "Sets priority to 5") - (@arg 6: -6 --6 "Sets priority to 6") - ) - (@subcommand "view-tasks" => - (about: "View all tasks")) - (@subcommand 0 => - (about: "Set everything to zero priority")) - ); -} - #[test] fn multiarg() { #![allow(deprecated)] @@ -465,31 +289,6 @@ fn multiarg() { assert_eq!(matches.value_of("multiarg2"), Some("flag-set")); } -#[test] -fn validator() { - #![allow(deprecated)] - - use std::str::FromStr; - - fn validate(val: &str) -> Result { - val.parse::().map_err(|e| e.to_string()) - } - - let app = clap::clap_app!(claptests => - (@arg inline: { |val| val.parse::() }) - (@arg func1: { validate }) - (@arg func2: { u64::from_str }) - ); - - let matches = app - .try_get_matches_from(&["bin", "12", "34", "56"]) - .expect("match failed"); - - assert_eq!(matches.value_of_t::("inline").ok(), Some(12)); - assert_eq!(matches.value_of_t::("func1").ok(), Some(34)); - assert_eq!(matches.value_of_t::("func2").ok(), Some(56)); -} - mod arg { #[test] fn name_explicit() { diff --git a/tests/yaml.rs b/tests/yaml.rs index 3f903d24..3ee6c938 100644 --- a/tests/yaml.rs +++ b/tests/yaml.rs @@ -1,268 +1,38 @@ #![cfg(feature = "yaml")] #![allow(deprecated)] -use clap::{load_yaml, App, Arg, ErrorKind, ValueHint}; +use clap::{load_yaml, App}; #[test] fn create_app_from_yaml() { - let yaml = load_yaml!("fixtures/app.yaml"); - let _ = App::from_yaml(yaml); + let yml = load_yaml!("app.yml"); + App::from_yaml(yml); } -// TODO: Uncomment to test yaml with 2 spaces https://github.com/chyh1990/yaml-rust/issues/101 -// #[test] -// fn create_app_from_yaml_2spaces() { -// let yaml = load_yaml!("fixtures/app_2space.yaml"); -// App::from_yaml(yaml); -// } - #[test] fn help_message() { - let yaml = load_yaml!("fixtures/app.yaml"); - let mut app = App::from_yaml(yaml); + let yml = load_yaml!("app.yml"); + let mut app = App::from_yaml(yml); // Generate the full help message! - let _ = app.try_get_matches_from_mut(Vec::::new()); + let _ = app.get_matches_from_safe_borrow(Vec::::new()); let mut help_buffer = Vec::new(); app.write_help(&mut help_buffer).unwrap(); let help_string = String::from_utf8(help_buffer).unwrap(); - println!("{}", help_string); - assert!(help_string - .contains("-h, --help\n prints help with a nonstandard description\n")); + println!("{}", &help_string); + assert!(help_string.contains("tests positionals with exclusions\n")); } #[test] fn author() { - let yaml = load_yaml!("fixtures/app.yaml"); - let mut app = App::from_yaml(yaml); + let yml = load_yaml!("app.yml"); + let mut app = App::from_yaml(yml); // Generate the full help message! - let _ = app.try_get_matches_from_mut(Vec::::new()); + let _ = app.get_matches_from_safe_borrow(Vec::::new()); let mut help_buffer = Vec::new(); app.write_help(&mut help_buffer).unwrap(); let help_string = String::from_utf8(help_buffer).unwrap(); + println!("{}", &help_string); assert!(help_string.contains("Kevin K. ")); } - -#[test] -fn app_settings() { - let yaml = load_yaml!("fixtures/app.yaml"); - let app = App::from_yaml(yaml); - - let m = app.try_get_matches_from(vec!["prog"]); - - assert!(m.is_err()); - assert_eq!( - m.unwrap_err().kind, - ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand - ); -} - -#[test] -#[should_panic = "Unknown AppSetting 'random' found in YAML file for app"] -fn app_setting_invalid() { - let yaml = load_yaml!("fixtures/app_setting_invalid.yaml"); - let _ = App::from_yaml(yaml); -} - -#[test] -#[should_panic = "Unknown ArgSetting 'random' found in YAML file for arg 'option'"] -fn arg_setting_invalid() { - let yaml = load_yaml!("fixtures/arg_setting_invalid.yaml"); - let _ = App::from_yaml(yaml); -} - -// ValueHint must be parsed correctly from Yaml -#[test] -fn value_hint() { - let yml = load_yaml!("fixtures/app.yaml"); - let app = App::from_yaml(yml); - - let arg = app - .get_arguments() - .find(|a| a.get_name() == "value_hint") - .unwrap(); - assert_eq!(arg.get_value_hint(), ValueHint::FilePath); -} - -#[test] -fn default_value_if_not_triggered_by_argument() { - let yml = load_yaml!("fixtures/app.yaml"); - let app = App::from_yaml(yml); - - // Fixtures use "other" as value - let matches = app.try_get_matches_from(vec!["prog", "wrong"]).unwrap(); - - assert!(matches.value_of("positional2").is_none()); -} - -#[test] -fn default_value_if_triggered_by_matching_argument() { - let yml = load_yaml!("fixtures/app.yaml"); - let app = App::from_yaml(yml); - - let matches = app.try_get_matches_from(vec!["prog", "other"]).unwrap(); - assert_eq!(matches.value_of("positional2").unwrap(), "something"); -} - -#[test] -fn default_value_if_triggered_by_flag() { - let yml = load_yaml!("fixtures/app.yaml"); - let app = App::from_yaml(yml); - - let matches = app - .try_get_matches_from(vec!["prog", "--flag", "flagvalue"]) - .unwrap(); - - assert_eq!(matches.value_of("positional2").unwrap(), "some"); -} - -#[test] -fn default_value_if_triggered_by_flag_and_argument() { - let yml = load_yaml!("fixtures/app.yaml"); - let app = App::from_yaml(yml); - - let matches = app - .try_get_matches_from(vec!["prog", "--flag", "flagvalue", "other"]) - .unwrap(); - - // First condition triggers, therefore "some" - assert_eq!(matches.value_of("positional2").unwrap(), "some"); -} - -#[test] -fn yaml_multiple_occurrences() { - let yaml = load_yaml!("fixtures/app.yaml"); - let matches = App::from_yaml(yaml) - .try_get_matches_from(vec!["prog", "-vvv"]) - .unwrap(); - assert_eq!(matches.occurrences_of("verbose"), 3); -} - -#[test] -fn yaml_multiple_values() { - let yaml = load_yaml!("fixtures/app.yaml"); - let matches = App::from_yaml(yaml) - .try_get_matches_from(vec!["prog", "-s", "aaa", "bbb"]) - .unwrap(); - assert_eq!( - matches - .values_of("settings") - .unwrap() - .collect::>(), - vec!["aaa", "bbb"] - ); -} - -#[cfg(feature = "regex")] -#[test] -fn regex_with_invalid_string() { - let yml = load_yaml!("fixtures/app_regex.yaml"); - let app = App::from_yaml(yml); - let res = app.try_get_matches_from(vec!["prog", "not a proper filter"]); - - assert!(res.is_err()); -} - -#[cfg(feature = "regex")] -#[test] -fn regex_with_valid_string() { - let yml = load_yaml!("fixtures/app_regex.yaml"); - let app = App::from_yaml(yml); - - let matches = app.try_get_matches_from(vec!["prog", "*.txt"]).unwrap(); - - assert_eq!(matches.value_of("filter").unwrap(), "*.txt"); -} - -#[cfg(feature = "regex")] -#[test] -#[should_panic] -fn regex_with_invalid_yaml() { - let yml = load_yaml!("fixtures/app_regex_invalid.yaml"); - let _ = App::from_yaml(yml); -} - -#[test] -fn extra_fields() { - let yml = load_yaml!("fixtures/extra_fields.yaml"); - let _ = App::from_yaml(yml); -} - -#[test] -#[should_panic = "Unknown setting 'random' in YAML file for arg 'option'"] -fn extra_fields_invalid_arg() { - let yml = load_yaml!("fixtures/extra_fields_invalid_arg.yaml"); - let _ = App::from_yaml(yml); -} - -#[test] -#[should_panic = "Unknown setting 'random' in YAML file for subcommand 'info'"] -fn extra_fields_invalid_app() { - let yml = load_yaml!("fixtures/extra_fields_invalid_app.yaml"); - let _ = App::from_yaml(yml); -} - -#[test] -#[should_panic = "YAML file must be a hash"] -fn app_not_hash() { - let yml = load_yaml!("fixtures/not_hash.yaml"); - let _ = App::from_yaml(yml); -} - -#[test] -#[should_panic = "YAML file must be a hash"] -fn arg_file_not_hash() { - let yml = load_yaml!("fixtures/not_hash.yaml"); - let _ = Arg::from_yaml(yml); -} - -#[test] -#[should_panic = "Subcommand must be a hash"] -fn subcommand_not_hash() { - let yml = load_yaml!("fixtures/field_not_hash.yaml"); - let _ = App::from_yaml(yml); -} - -#[test] -#[should_panic = "Arg must be a hash"] -fn arg_not_hash() { - let yml = load_yaml!("fixtures/arg_not_hash.yaml"); - let _ = App::from_yaml(yml); -} - -#[test] -#[should_panic = "Subcommand name must be a string"] -fn subcommand_name_not_string() { - let yml = load_yaml!("fixtures/name_not_string.yaml"); - let _ = App::from_yaml(yml); -} - -#[test] -#[should_panic = "Arg name must be a string"] -fn arg_name_not_string() { - let yml = load_yaml!("fixtures/name_not_string.yaml"); - let _ = Arg::from_yaml(yml); -} - -#[test] -#[should_panic = "App fields must be strings"] -fn app_field_not_string() { - let yml = load_yaml!("fixtures/app_field_not_string.yaml"); - let _ = App::from_yaml(yml); -} - -#[test] -#[should_panic = "Arg fields must be strings"] -fn arg_field_not_string() { - let yml = load_yaml!("fixtures/arg_field_not_string.yaml"); - let _ = Arg::from_yaml(yml); -} - -#[test] -fn multiple_groups() { - let yml = load_yaml!("fixtures/multiple_groups.yaml"); - let matches = App::from_yaml(yml).try_get_matches_from(&["app", "-a", "-c"]); - eprintln!("{:?}", matches); - assert!(matches.is_ok()); -}