1 #[cfg(feature = "yaml")] 2 use std::collections::BTreeMap; 3 use std::fmt::{Debug, Formatter, Result}; 4 5 #[cfg(feature = "yaml")] 6 use yaml_rust::Yaml; 7 8 /// `ArgGroup`s are a family of related [arguments] and way for you to express, "Any of these 9 /// arguments". By placing arguments in a logical group, you can create easier requirement and 10 /// exclusion rules instead of having to list each argument individually, or when you want a rule 11 /// to apply "any but not all" arguments. 12 /// 13 /// For instance, you can make an entire `ArgGroup` required. If [`ArgGroup::multiple(true)`] is 14 /// set, this means that at least one argument from that group must be present. If 15 /// [`ArgGroup::multiple(false)`] is set (the default), one and *only* one must be present. 16 /// 17 /// You can also do things such as name an entire `ArgGroup` as a [conflict] or [requirement] for 18 /// another argument, meaning any of the arguments that belong to that group will cause a failure 19 /// if present, or must present respectively. 20 /// 21 /// Perhaps the most common use of `ArgGroup`s is to require one and *only* one argument to be 22 /// present out of a given set. Imagine that you had multiple arguments, and you want one of them 23 /// to be required, but making all of them required isn't feasible because perhaps they conflict 24 /// with each other. For example, lets say that you were building an application where one could 25 /// set a given version number by supplying a string with an option argument, i.e. 26 /// `--set-ver v1.2.3`, you also wanted to support automatically using a previous version number 27 /// and simply incrementing one of the three numbers. So you create three flags `--major`, 28 /// `--minor`, and `--patch`. All of these arguments shouldn't be used at one time but you want to 29 /// specify that *at least one* of them is used. For this, you can create a group. 30 /// 31 /// Finally, you may use `ArgGroup`s to pull a value from a group of arguments when you don't care 32 /// exactly which argument was actually used at runtime. 33 /// 34 /// # Examples 35 /// 36 /// The following example demonstrates using an `ArgGroup` to ensure that one, and only one, of 37 /// the arguments from the specified group is present at runtime. 38 /// 39 /// ```rust 40 /// # use clap::{App, ArgGroup, ErrorKind}; 41 /// let result = App::new("app") 42 /// .args_from_usage( 43 /// "--set-ver [ver] 'set the version manually' 44 /// --major 'auto increase major' 45 /// --minor 'auto increase minor' 46 /// --patch 'auto increase patch'") 47 /// .group(ArgGroup::with_name("vers") 48 /// .args(&["set-ver", "major", "minor", "patch"]) 49 /// .required(true)) 50 /// .get_matches_from_safe(vec!["app", "--major", "--patch"]); 51 /// // Because we used two args in the group it's an error 52 /// assert!(result.is_err()); 53 /// let err = result.unwrap_err(); 54 /// assert_eq!(err.kind, ErrorKind::ArgumentConflict); 55 /// ``` 56 /// This next example shows a passing parse of the same scenario 57 /// 58 /// ```rust 59 /// # use clap::{App, ArgGroup}; 60 /// let result = App::new("app") 61 /// .args_from_usage( 62 /// "--set-ver [ver] 'set the version manually' 63 /// --major 'auto increase major' 64 /// --minor 'auto increase minor' 65 /// --patch 'auto increase patch'") 66 /// .group(ArgGroup::with_name("vers") 67 /// .args(&["set-ver", "major", "minor","patch"]) 68 /// .required(true)) 69 /// .get_matches_from_safe(vec!["app", "--major"]); 70 /// assert!(result.is_ok()); 71 /// let matches = result.unwrap(); 72 /// // We may not know which of the args was used, so we can test for the group... 73 /// assert!(matches.is_present("vers")); 74 /// // we could also alternatively check each arg individually (not shown here) 75 /// ``` 76 /// [`ArgGroup::multiple(true)`]: ./struct.ArgGroup.html#method.multiple 77 /// [arguments]: ./struct.Arg.html 78 /// [conflict]: ./struct.Arg.html#method.conflicts_with 79 /// [requirement]: ./struct.Arg.html#method.requires 80 #[derive(Default)] 81 pub struct ArgGroup<'a> { 82 #[doc(hidden)] 83 pub name: &'a str, 84 #[doc(hidden)] 85 pub args: Vec<&'a str>, 86 #[doc(hidden)] 87 pub required: bool, 88 #[doc(hidden)] 89 pub requires: Option<Vec<&'a str>>, 90 #[doc(hidden)] 91 pub conflicts: Option<Vec<&'a str>>, 92 #[doc(hidden)] 93 pub multiple: bool, 94 } 95 96 impl<'a> ArgGroup<'a> { 97 /// Creates a new instance of `ArgGroup` using a unique string name. The name will be used to 98 /// get values from the group or refer to the group inside of conflict and requirement rules. 99 /// 100 /// # Examples 101 /// 102 /// ```rust 103 /// # use clap::{App, ArgGroup}; 104 /// ArgGroup::with_name("config") 105 /// # ; 106 /// ``` with_name(n: &'a str) -> Self107 pub fn with_name(n: &'a str) -> Self { 108 ArgGroup { 109 name: n, 110 required: false, 111 args: vec![], 112 requires: None, 113 conflicts: None, 114 multiple: false, 115 } 116 } 117 118 /// Creates a new instance of `ArgGroup` from a .yml (YAML) file. 119 /// 120 /// # Examples 121 /// 122 /// ```ignore 123 /// # #[macro_use] 124 /// # extern crate clap; 125 /// # use clap::ArgGroup; 126 /// # fn main() { 127 /// let yml = load_yaml!("group.yml"); 128 /// let ag = ArgGroup::from_yaml(yml); 129 /// # } 130 /// ``` 131 #[cfg(feature = "yaml")] from_yaml(y: &'a Yaml) -> ArgGroup<'a>132 pub fn from_yaml(y: &'a Yaml) -> ArgGroup<'a> { 133 ArgGroup::from(y.as_hash().unwrap()) 134 } 135 136 /// Adds an [argument] to this group by name 137 /// 138 /// # Examples 139 /// 140 /// ```rust 141 /// # use clap::{App, Arg, ArgGroup}; 142 /// let m = App::new("myprog") 143 /// .arg(Arg::with_name("flag") 144 /// .short("f")) 145 /// .arg(Arg::with_name("color") 146 /// .short("c")) 147 /// .group(ArgGroup::with_name("req_flags") 148 /// .arg("flag") 149 /// .arg("color")) 150 /// .get_matches_from(vec!["myprog", "-f"]); 151 /// // maybe we don't know which of the two flags was used... 152 /// assert!(m.is_present("req_flags")); 153 /// // but we can also check individually if needed 154 /// assert!(m.is_present("flag")); 155 /// ``` 156 /// [argument]: ./struct.Arg.html 157 #[cfg_attr(feature = "lints", allow(should_assert_eq))] arg(mut self, n: &'a str) -> Self158 pub fn arg(mut self, n: &'a str) -> Self { 159 assert!( 160 self.name != n, 161 "ArgGroup '{}' can not have same name as arg inside it", 162 &*self.name 163 ); 164 self.args.push(n); 165 self 166 } 167 168 /// Adds multiple [arguments] to this group by name 169 /// 170 /// # Examples 171 /// 172 /// ```rust 173 /// # use clap::{App, Arg, ArgGroup}; 174 /// let m = App::new("myprog") 175 /// .arg(Arg::with_name("flag") 176 /// .short("f")) 177 /// .arg(Arg::with_name("color") 178 /// .short("c")) 179 /// .group(ArgGroup::with_name("req_flags") 180 /// .args(&["flag", "color"])) 181 /// .get_matches_from(vec!["myprog", "-f"]); 182 /// // maybe we don't know which of the two flags was used... 183 /// assert!(m.is_present("req_flags")); 184 /// // but we can also check individually if needed 185 /// assert!(m.is_present("flag")); 186 /// ``` 187 /// [arguments]: ./struct.Arg.html args(mut self, ns: &[&'a str]) -> Self188 pub fn args(mut self, ns: &[&'a str]) -> Self { 189 for n in ns { 190 self = self.arg(n); 191 } 192 self 193 } 194 195 /// Allows more than one of the ['Arg']s in this group to be used. (Default: `false`) 196 /// 197 /// # Examples 198 /// 199 /// Notice in this example we use *both* the `-f` and `-c` flags which are both part of the 200 /// group 201 /// 202 /// ```rust 203 /// # use clap::{App, Arg, ArgGroup}; 204 /// let m = App::new("myprog") 205 /// .arg(Arg::with_name("flag") 206 /// .short("f")) 207 /// .arg(Arg::with_name("color") 208 /// .short("c")) 209 /// .group(ArgGroup::with_name("req_flags") 210 /// .args(&["flag", "color"]) 211 /// .multiple(true)) 212 /// .get_matches_from(vec!["myprog", "-f", "-c"]); 213 /// // maybe we don't know which of the two flags was used... 214 /// assert!(m.is_present("req_flags")); 215 /// ``` 216 /// In this next example, we show the default behavior (i.e. `multiple(false)) which will throw 217 /// an error if more than one of the args in the group was used. 218 /// 219 /// ```rust 220 /// # use clap::{App, Arg, ArgGroup, ErrorKind}; 221 /// let result = App::new("myprog") 222 /// .arg(Arg::with_name("flag") 223 /// .short("f")) 224 /// .arg(Arg::with_name("color") 225 /// .short("c")) 226 /// .group(ArgGroup::with_name("req_flags") 227 /// .args(&["flag", "color"])) 228 /// .get_matches_from_safe(vec!["myprog", "-f", "-c"]); 229 /// // Because we used both args in the group it's an error 230 /// assert!(result.is_err()); 231 /// let err = result.unwrap_err(); 232 /// assert_eq!(err.kind, ErrorKind::ArgumentConflict); 233 /// ``` 234 /// ['Arg']: ./struct.Arg.html multiple(mut self, m: bool) -> Self235 pub fn multiple(mut self, m: bool) -> Self { 236 self.multiple = m; 237 self 238 } 239 240 /// Sets the group as required or not. A required group will be displayed in the usage string 241 /// of the application in the format `<arg|arg2|arg3>`. A required `ArgGroup` simply states 242 /// that one argument from this group *must* be present at runtime (unless 243 /// conflicting with another argument). 244 /// 245 /// **NOTE:** This setting only applies to the current [`App`] / [`SubCommand`], and not 246 /// globally. 247 /// 248 /// **NOTE:** By default, [`ArgGroup::multiple`] is set to `false` which when combined with 249 /// `ArgGroup::required(true)` states, "One and *only one* arg must be used from this group. 250 /// Use of more than one arg is an error." Vice setting `ArgGroup::multiple(true)` which 251 /// states, '*At least* one arg from this group must be used. Using multiple is OK." 252 /// 253 /// # Examples 254 /// 255 /// ```rust 256 /// # use clap::{App, Arg, ArgGroup, ErrorKind}; 257 /// let result = App::new("myprog") 258 /// .arg(Arg::with_name("flag") 259 /// .short("f")) 260 /// .arg(Arg::with_name("color") 261 /// .short("c")) 262 /// .group(ArgGroup::with_name("req_flags") 263 /// .args(&["flag", "color"]) 264 /// .required(true)) 265 /// .get_matches_from_safe(vec!["myprog"]); 266 /// // Because we didn't use any of the args in the group, it's an error 267 /// assert!(result.is_err()); 268 /// let err = result.unwrap_err(); 269 /// assert_eq!(err.kind, ErrorKind::MissingRequiredArgument); 270 /// ``` 271 /// [`App`]: ./struct.App.html 272 /// [`SubCommand`]: ./struct.SubCommand.html 273 /// [`ArgGroup::multiple`]: ./struct.ArgGroup.html#method.multiple required(mut self, r: bool) -> Self274 pub fn required(mut self, r: bool) -> Self { 275 self.required = r; 276 self 277 } 278 279 /// Sets the requirement rules of this group. This is not to be confused with a 280 /// [required group]. Requirement rules function just like [argument requirement rules], you 281 /// can name other arguments or groups that must be present when any one of the arguments from 282 /// this group is used. 283 /// 284 /// **NOTE:** The name provided may be an argument, or group name 285 /// 286 /// # Examples 287 /// 288 /// ```rust 289 /// # use clap::{App, Arg, ArgGroup, ErrorKind}; 290 /// let result = App::new("myprog") 291 /// .arg(Arg::with_name("flag") 292 /// .short("f")) 293 /// .arg(Arg::with_name("color") 294 /// .short("c")) 295 /// .arg(Arg::with_name("debug") 296 /// .short("d")) 297 /// .group(ArgGroup::with_name("req_flags") 298 /// .args(&["flag", "color"]) 299 /// .requires("debug")) 300 /// .get_matches_from_safe(vec!["myprog", "-c"]); 301 /// // because we used an arg from the group, and the group requires "-d" to be used, it's an 302 /// // error 303 /// assert!(result.is_err()); 304 /// let err = result.unwrap_err(); 305 /// assert_eq!(err.kind, ErrorKind::MissingRequiredArgument); 306 /// ``` 307 /// [required group]: ./struct.ArgGroup.html#method.required 308 /// [argument requirement rules]: ./struct.Arg.html#method.requires requires(mut self, n: &'a str) -> Self309 pub fn requires(mut self, n: &'a str) -> Self { 310 if let Some(ref mut reqs) = self.requires { 311 reqs.push(n); 312 } else { 313 self.requires = Some(vec![n]); 314 } 315 self 316 } 317 318 /// Sets the requirement rules of this group. This is not to be confused with a 319 /// [required group]. Requirement rules function just like [argument requirement rules], you 320 /// can name other arguments or groups that must be present when one of the arguments from this 321 /// group is used. 322 /// 323 /// **NOTE:** The names provided may be an argument, or group name 324 /// 325 /// # Examples 326 /// 327 /// ```rust 328 /// # use clap::{App, Arg, ArgGroup, ErrorKind}; 329 /// let result = App::new("myprog") 330 /// .arg(Arg::with_name("flag") 331 /// .short("f")) 332 /// .arg(Arg::with_name("color") 333 /// .short("c")) 334 /// .arg(Arg::with_name("debug") 335 /// .short("d")) 336 /// .arg(Arg::with_name("verb") 337 /// .short("v")) 338 /// .group(ArgGroup::with_name("req_flags") 339 /// .args(&["flag", "color"]) 340 /// .requires_all(&["debug", "verb"])) 341 /// .get_matches_from_safe(vec!["myprog", "-c", "-d"]); 342 /// // because we used an arg from the group, and the group requires "-d" and "-v" to be used, 343 /// // yet we only used "-d" it's an error 344 /// assert!(result.is_err()); 345 /// let err = result.unwrap_err(); 346 /// assert_eq!(err.kind, ErrorKind::MissingRequiredArgument); 347 /// ``` 348 /// [required group]: ./struct.ArgGroup.html#method.required 349 /// [argument requirement rules]: ./struct.Arg.html#method.requires_all requires_all(mut self, ns: &[&'a str]) -> Self350 pub fn requires_all(mut self, ns: &[&'a str]) -> Self { 351 for n in ns { 352 self = self.requires(n); 353 } 354 self 355 } 356 357 /// Sets the exclusion rules of this group. Exclusion (aka conflict) rules function just like 358 /// [argument exclusion rules], you can name other arguments or groups that must *not* be 359 /// present when one of the arguments from this group are used. 360 /// 361 /// **NOTE:** The name provided may be an argument, or group name 362 /// 363 /// # Examples 364 /// 365 /// ```rust 366 /// # use clap::{App, Arg, ArgGroup, ErrorKind}; 367 /// let result = App::new("myprog") 368 /// .arg(Arg::with_name("flag") 369 /// .short("f")) 370 /// .arg(Arg::with_name("color") 371 /// .short("c")) 372 /// .arg(Arg::with_name("debug") 373 /// .short("d")) 374 /// .group(ArgGroup::with_name("req_flags") 375 /// .args(&["flag", "color"]) 376 /// .conflicts_with("debug")) 377 /// .get_matches_from_safe(vec!["myprog", "-c", "-d"]); 378 /// // because we used an arg from the group, and the group conflicts with "-d", it's an error 379 /// assert!(result.is_err()); 380 /// let err = result.unwrap_err(); 381 /// assert_eq!(err.kind, ErrorKind::ArgumentConflict); 382 /// ``` 383 /// [argument exclusion rules]: ./struct.Arg.html#method.conflicts_with conflicts_with(mut self, n: &'a str) -> Self384 pub fn conflicts_with(mut self, n: &'a str) -> Self { 385 if let Some(ref mut confs) = self.conflicts { 386 confs.push(n); 387 } else { 388 self.conflicts = Some(vec![n]); 389 } 390 self 391 } 392 393 /// Sets the exclusion rules of this group. Exclusion rules function just like 394 /// [argument exclusion rules], you can name other arguments or groups that must *not* be 395 /// present when one of the arguments from this group are used. 396 /// 397 /// **NOTE:** The names provided may be an argument, or group name 398 /// 399 /// # Examples 400 /// 401 /// ```rust 402 /// # use clap::{App, Arg, ArgGroup, ErrorKind}; 403 /// let result = App::new("myprog") 404 /// .arg(Arg::with_name("flag") 405 /// .short("f")) 406 /// .arg(Arg::with_name("color") 407 /// .short("c")) 408 /// .arg(Arg::with_name("debug") 409 /// .short("d")) 410 /// .arg(Arg::with_name("verb") 411 /// .short("v")) 412 /// .group(ArgGroup::with_name("req_flags") 413 /// .args(&["flag", "color"]) 414 /// .conflicts_with_all(&["debug", "verb"])) 415 /// .get_matches_from_safe(vec!["myprog", "-c", "-v"]); 416 /// // because we used an arg from the group, and the group conflicts with either "-v" or "-d" 417 /// // it's an error 418 /// assert!(result.is_err()); 419 /// let err = result.unwrap_err(); 420 /// assert_eq!(err.kind, ErrorKind::ArgumentConflict); 421 /// ``` 422 /// [argument exclusion rules]: ./struct.Arg.html#method.conflicts_with_all conflicts_with_all(mut self, ns: &[&'a str]) -> Self423 pub fn conflicts_with_all(mut self, ns: &[&'a str]) -> Self { 424 for n in ns { 425 self = self.conflicts_with(n); 426 } 427 self 428 } 429 } 430 431 impl<'a> Debug for ArgGroup<'a> { fmt(&self, f: &mut Formatter) -> Result432 fn fmt(&self, f: &mut Formatter) -> Result { 433 write!( 434 f, 435 "{{\n\ 436 \tname: {:?},\n\ 437 \targs: {:?},\n\ 438 \trequired: {:?},\n\ 439 \trequires: {:?},\n\ 440 \tconflicts: {:?},\n\ 441 }}", 442 self.name, self.args, self.required, self.requires, self.conflicts 443 ) 444 } 445 } 446 447 impl<'a, 'z> From<&'z ArgGroup<'a>> for ArgGroup<'a> { from(g: &'z ArgGroup<'a>) -> Self448 fn from(g: &'z ArgGroup<'a>) -> Self { 449 ArgGroup { 450 name: g.name, 451 required: g.required, 452 args: g.args.clone(), 453 requires: g.requires.clone(), 454 conflicts: g.conflicts.clone(), 455 multiple: g.multiple, 456 } 457 } 458 } 459 460 #[cfg(feature = "yaml")] 461 impl<'a> From<&'a BTreeMap<Yaml, Yaml>> for ArgGroup<'a> { from(b: &'a BTreeMap<Yaml, Yaml>) -> Self462 fn from(b: &'a BTreeMap<Yaml, Yaml>) -> Self { 463 // We WANT this to panic on error...so expect() is good. 464 let mut a = ArgGroup::default(); 465 let group_settings = if b.len() == 1 { 466 let name_yml = b.keys().nth(0).expect("failed to get name"); 467 let name_str = name_yml 468 .as_str() 469 .expect("failed to convert arg YAML name to str"); 470 a.name = name_str; 471 b.get(name_yml) 472 .expect("failed to get name_str") 473 .as_hash() 474 .expect("failed to convert to a hash") 475 } else { 476 b 477 }; 478 479 for (k, v) in group_settings { 480 a = match k.as_str().unwrap() { 481 "required" => a.required(v.as_bool().unwrap()), 482 "multiple" => a.multiple(v.as_bool().unwrap()), 483 "args" => yaml_vec_or_str!(v, a, arg), 484 "arg" => { 485 if let Some(ys) = v.as_str() { 486 a = a.arg(ys); 487 } 488 a 489 } 490 "requires" => yaml_vec_or_str!(v, a, requires), 491 "conflicts_with" => yaml_vec_or_str!(v, a, conflicts_with), 492 "name" => { 493 if let Some(ys) = v.as_str() { 494 a.name = ys; 495 } 496 a 497 } 498 s => panic!( 499 "Unknown ArgGroup setting '{}' in YAML file for \ 500 ArgGroup '{}'", 501 s, a.name 502 ), 503 } 504 } 505 506 a 507 } 508 } 509 510 #[cfg(test)] 511 mod test { 512 use super::ArgGroup; 513 #[cfg(feature = "yaml")] 514 use yaml_rust::YamlLoader; 515 516 #[test] groups()517 fn groups() { 518 let g = ArgGroup::with_name("test") 519 .arg("a1") 520 .arg("a4") 521 .args(&["a2", "a3"]) 522 .required(true) 523 .conflicts_with("c1") 524 .conflicts_with_all(&["c2", "c3"]) 525 .conflicts_with("c4") 526 .requires("r1") 527 .requires_all(&["r2", "r3"]) 528 .requires("r4"); 529 530 let args = vec!["a1", "a4", "a2", "a3"]; 531 let reqs = vec!["r1", "r2", "r3", "r4"]; 532 let confs = vec!["c1", "c2", "c3", "c4"]; 533 534 assert_eq!(g.args, args); 535 assert_eq!(g.requires, Some(reqs)); 536 assert_eq!(g.conflicts, Some(confs)); 537 } 538 539 #[test] test_debug()540 fn test_debug() { 541 let g = ArgGroup::with_name("test") 542 .arg("a1") 543 .arg("a4") 544 .args(&["a2", "a3"]) 545 .required(true) 546 .conflicts_with("c1") 547 .conflicts_with_all(&["c2", "c3"]) 548 .conflicts_with("c4") 549 .requires("r1") 550 .requires_all(&["r2", "r3"]) 551 .requires("r4"); 552 553 let args = vec!["a1", "a4", "a2", "a3"]; 554 let reqs = vec!["r1", "r2", "r3", "r4"]; 555 let confs = vec!["c1", "c2", "c3", "c4"]; 556 557 let debug_str = format!( 558 "{{\n\ 559 \tname: \"test\",\n\ 560 \targs: {:?},\n\ 561 \trequired: {:?},\n\ 562 \trequires: {:?},\n\ 563 \tconflicts: {:?},\n\ 564 }}", 565 args, 566 true, 567 Some(reqs), 568 Some(confs) 569 ); 570 assert_eq!(&*format!("{:?}", g), &*debug_str); 571 } 572 573 #[test] test_from()574 fn test_from() { 575 let g = ArgGroup::with_name("test") 576 .arg("a1") 577 .arg("a4") 578 .args(&["a2", "a3"]) 579 .required(true) 580 .conflicts_with("c1") 581 .conflicts_with_all(&["c2", "c3"]) 582 .conflicts_with("c4") 583 .requires("r1") 584 .requires_all(&["r2", "r3"]) 585 .requires("r4"); 586 587 let args = vec!["a1", "a4", "a2", "a3"]; 588 let reqs = vec!["r1", "r2", "r3", "r4"]; 589 let confs = vec!["c1", "c2", "c3", "c4"]; 590 591 let g2 = ArgGroup::from(&g); 592 assert_eq!(g2.args, args); 593 assert_eq!(g2.requires, Some(reqs)); 594 assert_eq!(g2.conflicts, Some(confs)); 595 } 596 597 #[cfg(feature = "yaml")] 598 #[cfg_attr(feature = "yaml", test)] test_yaml()599 fn test_yaml() { 600 let g_yaml = "name: test 601 args: 602 - a1 603 - a4 604 - a2 605 - a3 606 conflicts_with: 607 - c1 608 - c2 609 - c3 610 - c4 611 requires: 612 - r1 613 - r2 614 - r3 615 - r4"; 616 let yml = &YamlLoader::load_from_str(g_yaml).expect("failed to load YAML file")[0]; 617 let g = ArgGroup::from_yaml(yml); 618 let args = vec!["a1", "a4", "a2", "a3"]; 619 let reqs = vec!["r1", "r2", "r3", "r4"]; 620 let confs = vec!["c1", "c2", "c3", "c4"]; 621 assert_eq!(g.args, args); 622 assert_eq!(g.requires, Some(reqs)); 623 assert_eq!(g.conflicts, Some(confs)); 624 } 625 } 626 627 impl<'a> Clone for ArgGroup<'a> { clone(&self) -> Self628 fn clone(&self) -> Self { 629 ArgGroup { 630 name: self.name, 631 required: self.required, 632 args: self.args.clone(), 633 requires: self.requires.clone(), 634 conflicts: self.conflicts.clone(), 635 multiple: self.multiple, 636 } 637 } 638 } 639