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