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