1 // Std 2 use std::ops::BitOr; 3 #[cfg(feature = "yaml")] 4 use std::str::FromStr; 5 6 // Third party 7 use bitflags::bitflags; 8 9 #[doc(hidden)] 10 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 11 pub struct ArgFlags(Flags); 12 13 impl Default for ArgFlags { default() -> Self14 fn default() -> Self { 15 Self::empty() 16 } 17 } 18 19 /// Various settings that apply to arguments and may be set, unset, and checked via getter/setter 20 /// methods [`Arg::setting`], [`Arg::unset_setting`], and [`Arg::is_set`]. This is what the 21 /// [`Arg`] methods which accept a `bool` use internally. 22 /// 23 /// [`Arg`]: crate::Arg 24 /// [`Arg::setting`]: crate::Arg::setting() 25 /// [`Arg::unset_setting`]: crate::Arg::unset_setting() 26 /// [`Arg::is_set`]: crate::Arg::is_set() 27 #[derive(Debug, PartialEq, Copy, Clone)] 28 #[non_exhaustive] 29 pub enum ArgSettings { 30 /// Specifies that an arg must be used 31 Required, 32 /// Allows an arg to accept multiple values 33 MultipleValues, 34 /// Allows an arg to appear multiple times 35 MultipleOccurrences, 36 /// Deprecated, see [`ArgSettings::MultipleOccurrences`] (most likely what you want) and 37 /// [`ArgSettings::MultipleValues`] 38 #[deprecated( 39 since = "3.0.0", 40 note = "Split into `ArgSettings::MultipleOccurrences` (most likely what you want) and `ArgSettings::MultipleValues`" 41 )] 42 Multiple, 43 /// Forbids an arg from accepting empty values such as `""` 44 ForbidEmptyValues, 45 /// Sets an arg to be global (i.e. exist in all subcommands) 46 Global, 47 /// Hides an arg from the help message 48 Hidden, 49 /// Allows an argument to take a value (such as `--option value`) 50 TakesValue, 51 /// Enables a delimiter to break up arguments `--option val1,val2,val3` becomes three values 52 /// (`val1`, `val2`, and `val3`) instead of the default one (`val1,val2,val3`) 53 UseValueDelimiter, 54 /// Tells an arg to display it's help on the line below the arg itself in the help message 55 NextLineHelp, 56 /// Says that arg *must* use a delimiter to separate values 57 RequireDelimiter, 58 /// Hides the possible values from the help message 59 HidePossibleValues, 60 /// Allows values that start with a hyphen 61 AllowHyphenValues, 62 /// Deprecated, replaced with [`ArgSettings::AllowHyphenValues`] 63 #[deprecated( 64 since = "3.0.0", 65 note = "Replaced with `ArgSettings::AllowHyphenValues`" 66 )] 67 AllowLeadingHyphen, 68 /// Requires that an equals be used to provide a value to an option such as `--option=value` 69 RequireEquals, 70 /// Says that a positional arg will be the last positional, and requires `--` to be accessed. 71 /// It can also be accessed early (i.e. before other positionals) by providing `--` 72 Last, 73 /// Hides the default value from the help message 74 HideDefaultValue, 75 /// Possible values become case insensitive 76 IgnoreCase, 77 /// Deprecated, replaced with [`ArgSettings::IgnoreCase`] 78 #[deprecated(since = "3.0.0", note = "Replaced with `ArgSettings::IgnoreCase`")] 79 CaseInsensitive, 80 /// Hides environment variable arguments from the help message 81 #[cfg(feature = "env")] 82 HideEnv, 83 /// Hides any values currently assigned to ENV variables in the help message (good for sensitive 84 /// information) 85 #[cfg(feature = "env")] 86 HideEnvValues, 87 /// The argument should **not** be shown in short help text 88 HiddenShortHelp, 89 /// The argument should **not** be shown in long help text 90 HiddenLongHelp, 91 /// Specifies that option values that are invalid UTF-8 should *not* be treated as an error. 92 AllowInvalidUtf8, 93 /// Specifies that option should exist on its own. 94 /// Having any other arguments present at runtime is an error. 95 Exclusive, 96 } 97 98 bitflags! { 99 struct Flags: u32 { 100 const REQUIRED = 1; 101 const MULTIPLE_OCC = 1 << 1; 102 const NO_EMPTY_VALS = 1 << 2; 103 const GLOBAL = 1 << 3; 104 const HIDDEN = 1 << 4; 105 const TAKES_VAL = 1 << 5; 106 const USE_DELIM = 1 << 6; 107 const NEXT_LINE_HELP = 1 << 7; 108 const REQ_DELIM = 1 << 9; 109 const DELIM_NOT_SET = 1 << 10; 110 const HIDE_POS_VALS = 1 << 11; 111 const ALLOW_TAC_VALS = 1 << 12; 112 const REQUIRE_EQUALS = 1 << 13; 113 const LAST = 1 << 14; 114 const HIDE_DEFAULT_VAL = 1 << 15; 115 const CASE_INSENSITIVE = 1 << 16; 116 #[cfg(feature = "env")] 117 const HIDE_ENV_VALS = 1 << 17; 118 const HIDDEN_SHORT_H = 1 << 18; 119 const HIDDEN_LONG_H = 1 << 19; 120 const MULTIPLE_VALS = 1 << 20; 121 const MULTIPLE = Self::MULTIPLE_OCC.bits | Self::MULTIPLE_VALS.bits; 122 #[cfg(feature = "env")] 123 const HIDE_ENV = 1 << 21; 124 const UTF8_NONE = 1 << 22; 125 const EXCLUSIVE = 1 << 23; 126 const NO_OP = 0; 127 } 128 } 129 130 impl_settings! { ArgSettings, ArgFlags, 131 Required => Flags::REQUIRED, 132 MultipleOccurrences => Flags::MULTIPLE_OCC, 133 MultipleValues => Flags::MULTIPLE_VALS, 134 Multiple => Flags::MULTIPLE, 135 ForbidEmptyValues => Flags::NO_EMPTY_VALS, 136 Global => Flags::GLOBAL, 137 Hidden => Flags::HIDDEN, 138 TakesValue => Flags::TAKES_VAL, 139 UseValueDelimiter => Flags::USE_DELIM, 140 NextLineHelp => Flags::NEXT_LINE_HELP, 141 RequireDelimiter => Flags::REQ_DELIM, 142 HidePossibleValues => Flags::HIDE_POS_VALS, 143 AllowHyphenValues => Flags::ALLOW_TAC_VALS, 144 AllowLeadingHyphen => Flags::ALLOW_TAC_VALS, 145 RequireEquals => Flags::REQUIRE_EQUALS, 146 Last => Flags::LAST, 147 IgnoreCase => Flags::CASE_INSENSITIVE, 148 CaseInsensitive => Flags::CASE_INSENSITIVE, 149 #[cfg(feature = "env")] 150 HideEnv => Flags::HIDE_ENV, 151 #[cfg(feature = "env")] 152 HideEnvValues => Flags::HIDE_ENV_VALS, 153 HideDefaultValue => Flags::HIDE_DEFAULT_VAL, 154 HiddenShortHelp => Flags::HIDDEN_SHORT_H, 155 HiddenLongHelp => Flags::HIDDEN_LONG_H, 156 AllowInvalidUtf8 => Flags::UTF8_NONE, 157 Exclusive => Flags::EXCLUSIVE 158 } 159 160 /// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case? 161 #[cfg(feature = "yaml")] 162 impl FromStr for ArgSettings { 163 type Err = String; from_str(s: &str) -> Result<Self, <Self as FromStr>::Err>164 fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> { 165 #[allow(deprecated)] 166 #[allow(unreachable_patterns)] 167 match &*s.to_ascii_lowercase() { 168 "required" => Ok(ArgSettings::Required), 169 "multipleoccurrences" => Ok(ArgSettings::MultipleOccurrences), 170 "multiplevalues" => Ok(ArgSettings::MultipleValues), 171 "multiple" => Ok(ArgSettings::Multiple), 172 "forbidemptyvalues" => Ok(ArgSettings::ForbidEmptyValues), 173 "global" => Ok(ArgSettings::Global), 174 "hidden" => Ok(ArgSettings::Hidden), 175 "takesvalue" => Ok(ArgSettings::TakesValue), 176 "usevaluedelimiter" => Ok(ArgSettings::UseValueDelimiter), 177 "nextlinehelp" => Ok(ArgSettings::NextLineHelp), 178 "requiredelimiter" => Ok(ArgSettings::RequireDelimiter), 179 "hidepossiblevalues" => Ok(ArgSettings::HidePossibleValues), 180 "allowhyphenvalues" => Ok(ArgSettings::AllowHyphenValues), 181 "allowleadinghypyhen" => Ok(ArgSettings::AllowLeadingHyphen), 182 "requireequals" => Ok(ArgSettings::RequireEquals), 183 "last" => Ok(ArgSettings::Last), 184 "ignorecase" => Ok(ArgSettings::IgnoreCase), 185 "caseinsensitive" => Ok(ArgSettings::CaseInsensitive), 186 #[cfg(feature = "env")] 187 "hideenv" => Ok(ArgSettings::HideEnv), 188 #[cfg(feature = "env")] 189 "hideenvvalues" => Ok(ArgSettings::HideEnvValues), 190 "hidedefaultvalue" => Ok(ArgSettings::HideDefaultValue), 191 "hiddenshorthelp" => Ok(ArgSettings::HiddenShortHelp), 192 "hiddenlonghelp" => Ok(ArgSettings::HiddenLongHelp), 193 "allowinvalidutf8" => Ok(ArgSettings::AllowInvalidUtf8), 194 "exclusive" => Ok(ArgSettings::Exclusive), 195 _ => Err(format!("unknown AppSetting: `{}`", s)), 196 } 197 } 198 } 199 200 #[cfg(test)] 201 mod test { 202 #[test] 203 #[cfg(feature = "yaml")] arg_settings_fromstr()204 fn arg_settings_fromstr() { 205 use super::ArgSettings; 206 207 assert_eq!( 208 "allowhyphenvalues".parse::<ArgSettings>().unwrap(), 209 ArgSettings::AllowHyphenValues 210 ); 211 assert_eq!( 212 "forbidemptyvalues".parse::<ArgSettings>().unwrap(), 213 ArgSettings::ForbidEmptyValues 214 ); 215 assert_eq!( 216 "hidepossiblevalues".parse::<ArgSettings>().unwrap(), 217 ArgSettings::HidePossibleValues 218 ); 219 assert_eq!( 220 "hidden".parse::<ArgSettings>().unwrap(), 221 ArgSettings::Hidden 222 ); 223 assert_eq!( 224 "nextlinehelp".parse::<ArgSettings>().unwrap(), 225 ArgSettings::NextLineHelp 226 ); 227 assert_eq!( 228 "requiredelimiter".parse::<ArgSettings>().unwrap(), 229 ArgSettings::RequireDelimiter 230 ); 231 assert_eq!( 232 "required".parse::<ArgSettings>().unwrap(), 233 ArgSettings::Required 234 ); 235 assert_eq!( 236 "takesvalue".parse::<ArgSettings>().unwrap(), 237 ArgSettings::TakesValue 238 ); 239 assert_eq!( 240 "usevaluedelimiter".parse::<ArgSettings>().unwrap(), 241 ArgSettings::UseValueDelimiter 242 ); 243 assert_eq!( 244 "requireequals".parse::<ArgSettings>().unwrap(), 245 ArgSettings::RequireEquals 246 ); 247 assert_eq!("last".parse::<ArgSettings>().unwrap(), ArgSettings::Last); 248 assert_eq!( 249 "hidedefaultvalue".parse::<ArgSettings>().unwrap(), 250 ArgSettings::HideDefaultValue 251 ); 252 assert_eq!( 253 "ignorecase".parse::<ArgSettings>().unwrap(), 254 ArgSettings::IgnoreCase 255 ); 256 #[cfg(feature = "env")] 257 assert_eq!( 258 "hideenv".parse::<ArgSettings>().unwrap(), 259 ArgSettings::HideEnv 260 ); 261 #[cfg(feature = "env")] 262 assert_eq!( 263 "hideenvvalues".parse::<ArgSettings>().unwrap(), 264 ArgSettings::HideEnvValues 265 ); 266 assert_eq!( 267 "hiddenshorthelp".parse::<ArgSettings>().unwrap(), 268 ArgSettings::HiddenShortHelp 269 ); 270 assert_eq!( 271 "hiddenlonghelp".parse::<ArgSettings>().unwrap(), 272 ArgSettings::HiddenLongHelp 273 ); 274 assert_eq!( 275 "allowinvalidutf8".parse::<ArgSettings>().unwrap(), 276 ArgSettings::AllowInvalidUtf8 277 ); 278 assert_eq!( 279 "exclusive".parse::<ArgSettings>().unwrap(), 280 ArgSettings::Exclusive 281 ); 282 assert!("hahahaha".parse::<ArgSettings>().is_err()); 283 } 284 } 285