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