mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 06:44:16 +00:00
Implement BitOr for settings
This commit is contained in:
parent
5580e8c465
commit
699a3f76d6
12 changed files with 254 additions and 61 deletions
|
@ -499,9 +499,9 @@ features = ["std", "suggestions", "color"]
|
|||
|
||||
#### Opt-in features
|
||||
|
||||
* **"regex"**: Enables regex validators. (builds dependency `regex`)
|
||||
* **"wrap_help"**: Turns on the help text wrapping feature, based on the terminal size. (builds dependency `term-size`)
|
||||
* **"yaml"**: Enables building CLIs from YAML documents. (builds dependency `yaml-rust`)
|
||||
* **regex**: Enables regex validators. (builds dependency `regex`)
|
||||
* **wrap_help**: Turns on the help text wrapping feature, based on the terminal size. (builds dependency `term-size`)
|
||||
* **yaml**: Enables building CLIs from YAML documents. (builds dependency `yaml-rust`)
|
||||
|
||||
### More Information
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ mod settings;
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use self::settings::AppSettings;
|
||||
pub use self::settings::{AppFlags, AppSettings};
|
||||
|
||||
// Std
|
||||
use std::{
|
||||
|
@ -24,7 +24,7 @@ use yaml_rust::Yaml;
|
|||
|
||||
// Internal
|
||||
use crate::{
|
||||
build::{app::settings::AppFlags, arg::ArgProvider, Arg, ArgGroup, ArgSettings},
|
||||
build::{arg::ArgProvider, Arg, ArgGroup, ArgSettings},
|
||||
mkeymap::MKeyMap,
|
||||
output::{fmt::Colorizer, Help, HelpWriter, Usage},
|
||||
parse::{ArgMatcher, ArgMatches, Input, Parser},
|
||||
|
@ -897,9 +897,19 @@ impl<'help> App<'help> {
|
|||
/// .setting(AppSettings::WaitOnError)
|
||||
/// # ;
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, AppSettings};
|
||||
/// App::new("myprog")
|
||||
/// .setting(AppSettings::SubcommandRequired | AppSettings::WaitOnError)
|
||||
/// # ;
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn setting(mut self, setting: AppSettings) -> Self {
|
||||
self.settings.set(setting);
|
||||
pub fn setting<F>(mut self, setting: F) -> Self
|
||||
where
|
||||
F: Into<AppFlags>,
|
||||
{
|
||||
self.settings.insert(setting.into());
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -912,12 +922,23 @@ impl<'help> App<'help> {
|
|||
/// ```no_run
|
||||
/// # use clap::{App, AppSettings};
|
||||
/// App::new("myprog")
|
||||
/// .unset_setting(AppSettings::ColorAuto)
|
||||
/// .unset_setting(AppSettings::SubcommandRequired)
|
||||
/// .unset_setting(AppSettings::WaitOnError)
|
||||
/// # ;
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, AppSettings};
|
||||
/// App::new("myprog")
|
||||
/// .unset_setting(AppSettings::SubcommandRequired | AppSettings::WaitOnError)
|
||||
/// # ;
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn unset_setting(mut self, setting: AppSettings) -> Self {
|
||||
self.settings.unset(setting);
|
||||
pub fn unset_setting<F>(mut self, setting: F) -> Self
|
||||
where
|
||||
F: Into<AppFlags>,
|
||||
{
|
||||
self.settings.remove(setting.into());
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -2889,9 +2910,11 @@ impl<'help> From<&'help Yaml> for App<'help> {
|
|||
}
|
||||
a
|
||||
}
|
||||
"setting" | "settings" => yaml_to_setting!(a, v, setting, "AppSetting", err),
|
||||
"setting" | "settings" => {
|
||||
yaml_to_setting!(a, v, setting, AppSettings, "AppSetting", err)
|
||||
}
|
||||
"global_setting" | "global_settings" => {
|
||||
yaml_to_setting!(a, v, global_setting, "AppSetting", err)
|
||||
yaml_to_setting!(a, v, global_setting, AppSettings, "AppSetting", err)
|
||||
}
|
||||
"name" => continue,
|
||||
s => {
|
||||
|
|
|
@ -53,15 +53,9 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct AppFlags(Flags);
|
||||
|
||||
impl BitOr for AppFlags {
|
||||
type Output = Self;
|
||||
fn bitor(self, rhs: Self) -> Self {
|
||||
AppFlags(self.0 | rhs.0)
|
||||
}
|
||||
}
|
||||
pub struct AppFlags(Flags);
|
||||
|
||||
impl Default for AppFlags {
|
||||
fn default() -> Self {
|
||||
|
|
|
@ -77,7 +77,7 @@ impl<'help> ArgValue<'help> {
|
|||
/// ArgValue::new("fast")
|
||||
/// # ;
|
||||
/// ```
|
||||
/// [hidden]: ArgValue::hide
|
||||
/// [hidden]: ArgValue::hidden
|
||||
/// [possible value]: crate::Arg::possible_values
|
||||
/// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values()
|
||||
pub fn new(name: &'help str) -> Self {
|
||||
|
|
|
@ -7,7 +7,7 @@ mod tests;
|
|||
mod value_hint;
|
||||
|
||||
pub use self::arg_value::ArgValue;
|
||||
pub use self::settings::ArgSettings;
|
||||
pub use self::settings::{ArgFlags, ArgSettings};
|
||||
pub use self::value_hint::ValueHint;
|
||||
|
||||
// Std
|
||||
|
@ -32,7 +32,7 @@ use yaml_rust::Yaml;
|
|||
|
||||
// Internal
|
||||
use crate::{
|
||||
build::{arg::settings::ArgFlags, usage_parser::UsageParser},
|
||||
build::usage_parser::UsageParser,
|
||||
util::{Id, Key},
|
||||
INTERNAL_ERROR_MSG,
|
||||
};
|
||||
|
@ -4635,9 +4635,19 @@ impl<'help> Arg<'help> {
|
|||
/// .setting(ArgSettings::TakesValue)
|
||||
/// # ;
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{Arg, ArgSettings};
|
||||
/// Arg::new("config")
|
||||
/// .setting(ArgSettings::Required | ArgSettings::TakesValue)
|
||||
/// # ;
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn setting(mut self, setting: ArgSettings) -> Self {
|
||||
self.settings.set(setting);
|
||||
pub fn setting<F>(mut self, setting: F) -> Self
|
||||
where
|
||||
F: Into<ArgFlags>,
|
||||
{
|
||||
self.settings.insert(setting.into());
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -4651,11 +4661,22 @@ impl<'help> Arg<'help> {
|
|||
/// # use clap::{Arg, ArgSettings};
|
||||
/// Arg::new("config")
|
||||
/// .unset_setting(ArgSettings::Required)
|
||||
/// .unset_setting(ArgSettings::TakesValue)
|
||||
/// # ;
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{Arg, ArgSettings};
|
||||
/// Arg::new("config")
|
||||
/// .unset_setting(ArgSettings::Required | ArgSettings::TakesValue)
|
||||
/// # ;
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn unset_setting(mut self, setting: ArgSettings) -> Self {
|
||||
self.settings.unset(setting);
|
||||
pub fn unset_setting<F>(mut self, setting: F) -> Self
|
||||
where
|
||||
F: Into<ArgFlags>,
|
||||
{
|
||||
self.settings.remove(setting.into());
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -4889,7 +4910,14 @@ impl<'help> From<&'help Yaml> for Arg<'help> {
|
|||
}
|
||||
}
|
||||
"setting" | "settings" => {
|
||||
yaml_to_setting!(a, v, setting, "ArgSetting", format!("arg '{}'", name_str))
|
||||
yaml_to_setting!(
|
||||
a,
|
||||
v,
|
||||
setting,
|
||||
ArgSettings,
|
||||
"ArgSetting",
|
||||
format!("arg '{}'", name_str)
|
||||
)
|
||||
}
|
||||
s => {
|
||||
if !has_metadata {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Std
|
||||
use std::str::FromStr;
|
||||
use std::{ops::BitOr, str::FromStr};
|
||||
|
||||
// Third party
|
||||
use bitflags::bitflags;
|
||||
|
@ -34,8 +34,15 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(crate) struct ArgFlags(Flags);
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct ArgFlags(Flags);
|
||||
|
||||
impl Default for ArgFlags {
|
||||
fn default() -> Self {
|
||||
Self::empty()
|
||||
}
|
||||
}
|
||||
|
||||
// @TODO @p6 @internal: Reorder alphabetically
|
||||
impl_settings! { ArgSettings, ArgFlags,
|
||||
|
@ -64,12 +71,6 @@ impl_settings! { ArgSettings, ArgFlags,
|
|||
AllowInvalidUtf8("allowinvalidutf8") => Flags::UTF8_NONE
|
||||
}
|
||||
|
||||
impl Default for ArgFlags {
|
||||
fn default() -> Self {
|
||||
ArgFlags(Flags::empty())
|
||||
}
|
||||
}
|
||||
|
||||
/// Various settings that apply to arguments and may be set, unset, and checked via getter/setter
|
||||
/// methods [`Arg::setting`], [`Arg::unset_setting`], and [`Arg::is_set`]. This is what the
|
||||
/// [`Arg`] methods which accept a `bool` use internally.
|
||||
|
|
|
@ -213,11 +213,11 @@ macro_rules! yaml_to_usize {
|
|||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_to_setting {
|
||||
($a:ident, $v:ident, $c:ident, $t:literal, $n:expr) => {{
|
||||
($a:ident, $v:ident, $c:ident, $s:ident, $t:literal, $n:expr) => {{
|
||||
if let Some(v) = $v.as_vec() {
|
||||
for ys in v {
|
||||
if let Some(s) = ys.as_str() {
|
||||
$a = $a.$c(s.parse().unwrap_or_else(|_| {
|
||||
$a = $a.$c(s.parse::<$s>().unwrap_or_else(|_| {
|
||||
panic!("Unknown {} '{}' found in YAML file for {}", $t, s, $n)
|
||||
}));
|
||||
} else {
|
||||
|
@ -229,7 +229,7 @@ macro_rules! yaml_to_setting {
|
|||
}
|
||||
} else if let Some(v) = $v.as_str() {
|
||||
$a = $a.$c(v
|
||||
.parse()
|
||||
.parse::<$s>()
|
||||
.unwrap_or_else(|_| panic!("Unknown {} '{}' found in YAML file for {}", $t, v, $n)))
|
||||
} else {
|
||||
panic!("Failed to convert YAML {:?} value to a string", $v);
|
||||
|
|
|
@ -8,7 +8,7 @@ mod arg_group;
|
|||
mod usage_parser;
|
||||
|
||||
pub use self::{
|
||||
app::{App, AppSettings},
|
||||
arg::{Arg, ArgSettings, ArgValue, ValueHint},
|
||||
app::{App, AppFlags, AppSettings},
|
||||
arg::{Arg, ArgFlags, ArgSettings, ArgValue, ValueHint},
|
||||
arg_group::ArgGroup,
|
||||
};
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
compile_error!("`std` feature is currently required to build `clap`");
|
||||
|
||||
pub use crate::{
|
||||
build::{App, AppSettings, Arg, ArgGroup, ArgSettings, ArgValue, ValueHint},
|
||||
build::{
|
||||
App, AppFlags, AppSettings, Arg, ArgFlags, ArgGroup, ArgSettings, ArgValue, ValueHint,
|
||||
},
|
||||
parse::errors::{Error, ErrorKind, Result},
|
||||
parse::{ArgMatches, Indices, OsValues, Values},
|
||||
};
|
||||
|
|
|
@ -532,6 +532,18 @@ macro_rules! impl_settings {
|
|||
),+
|
||||
) => {
|
||||
impl $flags {
|
||||
pub(crate) fn empty() -> Self {
|
||||
$flags(Flags::empty())
|
||||
}
|
||||
|
||||
pub(crate) fn insert(&mut self, rhs: Self) {
|
||||
self.0.insert(rhs.0);
|
||||
}
|
||||
|
||||
pub(crate) fn remove(&mut self, rhs: Self) {
|
||||
self.0.remove(rhs.0);
|
||||
}
|
||||
|
||||
pub(crate) fn set(&mut self, s: $settings) {
|
||||
match s {
|
||||
$(
|
||||
|
@ -560,6 +572,43 @@ macro_rules! impl_settings {
|
|||
}
|
||||
}
|
||||
|
||||
impl BitOr for $flags {
|
||||
type Output = Self;
|
||||
|
||||
fn bitor(mut self, rhs: Self) -> Self::Output {
|
||||
self.0.insert(rhs.0);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$settings> for $flags {
|
||||
fn from(setting: $settings) -> Self {
|
||||
let mut flags = $flags::empty();
|
||||
flags.set(setting);
|
||||
flags
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr<$settings> for $flags {
|
||||
type Output = Self;
|
||||
|
||||
fn bitor(mut self, rhs: $settings) -> Self::Output {
|
||||
self.set(rhs);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr for $settings {
|
||||
type Output = $flags;
|
||||
|
||||
fn bitor(self, rhs: Self) -> Self::Output {
|
||||
let mut flags = $flags::empty();
|
||||
flags.set(self);
|
||||
flags.set(rhs);
|
||||
flags
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for $settings {
|
||||
type Err = String;
|
||||
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
|
||||
|
|
|
@ -148,6 +148,75 @@ SUBCOMMANDS:
|
|||
Print this message or the help of the given subcommand(s)
|
||||
test";
|
||||
|
||||
#[test]
|
||||
fn setting() {
|
||||
let m = App::new("setting").setting(AppSettings::AllArgsOverrideSelf);
|
||||
assert!(m.is_set(AppSettings::AllArgsOverrideSelf));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn global_setting() {
|
||||
let m = App::new("global_setting").global_setting(AppSettings::AllArgsOverrideSelf);
|
||||
assert!(m.is_set(AppSettings::AllArgsOverrideSelf));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unset_setting() {
|
||||
let m = App::new("unset_setting").setting(AppSettings::AllArgsOverrideSelf);
|
||||
assert!(m.is_set(AppSettings::AllArgsOverrideSelf));
|
||||
|
||||
let m = m.unset_setting(AppSettings::AllArgsOverrideSelf);
|
||||
assert!(!m.is_set(AppSettings::AllArgsOverrideSelf), "{:#?}", m);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unset_global_setting() {
|
||||
let m = App::new("unset_global_setting").global_setting(AppSettings::AllArgsOverrideSelf);
|
||||
assert!(m.is_set(AppSettings::AllArgsOverrideSelf));
|
||||
|
||||
let m = m.unset_global_setting(AppSettings::AllArgsOverrideSelf);
|
||||
assert!(!m.is_set(AppSettings::AllArgsOverrideSelf), "{:#?}", m);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unset_on_global_setting() {
|
||||
let m = App::new("unset_on_global_setting").global_setting(AppSettings::AllArgsOverrideSelf);
|
||||
assert!(m.is_set(AppSettings::AllArgsOverrideSelf));
|
||||
|
||||
let m = m.unset_setting(AppSettings::AllArgsOverrideSelf);
|
||||
assert!(m.is_set(AppSettings::AllArgsOverrideSelf), "{:#?}", m);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn setting_bitor() {
|
||||
let m = App::new("setting_bitor").setting(
|
||||
AppSettings::InferSubcommands | AppSettings::Hidden | AppSettings::DisableHelpSubcommand,
|
||||
);
|
||||
|
||||
assert!(m.is_set(AppSettings::InferSubcommands));
|
||||
assert!(m.is_set(AppSettings::Hidden));
|
||||
assert!(m.is_set(AppSettings::DisableHelpSubcommand));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unset_setting_bitor() {
|
||||
let m = App::new("unset_setting_bitor")
|
||||
.setting(AppSettings::InferSubcommands)
|
||||
.setting(AppSettings::Hidden)
|
||||
.setting(AppSettings::DisableHelpSubcommand);
|
||||
|
||||
assert!(m.is_set(AppSettings::InferSubcommands));
|
||||
assert!(m.is_set(AppSettings::Hidden));
|
||||
assert!(m.is_set(AppSettings::DisableHelpSubcommand));
|
||||
|
||||
let m = m.unset_setting(
|
||||
AppSettings::InferSubcommands | AppSettings::Hidden | AppSettings::DisableHelpSubcommand,
|
||||
);
|
||||
assert!(!m.is_set(AppSettings::InferSubcommands), "{:#?}", m);
|
||||
assert!(!m.is_set(AppSettings::Hidden), "{:#?}", m);
|
||||
assert!(!m.is_set(AppSettings::DisableHelpSubcommand), "{:#?}", m);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sub_command_negate_required() {
|
||||
App::new("sub_command_negate")
|
||||
|
@ -583,24 +652,6 @@ fn leading_double_hyphen_trailingvararg() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unset_setting() {
|
||||
let m = App::new("unset_setting").setting(AppSettings::AllArgsOverrideSelf);
|
||||
assert!(m.is_set(AppSettings::AllArgsOverrideSelf));
|
||||
|
||||
let m = m.unset_setting(AppSettings::AllArgsOverrideSelf);
|
||||
assert!(!m.is_set(AppSettings::AllArgsOverrideSelf));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unset_settings() {
|
||||
let m = App::new("unset_settings");
|
||||
assert!(&m.is_set(AppSettings::ColorAuto));
|
||||
|
||||
let m = m.unset_global_setting(AppSettings::ColorAuto);
|
||||
assert!(!m.is_set(AppSettings::ColorAuto), "{:#?}", m);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disable_help_subcommand() {
|
||||
let result = App::new("disablehelp")
|
||||
|
|
45
tests/arg_settings.rs
Normal file
45
tests/arg_settings.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
mod utils;
|
||||
|
||||
use clap::{Arg, ArgSettings};
|
||||
|
||||
#[test]
|
||||
fn setting() {
|
||||
let m = Arg::new("setting").setting(ArgSettings::Required);
|
||||
assert!(m.is_set(ArgSettings::Required));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unset_setting() {
|
||||
let m = Arg::new("unset_setting").setting(ArgSettings::Required);
|
||||
assert!(m.is_set(ArgSettings::Required));
|
||||
|
||||
let m = m.unset_setting(ArgSettings::Required);
|
||||
assert!(!m.is_set(ArgSettings::Required), "{:#?}", m);
|
||||
}
|
||||
|
||||
#[test]
|
||||
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));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unset_setting_bitor() {
|
||||
let m = Arg::new("unset_setting_bitor")
|
||||
.setting(ArgSettings::Required)
|
||||
.setting(ArgSettings::Hidden)
|
||||
.setting(ArgSettings::Last);
|
||||
|
||||
assert!(m.is_set(ArgSettings::Required));
|
||||
assert!(m.is_set(ArgSettings::Hidden));
|
||||
assert!(m.is_set(ArgSettings::Last));
|
||||
|
||||
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);
|
||||
}
|
Loading…
Reference in a new issue