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