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