diff --git a/Cargo.toml b/Cargo.toml index ede34f66afc..df31c2af644 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ is-it-maintained-open-issues = { repository = "clap-rs/clap" } maintenance = {status = "actively-developed"} [dependencies] +bitflags = "1.0" unicode-width = "0.1.4" textwrap = "0.10.0" strsim = { version = "0.8", optional = true } diff --git a/src/app/parser.rs b/src/app/parser.rs index 36ff48f7202..cb367cf6c66 100644 --- a/src/app/parser.rs +++ b/src/app/parser.rs @@ -407,8 +407,8 @@ where sc.p.set(AS::GlobalVersion); sc.p.meta.version = Some(self.meta.version.unwrap()); } - sc.p.settings.update(&self.g_settings); - sc.p.g_settings.update(&self.g_settings); + sc.p.settings = sc.p.settings | self.g_settings; + sc.p.g_settings = sc.p.g_settings | self.g_settings; sc.p.meta.term_w = self.meta.term_w; sc.p.meta.max_w = self.meta.max_w; } @@ -767,7 +767,7 @@ where pb.b.help = Some("The subcommand whose help message to display"); pb.set(ArgSettings::Multiple); sc.positionals.insert(1, pb); - sc.settings.update(&self.g_settings); + sc.settings = sc.settings | self.g_settings; } else { sc.create_help_and_version(); } diff --git a/src/app/settings.rs b/src/app/settings.rs index ac52f7d2455..4e7c6b5b928 100644 --- a/src/app/settings.rs +++ b/src/app/settings.rs @@ -1,122 +1,120 @@ // Std -use std::collections::HashSet; #[allow(deprecated, unused_imports)] use std::ascii::AsciiExt; use std::str::FromStr; +use std::ops::BitOr; -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -enum Flags { - ScNegateReqs, - ScRequired, - ARequiredElseHelp, - GlobalVersion, - VersionlessSc, - UnifiedHelp, - WaitOnError, - ScRequiredElseHelp, - NeedsLongHelp, - NeedsLongVersion, - NeedsScHelp, - DisableVersion, - Hidden, - TrailingVararg, - NoBinName, - AllowUnkSc, - Utf8Strict, - Utf8None, - LeadingHyphen, - NoPosValues, - NextLineHelp, - DeriveDispOrder, - ColoredHelp, - ColorAlways, - ColorAuto, - ColorNever, - DontDelimTrail, - AllowNegNums, - LowIndexMulPos, - DisableHelpSc, - DontCollapseArgs, - ArgsNegateScs, - PropagateValsDown, - AllowMissingPos, - TrailingValues, - ValidNegNumFound, - Propagated, - ValidArgFound, - InferSubcommands, - ContainsLast, - ArgsOverrideSelf, +bitflags! { + struct Flags: u64 { + const SC_NEGATE_REQS = 1; + const SC_REQUIRED = 1 << 1; + const A_REQUIRED_ELSE_HELP = 1 << 2; + const GLOBAL_VERSION = 1 << 3; + const VERSIONLESS_SC = 1 << 4; + const UNIFIED_HELP = 1 << 5; + const WAIT_ON_ERROR = 1 << 6; + const SC_REQUIRED_ELSE_HELP= 1 << 7; + const NEEDS_LONG_HELP = 1 << 8; + const NEEDS_LONG_VERSION = 1 << 9; + const NEEDS_SC_HELP = 1 << 10; + const DISABLE_VERSION = 1 << 11; + const HIDDEN = 1 << 12; + const TRAILING_VARARG = 1 << 13; + const NO_BIN_NAME = 1 << 14; + const ALLOW_UNK_SC = 1 << 15; + const UTF8_STRICT = 1 << 16; + const UTF8_NONE = 1 << 17; + const LEADING_HYPHEN = 1 << 18; + const NO_POS_VALUES = 1 << 19; + const NEXT_LINE_HELP = 1 << 20; + const DERIVE_DISP_ORDER = 1 << 21; + const COLORED_HELP = 1 << 22; + const COLOR_ALWAYS = 1 << 23; + const COLOR_AUTO = 1 << 24; + const COLOR_NEVER = 1 << 25; + const DONT_DELIM_TRAIL = 1 << 26; + const ALLOW_NEG_NUMS = 1 << 27; + const LOW_INDEX_MUL_POS = 1 << 28; + const DISABLE_HELP_SC = 1 << 29; + const DONT_COLLAPSE_ARGS = 1 << 30; + const ARGS_NEGATE_SCS = 1 << 31; + const PROPAGATE_VALS_DOWN = 1 << 32; + const ALLOW_MISSING_POS = 1 << 33; + const TRAILING_VALUES = 1 << 34; + const VALID_NEG_NUM_FOUND = 1 << 35; + const PROPAGATED = 1 << 36; + const VALID_ARG_FOUND = 1 << 37; + const INFER_SUBCOMMANDS = 1 << 38; + const CONTAINS_LAST = 1 << 39; + const ARGS_OVERRIDE_SELF = 1 << 40; + } } #[doc(hidden)] -#[derive(Debug, Clone, PartialEq)] -pub struct AppFlags(HashSet); +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct AppFlags(Flags); + +impl BitOr for AppFlags { + type Output = Self; + fn bitor(self, rhs: Self) -> Self { AppFlags(self.0 | rhs.0) } +} impl Default for AppFlags { fn default() -> Self { - let mut set = HashSet::new(); - set.insert(Flags::NeedsLongVersion); - set.insert(Flags::NeedsLongHelp); - set.insert(Flags::NeedsScHelp); - set.insert(Flags::Utf8None); - set.insert(Flags::ColorAuto); - AppFlags(set) + AppFlags( + Flags::NEEDS_LONG_VERSION | Flags::NEEDS_LONG_HELP | Flags::NEEDS_SC_HELP + | Flags::UTF8_NONE | Flags::COLOR_AUTO, + ) } } #[allow(deprecated)] impl AppFlags { pub fn new() -> Self { AppFlags::default() } - pub fn zeroed() -> Self { AppFlags(HashSet::new()) } - pub fn update(&mut self, other: &Self) { - for flag in other.0.iter() { - self.0.insert(*flag); - } - } + pub fn zeroed() -> Self { AppFlags(Flags::empty()) } impl_settings! { AppSettings, - ArgRequiredElseHelp => Flags::ARequiredElseHelp, - ArgsNegateSubcommands => Flags::ArgsNegateScs, - AllArgsOverrideSelf => Flags::ArgsOverrideSelf, - AllowExternalSubcommands => Flags::AllowUnkSc, - AllowInvalidUtf8 => Flags::Utf8None, - AllowLeadingHyphen => Flags::LeadingHyphen, - AllowNegativeNumbers => Flags::AllowNegNums, - AllowMissingPositional => Flags::AllowMissingPos, - ColoredHelp => Flags::ColoredHelp, - ColorAlways => Flags::ColorAlways, - ColorAuto => Flags::ColorAuto, - ColorNever => Flags::ColorNever, - DontDelimitTrailingValues => Flags::DontDelimTrail, - DontCollapseArgsInUsage => Flags::DontCollapseArgs, - DeriveDisplayOrder => Flags::DeriveDispOrder, - DisableHelpSubcommand => Flags::DisableHelpSc, - DisableVersion => Flags::DisableVersion, - GlobalVersion => Flags::GlobalVersion, - HidePossibleValuesInHelp => Flags::NoPosValues, - Hidden => Flags::Hidden, - LowIndexMultiplePositional => Flags::LowIndexMulPos, - NeedsLongHelp => Flags::NeedsLongHelp, - NeedsLongVersion => Flags::NeedsLongVersion, - NeedsSubcommandHelp => Flags::NeedsScHelp, - NoBinaryName => Flags::NoBinName, - PropagateGlobalValuesDown=> Flags::PropagateValsDown, - StrictUtf8 => Flags::Utf8Strict, - SubcommandsNegateReqs => Flags::ScNegateReqs, - SubcommandRequired => Flags::ScRequired, - SubcommandRequiredElseHelp => Flags::ScRequiredElseHelp, - TrailingVarArg => Flags::TrailingVararg, - UnifiedHelpMessage => Flags::UnifiedHelp, - NextLineHelp => Flags::NextLineHelp, - VersionlessSubcommands => Flags::VersionlessSc, - WaitOnError => Flags::WaitOnError, - TrailingValues => Flags::TrailingValues, - ValidNegNumFound => Flags::ValidNegNumFound, - Propagated => Flags::Propagated, - ValidArgFound => Flags::ValidArgFound, - InferSubcommands => Flags::InferSubcommands, - ContainsLast => Flags::ContainsLast + ArgRequiredElseHelp => Flags::A_REQUIRED_ELSE_HELP, + ArgsNegateSubcommands => Flags::ARGS_NEGATE_SCS, + AllArgsOverrideSelf => Flags::ARGS_OVERRIDE_SELF, + AllowExternalSubcommands => Flags::ALLOW_UNK_SC, + AllowInvalidUtf8 => Flags::UTF8_NONE, + AllowLeadingHyphen => Flags::LEADING_HYPHEN, + AllowNegativeNumbers => Flags::ALLOW_NEG_NUMS, + AllowMissingPositional => Flags::ALLOW_MISSING_POS, + ColoredHelp => Flags::COLORED_HELP, + ColorAlways => Flags::COLOR_ALWAYS, + ColorAuto => Flags::COLOR_AUTO, + ColorNever => Flags::COLOR_NEVER, + DontDelimitTrailingValues => Flags::DONT_DELIM_TRAIL, + DontCollapseArgsInUsage => Flags::DONT_COLLAPSE_ARGS, + DeriveDisplayOrder => Flags::DERIVE_DISP_ORDER, + DisableHelpSubcommand => Flags::DISABLE_HELP_SC, + DisableVersion => Flags::DISABLE_VERSION, + GlobalVersion => Flags::GLOBAL_VERSION, + HidePossibleValuesInHelp => Flags::NO_POS_VALUES, + Hidden => Flags::HIDDEN, + LowIndexMultiplePositional => Flags::LOW_INDEX_MUL_POS, + NeedsLongHelp => Flags::NEEDS_LONG_HELP, + NeedsLongVersion => Flags::NEEDS_LONG_VERSION, + NeedsSubcommandHelp => Flags::NEEDS_SC_HELP, + NoBinaryName => Flags::NO_BIN_NAME, + PropagateGlobalValuesDown=> Flags::PROPAGATE_VALS_DOWN, + StrictUtf8 => Flags::UTF8_STRICT, + SubcommandsNegateReqs => Flags::SC_NEGATE_REQS, + SubcommandRequired => Flags::SC_REQUIRED, + SubcommandRequiredElseHelp => Flags::SC_REQUIRED_ELSE_HELP, + TrailingVarArg => Flags::TRAILING_VARARG, + UnifiedHelpMessage => Flags::UNIFIED_HELP, + NextLineHelp => Flags::NEXT_LINE_HELP, + VersionlessSubcommands => Flags::VERSIONLESS_SC, + WaitOnError => Flags::WAIT_ON_ERROR, + TrailingValues => Flags::TRAILING_VALUES, + ValidNegNumFound => Flags::VALID_NEG_NUM_FOUND, + Propagated => Flags::PROPAGATED, + ValidArgFound => Flags::VALID_ARG_FOUND, + InferSubcommands => Flags::INFER_SUBCOMMANDS, + ContainsLast => Flags::CONTAINS_LAST } } diff --git a/src/args/settings.rs b/src/args/settings.rs index 436fe664a21..7b0e0a26c7a 100644 --- a/src/args/settings.rs +++ b/src/args/settings.rs @@ -1,71 +1,66 @@ // Std -use std::collections::HashSet; #[allow(deprecated, unused_imports)] use std::ascii::AsciiExt; use std::str::FromStr; -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -enum Flags { - Required, - Multiple, - EmptyVals, - Global, - Hidden, - TakesVal, - UseDelim, - NextLineHelp, - RUnlessAll, - ReqDelim, - DelimNotSet, - HidePosVals, - AllowTacVals, - RequireEquals, - Last, - HideDefaultVal, - CaseInsensitive, - HideEnvVals, - HiddenShortH, - HiddenLongH +bitflags! { + struct Flags: u32 { + const REQUIRED = 1; + const MULTIPLE = 1 << 1; + const EMPTY_VALS = 1 << 2; + const GLOBAL = 1 << 3; + const HIDDEN = 1 << 4; + const TAKES_VAL = 1 << 5; + const USE_DELIM = 1 << 6; + const NEXT_LINE_HELP = 1 << 7; + const R_UNLESS_ALL = 1 << 8; + const REQ_DELIM = 1 << 9; + const DELIM_NOT_SET = 1 << 10; + const HIDE_POS_VALS = 1 << 11; + const ALLOW_TAC_VALS = 1 << 12; + const REQUIRE_EQUALS = 1 << 13; + const LAST = 1 << 14; + const HIDE_DEFAULT_VAL = 1 << 15; + const CASE_INSENSITIVE = 1 << 16; + const HIDE_ENV_VALS = 1 << 17; + const HIDDEN_SHORT_H = 1 << 18; + const HIDDEN_LONG_H = 1 << 19; + } } #[doc(hidden)] -#[derive(Debug, Clone)] -pub struct ArgFlags(HashSet); +#[derive(Debug, Clone, Copy)] +pub struct ArgFlags(Flags); impl ArgFlags { pub fn new() -> Self { ArgFlags::default() } impl_settings!{ArgSettings, - Required => Flags::Required, - Multiple => Flags::Multiple, - EmptyValues => Flags::EmptyVals, - Global => Flags::Global, - Hidden => Flags::Hidden, - TakesValue => Flags::TakesVal, - UseValueDelimiter => Flags::UseDelim, - NextLineHelp => Flags::NextLineHelp, - RequiredUnlessAll => Flags::RUnlessAll, - RequireDelimiter => Flags::ReqDelim, - ValueDelimiterNotSet => Flags::DelimNotSet, - HidePossibleValues => Flags::HidePosVals, - AllowLeadingHyphen => Flags::AllowTacVals, - RequireEquals => Flags::RequireEquals, - Last => Flags::Last, - CaseInsensitive => Flags::CaseInsensitive, - HideEnvValues => Flags::HideEnvVals, - HideDefaultValue => Flags::HideDefaultVal, - HiddenShortHelp => Flags::HiddenShortH, - HiddenLongHelp => Flags::HiddenLongH + Required => Flags::REQUIRED, + Multiple => Flags::MULTIPLE, + EmptyValues => Flags::EMPTY_VALS, + Global => Flags::GLOBAL, + Hidden => Flags::HIDDEN, + TakesValue => Flags::TAKES_VAL, + UseValueDelimiter => Flags::USE_DELIM, + NextLineHelp => Flags::NEXT_LINE_HELP, + RequiredUnlessAll => Flags::R_UNLESS_ALL, + RequireDelimiter => Flags::REQ_DELIM, + ValueDelimiterNotSet => Flags::DELIM_NOT_SET, + HidePossibleValues => Flags::HIDE_POS_VALS, + AllowLeadingHyphen => Flags::ALLOW_TAC_VALS, + RequireEquals => Flags::REQUIRE_EQUALS, + Last => Flags::LAST, + CaseInsensitive => Flags::CASE_INSENSITIVE, + HideEnvValues => Flags::HIDE_ENV_VALS, + HideDefaultValue => Flags::HIDE_DEFAULT_VAL, + HiddenShortHelp => Flags::HIDDEN_SHORT_H, + HiddenLongHelp => Flags::HIDDEN_LONG_H } } impl Default for ArgFlags { - fn default() -> Self { - let mut set = HashSet::new(); - set.insert(Flags::EmptyVals); - set.insert(Flags::DelimNotSet); - ArgFlags(set) - } + fn default() -> Self { ArgFlags(Flags::EMPTY_VALS | Flags::DELIM_NOT_SET) } } /// Various settings that apply to arguments and may be set, unset, and checked via getter/setter diff --git a/src/lib.rs b/src/lib.rs index 27a9f7cf6e6..2587122be06 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -519,9 +519,10 @@ #![crate_type = "lib"] #![doc(html_root_url = "https://docs.rs/clap/2.32.0")] #![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts, - unused_import_braces, unused_allocation, trivial_numeric_casts)] + unused_import_braces, unused_allocation)] // Lints we'd like to deny but are currently failing for upstream crates -// unused_qualifications (clippy) +// unused_qualifications (bitflags, clippy) +// trivial_numeric_casts (bitflags) #![cfg_attr(not(any(feature = "lints", feature = "nightly")), forbid(unstable_features))] #![cfg_attr(feature = "lints", feature(plugin))] #![cfg_attr(feature = "lints", plugin(clippy))] @@ -535,6 +536,8 @@ extern crate ansi_term; #[cfg(feature = "color")] extern crate atty; +#[macro_use] +extern crate bitflags; #[cfg(feature = "suggestions")] extern crate strsim; #[cfg(feature = "wrap_help")] diff --git a/src/macros.rs b/src/macros.rs index b935be3646c..74212ff04f1 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -800,18 +800,18 @@ macro_rules! impl_settings { pub fn set(&mut self, s: $n) { match s { $($n::$v => self.0.insert($c)),+ - }; + } } pub fn unset(&mut self, s: $n) { match s { - $($n::$v => self.0.remove(&$c)),+ - }; + $($n::$v => self.0.remove($c)),+ + } } pub fn is_set(&self, s: $n) -> bool { match s { - $($n::$v => self.0.contains(&$c)),+ + $($n::$v => self.0.contains($c)),+ } } };