1 /// Behavior of arguments when they are encountered while parsing 2 /// 3 /// # Examples 4 /// 5 /// ```rust 6 /// # use clap::Command; 7 /// # use clap::Arg; 8 /// let cmd = Command::new("mycmd") 9 /// .arg( 10 /// Arg::new("special-help") 11 /// .short('?') 12 /// .action(clap::ArgAction::Help) 13 /// ); 14 /// 15 /// // Existing help still exists 16 /// let err = cmd.clone().try_get_matches_from(["mycmd", "-h"]).unwrap_err(); 17 /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); 18 /// 19 /// // New help available 20 /// let err = cmd.try_get_matches_from(["mycmd", "-?"]).unwrap_err(); 21 /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); 22 /// ``` 23 #[derive(Clone, Debug)] 24 #[non_exhaustive] 25 #[allow(missing_copy_implementations)] // In the future, we may accept `Box<dyn ...>` 26 pub enum ArgAction { 27 /// When encountered, store the associated value(s) in [`ArgMatches`][crate::ArgMatches] 28 /// 29 /// # Examples 30 /// 31 /// ```rust 32 /// # use clap::Command; 33 /// # use clap::Arg; 34 /// let cmd = Command::new("mycmd") 35 /// .arg( 36 /// Arg::new("flag") 37 /// .long("flag") 38 /// .action(clap::ArgAction::Set) 39 /// ); 40 /// 41 /// let matches = cmd.try_get_matches_from(["mycmd", "--flag", "value"]).unwrap(); 42 /// assert!(matches.contains_id("flag")); 43 /// assert_eq!(matches.occurrences_of("flag"), 0); 44 /// assert_eq!( 45 /// matches.get_many::<String>("flag").unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(), 46 /// vec!["value"] 47 /// ); 48 /// ``` 49 Set, 50 /// When encountered, store the associated value(s) in [`ArgMatches`][crate::ArgMatches] 51 /// 52 /// # Examples 53 /// 54 /// ```rust 55 /// # use clap::Command; 56 /// # use clap::Arg; 57 /// let cmd = Command::new("mycmd") 58 /// .arg( 59 /// Arg::new("flag") 60 /// .long("flag") 61 /// .action(clap::ArgAction::Append) 62 /// ); 63 /// 64 /// let matches = cmd.try_get_matches_from(["mycmd", "--flag", "value1", "--flag", "value2"]).unwrap(); 65 /// assert!(matches.contains_id("flag")); 66 /// assert_eq!(matches.occurrences_of("flag"), 0); 67 /// assert_eq!( 68 /// matches.get_many::<String>("flag").unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(), 69 /// vec!["value1", "value2"] 70 /// ); 71 /// ``` 72 Append, 73 /// Deprecated, replaced with [`ArgAction::Set`] or [`ArgAction::Append`] 74 /// 75 /// Builder: Instead of `arg.action(ArgAction::StoreValue)`, 76 /// - Use `arg.action(ArgAction::Set)` for single-occurrence arguments 77 /// - Use `arg.action(ArgAction::Append)` for multiple-occurrence arguments 78 /// 79 /// Derive: opt-in to the new behavior with `#[clap(action)]` 80 #[cfg_attr( 81 feature = "deprecated", 82 deprecated( 83 since = "3.2.0", 84 note = "Replaced with `ArgAction::Set` or `ArgAction::Append` 85 86 Derive: opt-in to the new behavior with `#[clap(action)]` 87 88 Builder: Instead of `arg.action(ArgAction::StoreValue)`, 89 - Use `arg.action(ArgAction::Set)` for single-occurrence arguments 90 - Use `arg.action(ArgAction::Append)` for multiple-occurrence arguments 91 " 92 ) 93 )] 94 StoreValue, 95 /// Deprecated, replaced with [`ArgAction::SetTrue`] or [`ArgAction::Count`] 96 #[cfg_attr( 97 feature = "deprecated", 98 deprecated( 99 since = "3.2.0", 100 note = "Replaced with `ArgAction::SetTrue` or `ArgAction::Count` 101 102 Derive: opt-in to the new behavior with `#[clap(action)]` 103 104 Builder: Instead of `arg.action(ArgAction::IncOccurrence)`, 105 - Use `arg.action(ArgAction::SetTrue)` if you just care if its set, then switch `matches.is_present` to `matches.get_flag` 106 - Use `arg.action(ArgAction::Count)` if you care how many times its set, then switch `matches.occurrences_of` to `matches.get_count` 107 " 108 ) 109 )] 110 IncOccurrence, 111 /// When encountered, act as if `"true"` was encountered on the command-line 112 /// 113 /// If no [`default_value`][super::Arg::default_value] is set, it will be `false`. 114 /// 115 /// No value is allowed. To optionally accept a value, see 116 /// [`Arg::default_missing_value`][super::Arg::default_missing_value] 117 /// 118 /// # Examples 119 /// 120 /// ```rust 121 /// # use clap::Command; 122 /// # use clap::Arg; 123 /// let cmd = Command::new("mycmd") 124 /// .arg( 125 /// Arg::new("flag") 126 /// .long("flag") 127 /// .action(clap::ArgAction::SetTrue) 128 /// ); 129 /// 130 /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag", "--flag"]).unwrap(); 131 /// assert!(matches.contains_id("flag")); 132 /// assert_eq!(matches.occurrences_of("flag"), 0); 133 /// assert_eq!( 134 /// matches.get_one::<bool>("flag").copied(), 135 /// Some(true) 136 /// ); 137 /// 138 /// let matches = cmd.try_get_matches_from(["mycmd"]).unwrap(); 139 /// assert!(matches.contains_id("flag")); 140 /// assert_eq!(matches.occurrences_of("flag"), 0); 141 /// assert_eq!( 142 /// matches.get_one::<bool>("flag").copied(), 143 /// Some(false) 144 /// ); 145 /// ``` 146 SetTrue, 147 /// When encountered, act as if `"false"` was encountered on the command-line 148 /// 149 /// If no [`default_value`][super::Arg::default_value] is set, it will be `true`. 150 /// 151 /// No value is allowed. To optionally accept a value, see 152 /// [`Arg::default_missing_value`][super::Arg::default_missing_value] 153 /// 154 /// # Examples 155 /// 156 /// ```rust 157 /// # use clap::Command; 158 /// # use clap::Arg; 159 /// let cmd = Command::new("mycmd") 160 /// .arg( 161 /// Arg::new("flag") 162 /// .long("flag") 163 /// .action(clap::ArgAction::SetFalse) 164 /// ); 165 /// 166 /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag", "--flag"]).unwrap(); 167 /// assert!(matches.contains_id("flag")); 168 /// assert_eq!(matches.occurrences_of("flag"), 0); 169 /// assert_eq!( 170 /// matches.get_one::<bool>("flag").copied(), 171 /// Some(false) 172 /// ); 173 /// 174 /// let matches = cmd.try_get_matches_from(["mycmd"]).unwrap(); 175 /// assert!(matches.contains_id("flag")); 176 /// assert_eq!(matches.occurrences_of("flag"), 0); 177 /// assert_eq!( 178 /// matches.get_one::<bool>("flag").copied(), 179 /// Some(true) 180 /// ); 181 /// ``` 182 SetFalse, 183 /// When encountered, increment a `u8` counter 184 /// 185 /// If no [`default_value`][super::Arg::default_value] is set, it will be `0`. 186 /// 187 /// No value is allowed. To optionally accept a value, see 188 /// [`Arg::default_missing_value`][super::Arg::default_missing_value] 189 /// 190 /// # Examples 191 /// 192 /// ```rust 193 /// # use clap::Command; 194 /// # use clap::Arg; 195 /// let cmd = Command::new("mycmd") 196 /// .arg( 197 /// Arg::new("flag") 198 /// .long("flag") 199 /// .action(clap::ArgAction::Count) 200 /// ); 201 /// 202 /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag", "--flag"]).unwrap(); 203 /// assert!(matches.contains_id("flag")); 204 /// assert_eq!(matches.occurrences_of("flag"), 0); 205 /// assert_eq!( 206 /// matches.get_count("flag"), 207 /// 2 208 /// ); 209 /// 210 /// let matches = cmd.try_get_matches_from(["mycmd"]).unwrap(); 211 /// assert!(matches.contains_id("flag")); 212 /// assert_eq!(matches.occurrences_of("flag"), 0); 213 /// assert_eq!( 214 /// matches.get_count("flag"), 215 /// 0 216 /// ); 217 /// ``` 218 Count, 219 /// When encountered, display [`Command::print_help`][super::App::print_help] 220 /// 221 /// Depending on the flag, [`Command::print_long_help`][super::App::print_long_help] may be shown 222 /// 223 /// # Examples 224 /// 225 /// ```rust 226 /// # use clap::Command; 227 /// # use clap::Arg; 228 /// let cmd = Command::new("mycmd") 229 /// .arg( 230 /// Arg::new("special-help") 231 /// .short('?') 232 /// .action(clap::ArgAction::Help) 233 /// ); 234 /// 235 /// // Existing help still exists 236 /// let err = cmd.clone().try_get_matches_from(["mycmd", "-h"]).unwrap_err(); 237 /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); 238 /// 239 /// // New help available 240 /// let err = cmd.try_get_matches_from(["mycmd", "-?"]).unwrap_err(); 241 /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); 242 /// ``` 243 Help, 244 /// When encountered, display [`Command::version`][super::App::version] 245 /// 246 /// Depending on the flag, [`Command::long_version`][super::App::long_version] may be shown 247 /// 248 /// # Examples 249 /// 250 /// ```rust 251 /// # use clap::Command; 252 /// # use clap::Arg; 253 /// let cmd = Command::new("mycmd") 254 /// .version("1.0.0") 255 /// .arg( 256 /// Arg::new("special-version") 257 /// .long("special-version") 258 /// .action(clap::ArgAction::Version) 259 /// ); 260 /// 261 /// // Existing help still exists 262 /// let err = cmd.clone().try_get_matches_from(["mycmd", "--version"]).unwrap_err(); 263 /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayVersion); 264 /// 265 /// // New help available 266 /// let err = cmd.try_get_matches_from(["mycmd", "--special-version"]).unwrap_err(); 267 /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayVersion); 268 /// ``` 269 Version, 270 } 271 272 impl ArgAction { 273 /// Returns whether this action accepts values on the command-line 274 /// 275 /// [`default_values`][super::Arg::default_values] and [`env`][super::Arg::env] may still be 276 /// processed. takes_values(&self) -> bool277 pub fn takes_values(&self) -> bool { 278 match self { 279 Self::Set => true, 280 Self::Append => true, 281 #[allow(deprecated)] 282 Self::StoreValue => true, 283 #[allow(deprecated)] 284 Self::IncOccurrence => false, 285 Self::SetTrue => false, 286 Self::SetFalse => false, 287 Self::Count => false, 288 Self::Help => false, 289 Self::Version => false, 290 } 291 } 292 default_value(&self) -> Option<&'static std::ffi::OsStr>293 pub(crate) fn default_value(&self) -> Option<&'static std::ffi::OsStr> { 294 match self { 295 Self::Set => None, 296 Self::Append => None, 297 #[allow(deprecated)] 298 Self::StoreValue => None, 299 #[allow(deprecated)] 300 Self::IncOccurrence => None, 301 Self::SetTrue => Some(std::ffi::OsStr::new("false")), 302 Self::SetFalse => Some(std::ffi::OsStr::new("true")), 303 Self::Count => Some(std::ffi::OsStr::new("0")), 304 Self::Help => None, 305 Self::Version => None, 306 } 307 } 308 default_value_parser(&self) -> Option<super::ValueParser>309 pub(crate) fn default_value_parser(&self) -> Option<super::ValueParser> { 310 match self { 311 Self::Set => None, 312 Self::Append => None, 313 #[allow(deprecated)] 314 Self::StoreValue => None, 315 #[allow(deprecated)] 316 Self::IncOccurrence => None, 317 Self::SetTrue => Some(super::ValueParser::bool()), 318 Self::SetFalse => Some(super::ValueParser::bool()), 319 Self::Count => Some(crate::value_parser!(u8).into()), 320 Self::Help => None, 321 Self::Version => None, 322 } 323 } 324 325 #[cfg(debug_assertions)] value_type_id(&self) -> Option<crate::parser::AnyValueId>326 pub(crate) fn value_type_id(&self) -> Option<crate::parser::AnyValueId> { 327 use crate::parser::AnyValueId; 328 329 match self { 330 Self::Set => None, 331 Self::Append => None, 332 #[allow(deprecated)] 333 Self::StoreValue => None, 334 #[allow(deprecated)] 335 Self::IncOccurrence => None, 336 Self::SetTrue => Some(AnyValueId::of::<bool>()), 337 Self::SetFalse => Some(AnyValueId::of::<bool>()), 338 Self::Count => Some(AnyValueId::of::<CountType>()), 339 Self::Help => None, 340 Self::Version => None, 341 } 342 } 343 } 344 345 pub(crate) type CountType = u8; 346