1 | #[cfg (debug_assertions)] |
2 | use crate::util::AnyValueId; |
3 | |
4 | /// Behavior of arguments when they are encountered while parsing |
5 | /// |
6 | /// # Examples |
7 | /// |
8 | /// ```rust |
9 | /// # #[cfg (feature = "help" )] { |
10 | /// # use clap_builder as clap; |
11 | /// # use clap::Command; |
12 | /// # use clap::Arg; |
13 | /// let cmd = Command::new("mycmd" ) |
14 | /// .arg( |
15 | /// Arg::new("special-help" ) |
16 | /// .short('?' ) |
17 | /// .action(clap::ArgAction::Help) |
18 | /// ); |
19 | /// |
20 | /// // Existing help still exists |
21 | /// let err = cmd.clone().try_get_matches_from(["mycmd" , "-h" ]).unwrap_err(); |
22 | /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); |
23 | /// |
24 | /// // New help available |
25 | /// let err = cmd.try_get_matches_from(["mycmd" , "-?" ]).unwrap_err(); |
26 | /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); |
27 | /// # } |
28 | /// ``` |
29 | #[derive (Clone, Debug)] |
30 | #[non_exhaustive ] |
31 | #[allow (missing_copy_implementations)] // In the future, we may accept `Box<dyn ...>` |
32 | pub enum ArgAction { |
33 | /// When encountered, store the associated value(s) in [`ArgMatches`][crate::ArgMatches] |
34 | /// |
35 | /// <div class="warning"> |
36 | /// |
37 | /// **NOTE:** If the argument has previously been seen, it will result in a |
38 | /// [`ArgumentConflict`][crate::error::ErrorKind::ArgumentConflict] unless |
39 | /// [`Command::args_override_self(true)`][crate::Command::args_override_self] is set. |
40 | /// |
41 | /// </div> |
42 | /// |
43 | /// # Examples |
44 | /// |
45 | /// ```rust |
46 | /// # use clap_builder as clap; |
47 | /// # use clap::Command; |
48 | /// # use clap::Arg; |
49 | /// let cmd = Command::new("mycmd" ) |
50 | /// .arg( |
51 | /// Arg::new("flag" ) |
52 | /// .long("flag" ) |
53 | /// .action(clap::ArgAction::Set) |
54 | /// ); |
55 | /// |
56 | /// let matches = cmd.try_get_matches_from(["mycmd" , "--flag" , "value" ]).unwrap(); |
57 | /// assert!(matches.contains_id("flag" )); |
58 | /// assert_eq!( |
59 | /// matches.get_many::<String>("flag" ).unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(), |
60 | /// vec!["value" ] |
61 | /// ); |
62 | /// ``` |
63 | Set, |
64 | /// When encountered, store the associated value(s) in [`ArgMatches`][crate::ArgMatches] |
65 | /// |
66 | /// # Examples |
67 | /// |
68 | /// ```rust |
69 | /// # use clap_builder as clap; |
70 | /// # use clap::Command; |
71 | /// # use clap::Arg; |
72 | /// let cmd = Command::new("mycmd" ) |
73 | /// .arg( |
74 | /// Arg::new("flag" ) |
75 | /// .long("flag" ) |
76 | /// .action(clap::ArgAction::Append) |
77 | /// ); |
78 | /// |
79 | /// let matches = cmd.try_get_matches_from(["mycmd" , "--flag" , "value1" , "--flag" , "value2" ]).unwrap(); |
80 | /// assert!(matches.contains_id("flag" )); |
81 | /// assert_eq!( |
82 | /// matches.get_many::<String>("flag" ).unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(), |
83 | /// vec!["value1" , "value2" ] |
84 | /// ); |
85 | /// ``` |
86 | Append, |
87 | /// When encountered, act as if `"true"` was encountered on the command-line |
88 | /// |
89 | /// If no [`default_value`][super::Arg::default_value] is set, it will be `false`. |
90 | /// |
91 | /// No value is allowed. To optionally accept a value, see |
92 | /// [`Arg::default_missing_value`][super::Arg::default_missing_value] |
93 | /// |
94 | /// <div class="warning"> |
95 | /// |
96 | /// **NOTE:** If the argument has previously been seen, it will result in a |
97 | /// [`ArgumentConflict`][crate::error::ErrorKind::ArgumentConflict] unless |
98 | /// [`Command::args_override_self(true)`][crate::Command::args_override_self] is set. |
99 | /// |
100 | /// </div> |
101 | /// |
102 | /// # Examples |
103 | /// |
104 | /// ```rust |
105 | /// # use clap_builder as clap; |
106 | /// # use clap::Command; |
107 | /// # use clap::Arg; |
108 | /// let cmd = Command::new("mycmd" ) |
109 | /// .arg( |
110 | /// Arg::new("flag" ) |
111 | /// .long("flag" ) |
112 | /// .action(clap::ArgAction::SetTrue) |
113 | /// ); |
114 | /// |
115 | /// let matches = cmd.clone().try_get_matches_from(["mycmd" , "--flag" ]).unwrap(); |
116 | /// assert!(matches.contains_id("flag" )); |
117 | /// assert_eq!( |
118 | /// matches.get_flag("flag" ), |
119 | /// true |
120 | /// ); |
121 | /// |
122 | /// let matches = cmd.try_get_matches_from(["mycmd" ]).unwrap(); |
123 | /// assert!(matches.contains_id("flag" )); |
124 | /// assert_eq!( |
125 | /// matches.get_flag("flag" ), |
126 | /// false |
127 | /// ); |
128 | /// ``` |
129 | /// |
130 | /// You can use [`TypedValueParser::map`][crate::builder::TypedValueParser::map] to have the |
131 | /// flag control an application-specific type: |
132 | /// ```rust |
133 | /// # use clap_builder as clap; |
134 | /// # use clap::Command; |
135 | /// # use clap::Arg; |
136 | /// # use clap::builder::TypedValueParser as _; |
137 | /// # use clap::builder::BoolishValueParser; |
138 | /// let cmd = Command::new("mycmd" ) |
139 | /// .arg( |
140 | /// Arg::new("flag" ) |
141 | /// .long("flag" ) |
142 | /// .action(clap::ArgAction::SetTrue) |
143 | /// .value_parser( |
144 | /// BoolishValueParser::new() |
145 | /// .map(|b| -> usize { |
146 | /// if b { 10 } else { 5 } |
147 | /// }) |
148 | /// ) |
149 | /// ); |
150 | /// |
151 | /// let matches = cmd.clone().try_get_matches_from(["mycmd" , "--flag" ]).unwrap(); |
152 | /// assert!(matches.contains_id("flag" )); |
153 | /// assert_eq!( |
154 | /// matches.get_one::<usize>("flag" ).copied(), |
155 | /// Some(10) |
156 | /// ); |
157 | /// |
158 | /// let matches = cmd.try_get_matches_from(["mycmd" ]).unwrap(); |
159 | /// assert!(matches.contains_id("flag" )); |
160 | /// assert_eq!( |
161 | /// matches.get_one::<usize>("flag" ).copied(), |
162 | /// Some(5) |
163 | /// ); |
164 | /// ``` |
165 | SetTrue, |
166 | /// When encountered, act as if `"false"` was encountered on the command-line |
167 | /// |
168 | /// If no [`default_value`][super::Arg::default_value] is set, it will be `true`. |
169 | /// |
170 | /// No value is allowed. To optionally accept a value, see |
171 | /// [`Arg::default_missing_value`][super::Arg::default_missing_value] |
172 | /// |
173 | /// <div class="warning"> |
174 | /// |
175 | /// **NOTE:** If the argument has previously been seen, it will result in a |
176 | /// [`ArgumentConflict`][crate::error::ErrorKind::ArgumentConflict] unless |
177 | /// [`Command::args_override_self(true)`][crate::Command::args_override_self] is set. |
178 | /// |
179 | /// </div> |
180 | /// |
181 | /// # Examples |
182 | /// |
183 | /// ```rust |
184 | /// # use clap_builder as clap; |
185 | /// # use clap::Command; |
186 | /// # use clap::Arg; |
187 | /// let cmd = Command::new("mycmd" ) |
188 | /// .arg( |
189 | /// Arg::new("flag" ) |
190 | /// .long("flag" ) |
191 | /// .action(clap::ArgAction::SetFalse) |
192 | /// ); |
193 | /// |
194 | /// let matches = cmd.clone().try_get_matches_from(["mycmd" , "--flag" ]).unwrap(); |
195 | /// assert!(matches.contains_id("flag" )); |
196 | /// assert_eq!( |
197 | /// matches.get_flag("flag" ), |
198 | /// false |
199 | /// ); |
200 | /// |
201 | /// let matches = cmd.try_get_matches_from(["mycmd" ]).unwrap(); |
202 | /// assert!(matches.contains_id("flag" )); |
203 | /// assert_eq!( |
204 | /// matches.get_flag("flag" ), |
205 | /// true |
206 | /// ); |
207 | /// ``` |
208 | SetFalse, |
209 | /// When encountered, increment a `u8` counter starting from `0`. |
210 | /// |
211 | /// If no [`default_value`][super::Arg::default_value] is set, it will be `0`. |
212 | /// |
213 | /// No value is allowed. To optionally accept a value, see |
214 | /// [`Arg::default_missing_value`][super::Arg::default_missing_value] |
215 | /// |
216 | /// # Examples |
217 | /// |
218 | /// ```rust |
219 | /// # use clap_builder as clap; |
220 | /// # use clap::Command; |
221 | /// # use clap::Arg; |
222 | /// let cmd = Command::new("mycmd" ) |
223 | /// .arg( |
224 | /// Arg::new("flag" ) |
225 | /// .long("flag" ) |
226 | /// .action(clap::ArgAction::Count) |
227 | /// ); |
228 | /// |
229 | /// let matches = cmd.clone().try_get_matches_from(["mycmd" , "--flag" , "--flag" ]).unwrap(); |
230 | /// assert!(matches.contains_id("flag" )); |
231 | /// assert_eq!( |
232 | /// matches.get_count("flag" ), |
233 | /// 2 |
234 | /// ); |
235 | /// |
236 | /// let matches = cmd.try_get_matches_from(["mycmd" ]).unwrap(); |
237 | /// assert!(matches.contains_id("flag" )); |
238 | /// assert_eq!( |
239 | /// matches.get_count("flag" ), |
240 | /// 0 |
241 | /// ); |
242 | /// ``` |
243 | Count, |
244 | /// When encountered, display [`Command::print_help`][super::Command::print_help] |
245 | /// |
246 | /// Depending on the flag, [`Command::print_long_help`][super::Command::print_long_help] may be shown |
247 | /// |
248 | /// # Examples |
249 | /// |
250 | /// ```rust |
251 | /// # #[cfg (feature = "help" )] { |
252 | /// # use clap_builder as clap; |
253 | /// # use clap::Command; |
254 | /// # use clap::Arg; |
255 | /// let cmd = Command::new("mycmd" ) |
256 | /// .arg( |
257 | /// Arg::new("special-help" ) |
258 | /// .short('?' ) |
259 | /// .action(clap::ArgAction::Help) |
260 | /// ); |
261 | /// |
262 | /// // Existing help still exists |
263 | /// let err = cmd.clone().try_get_matches_from(["mycmd" , "-h" ]).unwrap_err(); |
264 | /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); |
265 | /// |
266 | /// // New help available |
267 | /// let err = cmd.try_get_matches_from(["mycmd" , "-?" ]).unwrap_err(); |
268 | /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); |
269 | /// # } |
270 | /// ``` |
271 | Help, |
272 | /// When encountered, display [`Command::print_help`][super::Command::print_help] |
273 | /// |
274 | /// # Examples |
275 | /// |
276 | /// ```rust |
277 | /// # #[cfg (feature = "help" )] { |
278 | /// # use clap_builder as clap; |
279 | /// # use clap::Command; |
280 | /// # use clap::Arg; |
281 | /// let cmd = Command::new("mycmd" ) |
282 | /// .arg( |
283 | /// Arg::new("special-help" ) |
284 | /// .short('?' ) |
285 | /// .action(clap::ArgAction::HelpShort) |
286 | /// ); |
287 | /// |
288 | /// // Existing help still exists |
289 | /// let err = cmd.clone().try_get_matches_from(["mycmd" , "-h" ]).unwrap_err(); |
290 | /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); |
291 | /// |
292 | /// // New help available |
293 | /// let err = cmd.try_get_matches_from(["mycmd" , "-?" ]).unwrap_err(); |
294 | /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); |
295 | /// # } |
296 | /// ``` |
297 | HelpShort, |
298 | /// When encountered, display [`Command::print_long_help`][super::Command::print_long_help] |
299 | /// |
300 | /// # Examples |
301 | /// |
302 | /// ```rust |
303 | /// # #[cfg (feature = "help" )] { |
304 | /// # use clap_builder as clap; |
305 | /// # use clap::Command; |
306 | /// # use clap::Arg; |
307 | /// let cmd = Command::new("mycmd" ) |
308 | /// .arg( |
309 | /// Arg::new("special-help" ) |
310 | /// .short('?' ) |
311 | /// .action(clap::ArgAction::HelpLong) |
312 | /// ); |
313 | /// |
314 | /// // Existing help still exists |
315 | /// let err = cmd.clone().try_get_matches_from(["mycmd" , "-h" ]).unwrap_err(); |
316 | /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); |
317 | /// |
318 | /// // New help available |
319 | /// let err = cmd.try_get_matches_from(["mycmd" , "-?" ]).unwrap_err(); |
320 | /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); |
321 | /// # } |
322 | /// ``` |
323 | HelpLong, |
324 | /// When encountered, display [`Command::version`][super::Command::version] |
325 | /// |
326 | /// Depending on the flag, [`Command::long_version`][super::Command::long_version] may be shown |
327 | /// |
328 | /// # Examples |
329 | /// |
330 | /// ```rust |
331 | /// # use clap_builder as clap; |
332 | /// # use clap::Command; |
333 | /// # use clap::Arg; |
334 | /// let cmd = Command::new("mycmd" ) |
335 | /// .version("1.0.0" ) |
336 | /// .arg( |
337 | /// Arg::new("special-version" ) |
338 | /// .long("special-version" ) |
339 | /// .action(clap::ArgAction::Version) |
340 | /// ); |
341 | /// |
342 | /// // Existing help still exists |
343 | /// let err = cmd.clone().try_get_matches_from(["mycmd" , "--version" ]).unwrap_err(); |
344 | /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayVersion); |
345 | /// |
346 | /// // New help available |
347 | /// let err = cmd.try_get_matches_from(["mycmd" , "--special-version" ]).unwrap_err(); |
348 | /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayVersion); |
349 | /// ``` |
350 | Version, |
351 | } |
352 | |
353 | impl ArgAction { |
354 | /// Returns whether this action accepts values on the command-line |
355 | /// |
356 | /// [`default_values`][super::Arg::default_values] and [`env`][super::Arg::env] may still be |
357 | /// processed. |
358 | pub fn takes_values(&self) -> bool { |
359 | match self { |
360 | Self::Set => true, |
361 | Self::Append => true, |
362 | Self::SetTrue => false, |
363 | Self::SetFalse => false, |
364 | Self::Count => false, |
365 | Self::Help => false, |
366 | Self::HelpShort => false, |
367 | Self::HelpLong => false, |
368 | Self::Version => false, |
369 | } |
370 | } |
371 | |
372 | pub(crate) fn default_value(&self) -> Option<&'static std::ffi::OsStr> { |
373 | match self { |
374 | Self::Set => None, |
375 | Self::Append => None, |
376 | Self::SetTrue => Some(std::ffi::OsStr::new("false" )), |
377 | Self::SetFalse => Some(std::ffi::OsStr::new("true" )), |
378 | Self::Count => Some(std::ffi::OsStr::new("0" )), |
379 | Self::Help => None, |
380 | Self::HelpShort => None, |
381 | Self::HelpLong => None, |
382 | Self::Version => None, |
383 | } |
384 | } |
385 | |
386 | pub(crate) fn default_missing_value(&self) -> Option<&'static std::ffi::OsStr> { |
387 | match self { |
388 | Self::Set => None, |
389 | Self::Append => None, |
390 | Self::SetTrue => Some(std::ffi::OsStr::new("true" )), |
391 | Self::SetFalse => Some(std::ffi::OsStr::new("false" )), |
392 | Self::Count => None, |
393 | Self::Help => None, |
394 | Self::HelpShort => None, |
395 | Self::HelpLong => None, |
396 | Self::Version => None, |
397 | } |
398 | } |
399 | |
400 | pub(crate) fn default_value_parser(&self) -> Option<super::ValueParser> { |
401 | match self { |
402 | Self::Set => None, |
403 | Self::Append => None, |
404 | Self::SetTrue => Some(super::ValueParser::bool()), |
405 | Self::SetFalse => Some(super::ValueParser::bool()), |
406 | Self::Count => Some(crate::value_parser!(u8).into()), |
407 | Self::Help => None, |
408 | Self::HelpShort => None, |
409 | Self::HelpLong => None, |
410 | Self::Version => None, |
411 | } |
412 | } |
413 | |
414 | #[cfg (debug_assertions)] |
415 | pub(crate) fn value_type_id(&self) -> Option<AnyValueId> { |
416 | match self { |
417 | Self::Set => None, |
418 | Self::Append => None, |
419 | Self::SetTrue => None, |
420 | Self::SetFalse => None, |
421 | Self::Count => Some(AnyValueId::of::<CountType>()), |
422 | Self::Help => None, |
423 | Self::HelpShort => None, |
424 | Self::HelpLong => None, |
425 | Self::Version => None, |
426 | } |
427 | } |
428 | } |
429 | |
430 | pub(crate) type CountType = u8; |
431 | |