1 // Std
2 #[allow(deprecated, unused_imports)]
3 use std::ascii::AsciiExt;
4 use std::str::FromStr;
5 
6 bitflags! {
7     struct Flags: u32 {
8         const REQUIRED         = 1;
9         const MULTIPLE         = 1 << 1;
10         const EMPTY_VALS       = 1 << 2;
11         const GLOBAL           = 1 << 3;
12         const HIDDEN           = 1 << 4;
13         const TAKES_VAL        = 1 << 5;
14         const USE_DELIM        = 1 << 6;
15         const NEXT_LINE_HELP   = 1 << 7;
16         const R_UNLESS_ALL     = 1 << 8;
17         const REQ_DELIM        = 1 << 9;
18         const DELIM_NOT_SET    = 1 << 10;
19         const HIDE_POS_VALS    = 1 << 11;
20         const ALLOW_TAC_VALS   = 1 << 12;
21         const REQUIRE_EQUALS   = 1 << 13;
22         const LAST             = 1 << 14;
23         const HIDE_DEFAULT_VAL = 1 << 15;
24         const CASE_INSENSITIVE = 1 << 16;
25         const HIDE_ENV_VALS    = 1 << 17;
26         const HIDDEN_SHORT_H   = 1 << 18;
27         const HIDDEN_LONG_H    = 1 << 19;
28     }
29 }
30 
31 #[doc(hidden)]
32 #[derive(Debug, Clone, Copy)]
33 pub struct ArgFlags(Flags);
34 
35 impl ArgFlags {
new() -> Self36     pub fn new() -> Self { ArgFlags::default() }
37 
38     impl_settings!{ArgSettings,
39         Required => Flags::REQUIRED,
40         Multiple => Flags::MULTIPLE,
41         EmptyValues => Flags::EMPTY_VALS,
42         Global => Flags::GLOBAL,
43         Hidden => Flags::HIDDEN,
44         TakesValue => Flags::TAKES_VAL,
45         UseValueDelimiter => Flags::USE_DELIM,
46         NextLineHelp => Flags::NEXT_LINE_HELP,
47         RequiredUnlessAll => Flags::R_UNLESS_ALL,
48         RequireDelimiter => Flags::REQ_DELIM,
49         ValueDelimiterNotSet => Flags::DELIM_NOT_SET,
50         HidePossibleValues => Flags::HIDE_POS_VALS,
51         AllowLeadingHyphen => Flags::ALLOW_TAC_VALS,
52         RequireEquals => Flags::REQUIRE_EQUALS,
53         Last => Flags::LAST,
54         CaseInsensitive => Flags::CASE_INSENSITIVE,
55         HideEnvValues => Flags::HIDE_ENV_VALS,
56         HideDefaultValue => Flags::HIDE_DEFAULT_VAL,
57         HiddenShortHelp => Flags::HIDDEN_SHORT_H,
58         HiddenLongHelp => Flags::HIDDEN_LONG_H
59     }
60 }
61 
62 impl Default for ArgFlags {
default() -> Self63     fn default() -> Self { ArgFlags(Flags::EMPTY_VALS | Flags::DELIM_NOT_SET) }
64 }
65 
66 /// Various settings that apply to arguments and may be set, unset, and checked via getter/setter
67 /// methods [`Arg::set`], [`Arg::unset`], and [`Arg::is_set`]
68 ///
69 /// [`Arg::set`]: ./struct.Arg.html#method.set
70 /// [`Arg::unset`]: ./struct.Arg.html#method.unset
71 /// [`Arg::is_set`]: ./struct.Arg.html#method.is_set
72 #[derive(Debug, PartialEq, Copy, Clone)]
73 pub enum ArgSettings {
74     /// The argument must be used
75     Required,
76     /// The argument may be used multiple times such as `--flag --flag`
77     Multiple,
78     /// The argument allows empty values such as `--option ""`
79     EmptyValues,
80     /// The argument should be propagated down through all child [`SubCommand`]s
81     ///
82     /// [`SubCommand`]: ./struct.SubCommand.html
83     Global,
84     /// The argument should **not** be shown in help text
85     Hidden,
86     /// The argument accepts a value, such as `--option <value>`
87     TakesValue,
88     /// Determines if the argument allows values to be grouped via a delimiter
89     UseValueDelimiter,
90     /// Prints the help text on the line after the argument
91     NextLineHelp,
92     /// Requires the use of a value delimiter for all multiple values
93     RequireDelimiter,
94     /// Hides the possible values from the help string
95     HidePossibleValues,
96     /// Allows vals that start with a '-'
97     AllowLeadingHyphen,
98     /// Require options use `--option=val` syntax
99     RequireEquals,
100     /// Specifies that the arg is the last positional argument and may be accessed early via `--`
101     /// syntax
102     Last,
103     /// Hides the default value from the help string
104     HideDefaultValue,
105     /// Makes `Arg::possible_values` case insensitive
106     CaseInsensitive,
107     /// Hides ENV values in the help message
108     HideEnvValues,
109     /// The argument should **not** be shown in short help text
110     HiddenShortHelp,
111     /// The argument should **not** be shown in long help text
112     HiddenLongHelp,
113     #[doc(hidden)] RequiredUnlessAll,
114     #[doc(hidden)] ValueDelimiterNotSet,
115 }
116 
117 impl FromStr for ArgSettings {
118     type Err = String;
from_str(s: &str) -> Result<Self, <Self as FromStr>::Err>119     fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
120         match &*s.to_ascii_lowercase() {
121             "required" => Ok(ArgSettings::Required),
122             "multiple" => Ok(ArgSettings::Multiple),
123             "global" => Ok(ArgSettings::Global),
124             "emptyvalues" => Ok(ArgSettings::EmptyValues),
125             "hidden" => Ok(ArgSettings::Hidden),
126             "takesvalue" => Ok(ArgSettings::TakesValue),
127             "usevaluedelimiter" => Ok(ArgSettings::UseValueDelimiter),
128             "nextlinehelp" => Ok(ArgSettings::NextLineHelp),
129             "requiredunlessall" => Ok(ArgSettings::RequiredUnlessAll),
130             "requiredelimiter" => Ok(ArgSettings::RequireDelimiter),
131             "valuedelimiternotset" => Ok(ArgSettings::ValueDelimiterNotSet),
132             "hidepossiblevalues" => Ok(ArgSettings::HidePossibleValues),
133             "allowleadinghyphen" => Ok(ArgSettings::AllowLeadingHyphen),
134             "requireequals" => Ok(ArgSettings::RequireEquals),
135             "last" => Ok(ArgSettings::Last),
136             "hidedefaultvalue" => Ok(ArgSettings::HideDefaultValue),
137             "caseinsensitive" => Ok(ArgSettings::CaseInsensitive),
138             "hideenvvalues" => Ok(ArgSettings::HideEnvValues),
139             "hiddenshorthelp" => Ok(ArgSettings::HiddenShortHelp),
140             "hiddenlonghelp" => Ok(ArgSettings::HiddenLongHelp),
141             _ => Err("unknown ArgSetting, cannot convert from str".to_owned()),
142         }
143     }
144 }
145 
146 #[cfg(test)]
147 mod test {
148     use super::ArgSettings;
149 
150     #[test]
arg_settings_fromstr()151     fn arg_settings_fromstr() {
152         assert_eq!(
153             "allowleadinghyphen".parse::<ArgSettings>().unwrap(),
154             ArgSettings::AllowLeadingHyphen
155         );
156         assert_eq!(
157             "emptyvalues".parse::<ArgSettings>().unwrap(),
158             ArgSettings::EmptyValues
159         );
160         assert_eq!(
161             "global".parse::<ArgSettings>().unwrap(),
162             ArgSettings::Global
163         );
164         assert_eq!(
165             "hidepossiblevalues".parse::<ArgSettings>().unwrap(),
166             ArgSettings::HidePossibleValues
167         );
168         assert_eq!(
169             "hidden".parse::<ArgSettings>().unwrap(),
170             ArgSettings::Hidden
171         );
172         assert_eq!(
173             "multiple".parse::<ArgSettings>().unwrap(),
174             ArgSettings::Multiple
175         );
176         assert_eq!(
177             "nextlinehelp".parse::<ArgSettings>().unwrap(),
178             ArgSettings::NextLineHelp
179         );
180         assert_eq!(
181             "requiredunlessall".parse::<ArgSettings>().unwrap(),
182             ArgSettings::RequiredUnlessAll
183         );
184         assert_eq!(
185             "requiredelimiter".parse::<ArgSettings>().unwrap(),
186             ArgSettings::RequireDelimiter
187         );
188         assert_eq!(
189             "required".parse::<ArgSettings>().unwrap(),
190             ArgSettings::Required
191         );
192         assert_eq!(
193             "takesvalue".parse::<ArgSettings>().unwrap(),
194             ArgSettings::TakesValue
195         );
196         assert_eq!(
197             "usevaluedelimiter".parse::<ArgSettings>().unwrap(),
198             ArgSettings::UseValueDelimiter
199         );
200         assert_eq!(
201             "valuedelimiternotset".parse::<ArgSettings>().unwrap(),
202             ArgSettings::ValueDelimiterNotSet
203         );
204         assert_eq!(
205             "requireequals".parse::<ArgSettings>().unwrap(),
206             ArgSettings::RequireEquals
207         );
208         assert_eq!("last".parse::<ArgSettings>().unwrap(), ArgSettings::Last);
209         assert_eq!(
210             "hidedefaultvalue".parse::<ArgSettings>().unwrap(),
211             ArgSettings::HideDefaultValue
212         );
213         assert_eq!(
214             "caseinsensitive".parse::<ArgSettings>().unwrap(),
215             ArgSettings::CaseInsensitive
216         );
217         assert_eq!(
218             "hideenvvalues".parse::<ArgSettings>().unwrap(),
219             ArgSettings::HideEnvValues
220         );
221         assert_eq!(
222             "hiddenshorthelp".parse::<ArgSettings>().unwrap(),
223             ArgSettings::HiddenShortHelp
224         );
225         assert_eq!(
226             "hiddenlonghelp".parse::<ArgSettings>().unwrap(),
227             ArgSettings::HiddenLongHelp
228         );
229         assert!("hahahaha".parse::<ArgSettings>().is_err());
230     }
231 }
232