1 // Std 2 use std::{ops::BitOr, str::FromStr}; 3 4 // Third party 5 use bitflags::bitflags; 6 7 bitflags! { 8 struct Flags: u32 { 9 const REQUIRED = 1; 10 const MULTIPLE_OCC = 1 << 1; 11 const NO_EMPTY_VALS = 1 << 2; 12 const GLOBAL = 1 << 3; 13 const HIDDEN = 1 << 4; 14 const TAKES_VAL = 1 << 5; 15 const USE_DELIM = 1 << 6; 16 const NEXT_LINE_HELP = 1 << 7; 17 const R_UNLESS_ALL = 1 << 8; 18 const REQ_DELIM = 1 << 9; 19 const DELIM_NOT_SET = 1 << 10; 20 const HIDE_POS_VALS = 1 << 11; 21 const ALLOW_TAC_VALS = 1 << 12; 22 const REQUIRE_EQUALS = 1 << 13; 23 const LAST = 1 << 14; 24 const HIDE_DEFAULT_VAL = 1 << 15; 25 const CASE_INSENSITIVE = 1 << 16; 26 #[cfg(feature = "env")] 27 const HIDE_ENV_VALS = 1 << 17; 28 const HIDDEN_SHORT_H = 1 << 18; 29 const HIDDEN_LONG_H = 1 << 19; 30 const MULTIPLE_VALS = 1 << 20; 31 #[cfg(feature = "env")] 32 const HIDE_ENV = 1 << 21; 33 const UTF8_NONE = 1 << 22; 34 } 35 } 36 37 #[doc(hidden)] 38 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 39 pub struct ArgFlags(Flags); 40 41 impl Default for ArgFlags { default() -> Self42 fn default() -> Self { 43 Self::empty() 44 } 45 } 46 47 // @TODO @p6 @internal: Reorder alphabetically 48 impl_settings! { ArgSettings, ArgFlags, 49 Required("required") => Flags::REQUIRED, 50 MultipleOccurrences("multipleoccurrences") => Flags::MULTIPLE_OCC, 51 MultipleValues("multiplevalues") => Flags::MULTIPLE_VALS, 52 ForbidEmptyValues("forbidemptyvalues") => Flags::NO_EMPTY_VALS, 53 Hidden("hidden") => Flags::HIDDEN, 54 TakesValue("takesvalue") => Flags::TAKES_VAL, 55 UseValueDelimiter("usevaluedelimiter") => Flags::USE_DELIM, 56 NextLineHelp("nextlinehelp") => Flags::NEXT_LINE_HELP, 57 RequiredUnlessAll("requiredunlessall") => Flags::R_UNLESS_ALL, 58 RequireDelimiter("requiredelimiter") => Flags::REQ_DELIM, 59 HidePossibleValues("hidepossiblevalues") => Flags::HIDE_POS_VALS, 60 AllowHyphenValues("allowhyphenvalues") => Flags::ALLOW_TAC_VALS, 61 RequireEquals("requireequals") => Flags::REQUIRE_EQUALS, 62 Last("last") => Flags::LAST, 63 IgnoreCase("ignorecase") => Flags::CASE_INSENSITIVE, 64 #[cfg(feature = "env")] 65 HideEnv("hideenv") => Flags::HIDE_ENV, 66 #[cfg(feature = "env")] 67 HideEnvValues("hideenvvalues") => Flags::HIDE_ENV_VALS, 68 HideDefaultValue("hidedefaultvalue") => Flags::HIDE_DEFAULT_VAL, 69 HiddenShortHelp("hiddenshorthelp") => Flags::HIDDEN_SHORT_H, 70 HiddenLongHelp("hiddenlonghelp") => Flags::HIDDEN_LONG_H, 71 AllowInvalidUtf8("allowinvalidutf8") => Flags::UTF8_NONE 72 } 73 74 /// Various settings that apply to arguments and may be set, unset, and checked via getter/setter 75 /// methods [`Arg::setting`], [`Arg::unset_setting`], and [`Arg::is_set`]. This is what the 76 /// [`Arg`] methods which accept a `bool` use internally. 77 /// 78 /// [`Arg`]: crate::Arg 79 /// [`Arg::setting`]: crate::Arg::setting() 80 /// [`Arg::unset_setting`]: crate::Arg::unset_setting() 81 /// [`Arg::is_set`]: crate::Arg::is_set() 82 #[derive(Debug, PartialEq, Copy, Clone)] 83 pub enum ArgSettings { 84 /// Specifies that an arg must be used 85 Required, 86 /// Allows an arg to accept multiple values 87 MultipleValues, 88 /// Allows an arg to appear multiple times 89 MultipleOccurrences, 90 /// Forbids an arg from accepting empty values such as `""` 91 ForbidEmptyValues, 92 /// Hides an arg from the help message 93 Hidden, 94 /// Allows an argument to take a value (such as `--option value`) 95 TakesValue, 96 /// Enables a delimiter to break up arguments `--option val1,val2,val3` becomes three values 97 /// (`val1`, `val2`, and `val3`) instead of the default one (`val1,val2,val3`) 98 UseValueDelimiter, 99 /// Tells an arg to display it's help on the line below the arg itself in the help message 100 NextLineHelp, 101 /// Says that arg *must* use a delimiter to separate values 102 RequireDelimiter, 103 /// Hides the possible values from the help message 104 HidePossibleValues, 105 /// Allows values that start with a hyphen 106 AllowHyphenValues, 107 /// Requires that an equals be used to provide a value to an option such as `--option=value` 108 RequireEquals, 109 /// Says that a positional arg will be the last positional, and requires `--` to be accessed. 110 /// It can also be accessed early (i.e. before other positionals) by providing `--` 111 Last, 112 /// Hides the default value from the help message 113 HideDefaultValue, 114 /// Possible values become case insensitive 115 IgnoreCase, 116 /// Hides environment variable arguments from the help message 117 #[cfg(feature = "env")] 118 HideEnv, 119 /// Hides any values currently assigned to ENV variables in the help message (good for sensitive 120 /// information) 121 #[cfg(feature = "env")] 122 HideEnvValues, 123 /// The argument should **not** be shown in short help text 124 HiddenShortHelp, 125 /// The argument should **not** be shown in long help text 126 HiddenLongHelp, 127 /// Specifies that option values that are invalid UTF-8 should *not* be treated as an error. 128 AllowInvalidUtf8, 129 130 #[doc(hidden)] 131 RequiredUnlessAll, 132 } 133 134 #[cfg(test)] 135 mod test { 136 use super::ArgSettings; 137 138 #[test] arg_settings_fromstr()139 fn arg_settings_fromstr() { 140 assert_eq!( 141 "allowhyphenvalues".parse::<ArgSettings>().unwrap(), 142 ArgSettings::AllowHyphenValues 143 ); 144 assert_eq!( 145 "forbidemptyvalues".parse::<ArgSettings>().unwrap(), 146 ArgSettings::ForbidEmptyValues 147 ); 148 assert_eq!( 149 "hidepossiblevalues".parse::<ArgSettings>().unwrap(), 150 ArgSettings::HidePossibleValues 151 ); 152 assert_eq!( 153 "hidden".parse::<ArgSettings>().unwrap(), 154 ArgSettings::Hidden 155 ); 156 assert_eq!( 157 "nextlinehelp".parse::<ArgSettings>().unwrap(), 158 ArgSettings::NextLineHelp 159 ); 160 assert_eq!( 161 "requiredunlessall".parse::<ArgSettings>().unwrap(), 162 ArgSettings::RequiredUnlessAll 163 ); 164 assert_eq!( 165 "requiredelimiter".parse::<ArgSettings>().unwrap(), 166 ArgSettings::RequireDelimiter 167 ); 168 assert_eq!( 169 "required".parse::<ArgSettings>().unwrap(), 170 ArgSettings::Required 171 ); 172 assert_eq!( 173 "takesvalue".parse::<ArgSettings>().unwrap(), 174 ArgSettings::TakesValue 175 ); 176 assert_eq!( 177 "usevaluedelimiter".parse::<ArgSettings>().unwrap(), 178 ArgSettings::UseValueDelimiter 179 ); 180 assert_eq!( 181 "requireequals".parse::<ArgSettings>().unwrap(), 182 ArgSettings::RequireEquals 183 ); 184 assert_eq!("last".parse::<ArgSettings>().unwrap(), ArgSettings::Last); 185 assert_eq!( 186 "hidedefaultvalue".parse::<ArgSettings>().unwrap(), 187 ArgSettings::HideDefaultValue 188 ); 189 assert_eq!( 190 "ignorecase".parse::<ArgSettings>().unwrap(), 191 ArgSettings::IgnoreCase 192 ); 193 #[cfg(feature = "env")] 194 assert_eq!( 195 "hideenv".parse::<ArgSettings>().unwrap(), 196 ArgSettings::HideEnv 197 ); 198 #[cfg(feature = "env")] 199 assert_eq!( 200 "hideenvvalues".parse::<ArgSettings>().unwrap(), 201 ArgSettings::HideEnvValues 202 ); 203 assert_eq!( 204 "hiddenshorthelp".parse::<ArgSettings>().unwrap(), 205 ArgSettings::HiddenShortHelp 206 ); 207 assert_eq!( 208 "hiddenlonghelp".parse::<ArgSettings>().unwrap(), 209 ArgSettings::HiddenLongHelp 210 ); 211 assert_eq!( 212 "allowinvalidutf8".parse::<ArgSettings>().unwrap(), 213 ArgSettings::AllowInvalidUtf8 214 ); 215 assert!("hahahaha".parse::<ArgSettings>().is_err()); 216 } 217 } 218