fix: Deprecate various APIs

- ArgSettings are part of #2717
- Errors are part of #2628
- `help_heading` is part of #1807 and #1553
- Some misc parts are for API consistency
This commit is contained in:
Ed Page 2022-02-10 19:30:32 -06:00
parent 48686804c7
commit 9bd7060089
12 changed files with 158 additions and 203 deletions

View file

@ -153,7 +153,7 @@ fn value_completion(option: &Arg) -> String {
format!(
" -r -f -a \"{{{}}}\"",
data.iter()
.filter_map(|value| if value.is_hidden() {
.filter_map(|value| if value.is_hide_set() {
None
} else {
Some(format!(

View file

@ -515,7 +515,7 @@ fn arg_conflicts(app: &App, arg: &Arg, app_global: Option<&App>) -> String {
}
let mut res = vec![];
match (app_global, arg.get_global()) {
match (app_global, arg.is_global_set()) {
(Some(x), true) => {
let conflicts = x.get_arg_conflicts_with(arg);

View file

@ -1325,20 +1325,10 @@ impl<'help> App<'help> {
}
}
/// Set the default section heading for future args.
///
/// This will be used for any arg that hasn't had [`Arg::help_heading`] called.
///
/// This is useful if the default `OPTIONS` or `ARGS` headings are
/// not specific enough for one's use case.
///
/// For subcommands, see [`App::subcommand_help_heading`]
///
/// [`App::arg`]: App::arg()
/// [`Arg::help_heading`]: crate::Arg::help_heading()
/// Deprecated, replaced with [`App::next_help_heading`]
#[inline]
#[must_use]
// TODO: Deprecate
#[deprecated(since = "3.1.0", note = "Replaced with `App::next_help_heading`")]
pub fn help_heading<O>(self, heading: O) -> Self
where
O: Into<Option<&'help str>>,
@ -2197,11 +2187,9 @@ impl<'help> App<'help> {
self.long_about
}
/// Get the custom section heading specified via [`App::help_heading`].
///
/// [`App::help_heading`]: App::help_heading()
/// Deprecated, replaced with [`App::get_next_help_heading`]
#[inline]
// TODO: Deprecate
#[deprecated(since = "3.1.0", note = "Replaced with `App::get_next_help_heading`")]
pub fn get_help_heading(&self) -> Option<&'help str> {
self.get_next_help_heading()
}

View file

@ -1,3 +1,5 @@
#![allow(deprecated)]
// Std
use std::{
borrow::Cow,
@ -872,7 +874,6 @@ impl<'help> Arg<'help> {
///
/// [`ArgSettings`]: crate::ArgSettings
#[inline]
// TODO: Deprecate
pub fn is_set(&self, s: ArgSettings) -> bool {
self.settings.is_set(s)
}
@ -899,7 +900,6 @@ impl<'help> Arg<'help> {
/// ```
#[inline]
#[must_use]
// TODO: Deprecate
pub fn setting<F>(mut self, setting: F) -> Self
where
F: Into<ArgFlags>,
@ -930,7 +930,6 @@ impl<'help> Arg<'help> {
/// ```
#[inline]
#[must_use]
// TODO: Deprecate
pub fn unset_setting<F>(mut self, setting: F) -> Self
where
F: Into<ArgFlags>,
@ -2128,58 +2127,10 @@ impl<'help> Arg<'help> {
}
}
/// Specifies that an argument should allow grouping of multiple values via a
/// delimiter.
///
/// i.e. should `--option=val1,val2,val3` be parsed as three values (`val1`, `val2`,
/// and `val3`) or as a single value (`val1,val2,val3`). Defaults to using `,` (comma) as the
/// value delimiter for all arguments that accept values (options and positional arguments)
///
/// **NOTE:** When this setting is used, it will default [`Arg::value_delimiter`]
/// to the comma `,`.
///
/// **NOTE:** Implicitly sets [`Arg::takes_value`]
///
/// # Examples
///
/// The following example shows the default behavior.
///
/// ```rust
/// # use clap::{App, Arg};
/// let delims = App::new("prog")
/// .arg(Arg::new("option")
/// .long("option")
/// .use_delimiter(true)
/// .takes_value(true))
/// .get_matches_from(vec![
/// "prog", "--option=val1,val2,val3",
/// ]);
///
/// assert!(delims.is_present("option"));
/// assert_eq!(delims.occurrences_of("option"), 1);
/// assert_eq!(delims.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
/// ```
/// The next example shows the difference when turning delimiters off. This is the default
/// behavior
///
/// ```rust
/// # use clap::{App, Arg};
/// let nodelims = App::new("prog")
/// .arg(Arg::new("option")
/// .long("option")
/// .takes_value(true))
/// .get_matches_from(vec![
/// "prog", "--option=val1,val2,val3",
/// ]);
///
/// assert!(nodelims.is_present("option"));
/// assert_eq!(nodelims.occurrences_of("option"), 1);
/// assert_eq!(nodelims.value_of("option").unwrap(), "val1,val2,val3");
/// ```
/// [`Arg::value_delimiter`]: Arg::value_delimiter()
/// Deprecated, replaced with [`Arg::use_value_delimiter`]
#[inline]
#[must_use]
// TODO: Deprecate
#[deprecated(since = "3.1.0", note = "Replaced with `Arg::use_value_delimiter`")]
pub fn use_delimiter(self, yes: bool) -> Self {
self.use_value_delimiter(yes)
}
@ -2300,85 +2251,10 @@ impl<'help> Arg<'help> {
}
}
/// Specifies that *multiple values* may only be set using the delimiter.
///
/// This means if an option is encountered, and no delimiter is found, it is assumed that no
/// additional values for that option follow. This is unlike the default, where it is generally
/// assumed that more values will follow regardless of whether or not a delimiter is used.
///
/// **NOTE:** The default is `false`.
///
/// **NOTE:** Setting this requires [`Arg::use_value_delimiter`] and
/// [`Arg::takes_value`]
///
/// **NOTE:** It's a good idea to inform the user that use of a delimiter is required, either
/// through help text or other means.
///
/// # Examples
///
/// These examples demonstrate what happens when `require_delimiter(true)` is used. Notice
/// everything works in this first example, as we use a delimiter, as expected.
///
/// ```rust
/// # use clap::{App, Arg};
/// let delims = App::new("prog")
/// .arg(Arg::new("opt")
/// .short('o')
/// .takes_value(true)
/// .use_value_delimiter(true)
/// .require_delimiter(true)
/// .multiple_values(true))
/// .get_matches_from(vec![
/// "prog", "-o", "val1,val2,val3",
/// ]);
///
/// assert!(delims.is_present("opt"));
/// assert_eq!(delims.values_of("opt").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
/// ```
///
/// In this next example, we will *not* use a delimiter. Notice it's now an error.
///
/// ```rust
/// # use clap::{App, Arg, ErrorKind};
/// let res = App::new("prog")
/// .arg(Arg::new("opt")
/// .short('o')
/// .takes_value(true)
/// .use_value_delimiter(true)
/// .require_delimiter(true))
/// .try_get_matches_from(vec![
/// "prog", "-o", "val1", "val2", "val3",
/// ]);
///
/// assert!(res.is_err());
/// let err = res.unwrap_err();
/// assert_eq!(err.kind(), ErrorKind::UnknownArgument);
/// ```
///
/// What's happening is `-o` is getting `val1`, and because delimiters are required yet none
/// were present, it stops parsing `-o`. At this point it reaches `val2` and because no
/// positional arguments have been defined, it's an error of an unexpected argument.
///
/// In this final example, we contrast the above with `clap`'s default behavior where the above
/// is *not* an error.
///
/// ```rust
/// # use clap::{App, Arg};
/// let delims = App::new("prog")
/// .arg(Arg::new("opt")
/// .short('o')
/// .takes_value(true)
/// .multiple_values(true))
/// .get_matches_from(vec![
/// "prog", "-o", "val1", "val2", "val3",
/// ]);
///
/// assert!(delims.is_present("opt"));
/// assert_eq!(delims.values_of("opt").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
/// ```
/// Deprecated, replaced with [`Arg::require_value_delimiter`]
#[inline]
#[must_use]
// TODO: Deprecate
#[deprecated(since = "3.1.0", note = "Replaced with `Arg::require_value_delimiter`")]
pub fn require_delimiter(self, yes: bool) -> Self {
self.require_value_delimiter(yes)
}
@ -4751,8 +4627,8 @@ impl<'help> Arg<'help> {
self.value_hint
}
/// Get information on if this argument is global or not
// TODO: Deprecate
/// Deprecated, replaced with [`Arg::is_global_set`]
#[deprecated(since = "3.1.0", note = "Replaced with `Arg::is_global_set`")]
pub fn get_global(&self) -> bool {
self.is_global_set()
}

View file

@ -1,3 +1,5 @@
#![allow(deprecated)]
// Std
use std::ops::BitOr;
#[cfg(feature = "yaml")]
@ -6,6 +8,9 @@ use std::str::FromStr;
// Third party
use bitflags::bitflags;
#[allow(unused)]
use crate::Arg;
#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArgFlags(Flags);
@ -26,13 +31,25 @@ impl Default for ArgFlags {
/// [`Arg::is_set`]: crate::Arg::is_set()
#[derive(Debug, PartialEq, Copy, Clone)]
#[non_exhaustive]
// TODO: Deprecate
pub enum ArgSettings {
/// Specifies that an arg must be used
/// Deprecated, replaced with [`Arg::required`] and [`Arg::is_required_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::required` and `Arg::is_required_set`"
)]
Required,
/// Allows an arg to accept multiple values
/// Deprecated, replaced with [`Arg::multiple_values`] and [`Arg::is_multiple_values_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::multiple_values` and `Arg::`is_multiple_values_set`"
)]
MultipleValues,
/// Allows an arg to appear multiple times
/// Deprecated, replaced with [`Arg::multiple_occurrences`] and
/// [`Arg::is_multiple_occurrences_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::multiple_occurrences` and `Arg::is_multiple_occurrences_set`"
)]
MultipleOccurrences,
/// Deprecated, see [`ArgSettings::MultipleOccurrences`] (most likely what you want) and
/// [`ArgSettings::MultipleValues`]
@ -41,24 +58,64 @@ pub enum ArgSettings {
note = "Split into `ArgSettings::MultipleOccurrences` (most likely what you want) and `ArgSettings::MultipleValues`"
)]
Multiple,
/// Forbids an arg from accepting empty values such as `""`
/// Deprecated, replaced with [`Arg::forbid_empty_values`] and
/// [`Arg::is_forbid_empty_values_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::forbid_empty_values` and `Arg::is_forbid_empty_values_set`"
)]
ForbidEmptyValues,
/// Sets an arg to be global (i.e. exist in all subcommands)
/// Deprecated, replaced with [`Arg::global`] and [`Arg::is_global_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::global` and `Arg::is_global_set`"
)]
Global,
/// Hides an arg from the help message
/// Deprecated, replaced with [`Arg::hide`] and [`Arg::is_hide_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide` and `Arg::is_hide_set`"
)]
Hidden,
/// Allows an argument to take a value (such as `--option value`)
/// Deprecated, replaced with [`Arg::takes_value`] and [`Arg::is_takes_value_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::takes_value` and `Arg::is_takes_value_set`"
)]
TakesValue,
/// Enables a delimiter to break up arguments `--option val1,val2,val3` becomes three values
/// (`val1`, `val2`, and `val3`) instead of the default one (`val1,val2,val3`)
/// Deprecated, replaced with [`Arg::use_value_delimiter`] and
/// [`Arg::is_use_value_delimiter_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::use_value_delimiter` and `Arg::is_use_value_delimiter_set`"
)]
UseValueDelimiter,
/// Tells an arg to display it's help on the line below the arg itself in the help message
/// Deprecated, replaced with [`Arg::next_line_help`] and [`Arg::is_next_line_help_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::next_line_help` and `Arg::is_next_line_help_set`"
)]
NextLineHelp,
/// Says that arg *must* use a delimiter to separate values
/// Deprecated, replaced with [`Arg::require_value_delimiter`] and
/// [`Arg::is_require_value_delimiter_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::require_value_delimiter` and `Arg::is_require_value_delimiter_set`"
)]
RequireDelimiter,
/// Hides the possible values from the help message
/// Deprecated, replaced with [`Arg::hide_possible_values`] and
/// [`Arg::is_hide_possible_values_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_possible_values` and `Arg::is_hide_possible_values_set`"
)]
HidePossibleValues,
/// Allows values that start with a hyphen
/// Deprecated, replaced with [`Arg::allow_hyphen_values`] and
/// [`Arg::is_allow_hyphen_values_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::allow_hyphen_values` and `Arg::is_allow_hyphen_values_set`"
)]
AllowHyphenValues,
/// Deprecated, replaced with [`ArgSettings::AllowHyphenValues`]
#[deprecated(
@ -66,33 +123,70 @@ pub enum ArgSettings {
note = "Replaced with `ArgSettings::AllowHyphenValues`"
)]
AllowLeadingHyphen,
/// Requires that an equals be used to provide a value to an option such as `--option=value`
/// Deprecated, replaced with [`Arg::require_equals`] and [`Arg::is_require_equals_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::require_equals` and `Arg::is_require_equals_set`"
)]
RequireEquals,
/// Says that a positional arg will be the last positional, and requires `--` to be accessed.
/// It can also be accessed early (i.e. before other positionals) by providing `--`
/// Deprecated, replaced with [`Arg::last`] and [`Arg::is_last_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::last` and `Arg::is_last_set`"
)]
Last,
/// Hides the default value from the help message
/// Deprecated, replaced with [`Arg::hide_default_value`] and [`Arg::is_hide_default_value_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_default_value` and `Arg::is_hide_default_value_set`"
)]
HideDefaultValue,
/// Possible values become case insensitive
/// Deprecated, replaced with [`Arg::ignore_case`] and [`Arg::is_ignore_case_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::ignore_case` and `Arg::is_ignore_case_set`"
)]
IgnoreCase,
/// Deprecated, replaced with [`ArgSettings::IgnoreCase`]
#[deprecated(since = "3.0.0", note = "Replaced with `ArgSettings::IgnoreCase`")]
CaseInsensitive,
/// Hides environment variable arguments from the help message
/// Deprecated, replaced with [`Arg::hide_env`] and [`Arg::is_hide_env_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_env` and `Arg::is_hide_env_set`"
)]
#[cfg(feature = "env")]
HideEnv,
/// Hides any values currently assigned to ENV variables in the help message (good for sensitive
/// information)
/// Deprecated, replaced with [`Arg::hide_env_values`] and [`Arg::is_hide_env_values_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_env_values` and `Arg::is_hide_env_values_set`"
)]
#[cfg(feature = "env")]
HideEnvValues,
/// The argument should **not** be shown in short help text
/// Deprecated, replaced with [`Arg::hide_short_help`] and [`Arg::is_hide_short_help_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_short_help` and `Arg::is_hide_short_help_set`"
)]
HiddenShortHelp,
/// The argument should **not** be shown in long help text
/// Deprecated, replaced with [`Arg::hide_long_help`] and [`Arg::is_hide_long_help_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::hide_long_help` and `Arg::is_hide_long_help_set`"
)]
HiddenLongHelp,
/// Specifies that option values that are invalid UTF-8 should *not* be treated as an error.
/// Deprecated, replaced with [`Arg::allow_invalid_utf8`] and [`Arg::is_allow_invalid_utf8_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::allow_invalid_utf8` and `Arg::is_allow_invalid_utf8_set`"
)]
AllowInvalidUtf8,
/// Specifies that option should exist on its own.
/// Having any other arguments present at runtime is an error.
/// Deprecated, replaced with [`Arg::exclusive`] and [`Arg::is_exclusive_set`]
#[deprecated(
since = "3.1.0",
note = "Replaced with `Arg::exclusive` and `Arg::is_exclusive_set`"
)]
Exclusive,
}

View file

@ -148,9 +148,9 @@ impl<'help> PossibleValue<'help> {
self.help
}
/// Should the value be hidden from help messages and completion
/// Deprecated, replaced with [`PossibleValue::is_hide_set`]
#[inline]
// TODO: Deprecate
#[deprecated(since = "3.1.0", note = "Replaced with `PossibleValue::is_hide_set`")]
pub fn is_hidden(&self) -> bool {
self.is_hide_set()
}

View file

@ -1,3 +1,5 @@
#![allow(deprecated)]
// Internal
use crate::{
build::{Arg, ArgSettings},

View file

@ -1,4 +1,5 @@
//! Error reporting
#![allow(deprecated)]
// Std
use std::{
@ -39,12 +40,11 @@ pub type Result<T, E = Error> = StdResult<T, E>;
#[derive(Debug)]
pub struct Error {
inner: Box<ErrorInner>,
/// The type of error
// TODO: Deprecate
/// Deprecated, replaced with [`Error::kind()`]
#[deprecated(since = "3.1.0", note = "Replaced with `Error::kind()`")]
pub kind: ErrorKind,
/// Additional information depending on the error kind, like values and argument names.
/// Useful when you want to render an error of your own.
// TODO: Deprecate
/// Deprecated, replaced with [`Error::context()`]
#[deprecated(since = "3.1.0", note = "Replaced with `Error::context()`")]
pub info: Vec<String>,
}

View file

@ -1067,7 +1067,7 @@ fn aaos_opts_mult() {
.number_of_values(1)
.takes_value(true)
.use_value_delimiter(true)
.require_delimiter(true),
.require_value_delimiter(true),
)
.try_get_matches_from(vec!["", "--opt=some", "--opt=other", "--opt=one,two"]);
assert!(res.is_ok(), "{}", res.unwrap_err());

View file

@ -1,18 +1,19 @@
#![allow(deprecated)]
use clap::{Arg, ArgSettings};
#[test]
fn setting() {
let m = Arg::new("setting").setting(ArgSettings::Required);
assert!(m.is_set(ArgSettings::Required));
assert!(m.is_required_set());
}
#[test]
fn unset_setting() {
let m = Arg::new("unset_setting").setting(ArgSettings::Required);
assert!(m.is_set(ArgSettings::Required));
assert!(m.is_required_set());
let m = m.unset_setting(ArgSettings::Required);
assert!(!m.is_set(ArgSettings::Required), "{:#?}", m);
assert!(!m.is_required_set(), "{:#?}", m);
}
#[test]
@ -20,9 +21,9 @@ fn setting_bitor() {
let m = Arg::new("setting_bitor")
.setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
assert!(m.is_set(ArgSettings::Required));
assert!(m.is_set(ArgSettings::Hidden));
assert!(m.is_set(ArgSettings::Last));
assert!(m.is_required_set());
assert!(m.is_hide_set());
assert!(m.is_last_set());
}
#[test]
@ -32,12 +33,12 @@ fn unset_setting_bitor() {
.setting(ArgSettings::Hidden)
.setting(ArgSettings::Last);
assert!(m.is_set(ArgSettings::Required));
assert!(m.is_set(ArgSettings::Hidden));
assert!(m.is_set(ArgSettings::Last));
assert!(m.is_required_set());
assert!(m.is_hide_set());
assert!(m.is_last_set());
let m = m.unset_setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
assert!(!m.is_set(ArgSettings::Required), "{:#?}", m);
assert!(!m.is_set(ArgSettings::Hidden), "{:#?}", m);
assert!(!m.is_set(ArgSettings::Last), "{:#?}", m);
assert!(!m.is_required_set(), "{:#?}", m);
assert!(!m.is_hide_set(), "{:#?}", m);
assert!(!m.is_last_set(), "{:#?}", m);
}

View file

@ -2643,7 +2643,6 @@ fn disabled_help_flag() {
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::UnrecognizedSubcommand);
assert_eq!(err.info, &["a"]);
}
#[test]
@ -2656,7 +2655,6 @@ fn disabled_help_flag_and_subcommand() {
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::UnrecognizedSubcommand);
assert_eq!(err.info, &["help"]);
assert!(
err.to_string().ends_with('\n'),
"Errors should have a trailing newline, got {:?}",

View file

@ -27,7 +27,6 @@ fn no_version_flag_short() {
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument);
assert_eq!(err.info, ["-V"]);
}
#[test]
@ -37,7 +36,6 @@ fn no_version_flag_long() {
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument);
assert_eq!(err.info, ["--version"]);
}
#[test]
@ -178,7 +176,6 @@ fn no_propagation_by_default_long() {
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::UnknownArgument);
assert_eq!(err.info, &["--version"]);
}
#[test]
@ -188,7 +185,6 @@ fn no_propagation_by_default_short() {
assert!(res.is_err());
let err = res.unwrap_err();
assert_eq!(err.kind(), ErrorKind::UnknownArgument);
assert_eq!(err.info, &["-V"]);
}
#[test]