1 // Std
2 #[cfg(not(any(target_os = "windows", target_arch = "wasm32")))]
3 use std::os::unix::ffi::OsStrExt;
4 use std::{
5     cell::Cell,
6     ffi::{OsStr, OsString},
7     fmt::Display,
8     fs::File,
9     io::{self, BufWriter, Write},
10     iter::Peekable,
11     path::PathBuf,
12     slice::Iter,
13 };
14 
15 // Internal
16 #[cfg(all(feature = "debug", any(target_os = "windows", target_arch = "wasm32")))]
17 use crate::osstringext::OsStrExt3;
18 #[cfg(any(target_os = "windows", target_arch = "wasm32"))]
19 use crate::osstringext::OsStrExt3;
20 use crate::{
21     app::{
22         help::Help, meta::AppMeta, settings::AppFlags, settings::AppSettings as AS, usage,
23         validator::Validator, App,
24     },
25     args::{
26         settings::ArgSettings, AnyArg, Arg, ArgGroup, ArgMatcher, Base, FlagBuilder, OptBuilder,
27         PosBuilder, Switched,
28     },
29     completions::{ComplGen, Shell},
30     errors::Result as ClapResult,
31     errors::{Error, ErrorKind},
32     fmt::ColorWhen,
33     map::{self, VecMap},
34     osstringext::OsStrExt2,
35     suggestions, SubCommand, INTERNAL_ERROR_MSG, INVALID_UTF8,
36 };
37 
38 #[derive(Debug, PartialEq, Copy, Clone)]
39 #[doc(hidden)]
40 pub enum ParseResult<'a> {
41     Flag,
42     Opt(&'a str),
43     Pos(&'a str),
44     MaybeHyphenValue,
45     MaybeNegNum,
46     NotFound,
47     ValuesDone,
48 }
49 
50 #[allow(missing_debug_implementations)]
51 #[doc(hidden)]
52 #[derive(Clone, Default)]
53 pub struct Parser<'a, 'b>
54 where
55     'a: 'b,
56 {
57     pub meta: AppMeta<'b>,
58     settings: AppFlags,
59     pub g_settings: AppFlags,
60     pub flags: Vec<FlagBuilder<'a, 'b>>,
61     pub opts: Vec<OptBuilder<'a, 'b>>,
62     pub positionals: VecMap<PosBuilder<'a, 'b>>,
63     pub subcommands: Vec<App<'a, 'b>>,
64     pub groups: Vec<ArgGroup<'a>>,
65     pub global_args: Vec<Arg<'a, 'b>>,
66     pub required: Vec<&'a str>,
67     pub r_ifs: Vec<(&'a str, &'b str, &'a str)>,
68     pub overrides: Vec<(&'b str, &'a str)>,
69     help_short: Option<char>,
70     version_short: Option<char>,
71     cache: Option<&'a str>,
72     pub help_message: Option<&'a str>,
73     pub version_message: Option<&'a str>,
74     cur_idx: Cell<usize>,
75 }
76 
77 impl<'a, 'b> Parser<'a, 'b>
78 where
79     'a: 'b,
80 {
with_name(n: String) -> Self81     pub fn with_name(n: String) -> Self {
82         Parser {
83             meta: AppMeta::with_name(n),
84             g_settings: AppFlags::zeroed(),
85             cur_idx: Cell::new(0),
86             ..Default::default()
87         }
88     }
89 
help_short(&mut self, s: &str)90     pub fn help_short(&mut self, s: &str) {
91         let c = s
92             .trim_left_matches(|c| c == '-')
93             .chars()
94             .next()
95             .unwrap_or('h');
96         self.help_short = Some(c);
97     }
98 
version_short(&mut self, s: &str)99     pub fn version_short(&mut self, s: &str) {
100         let c = s
101             .trim_left_matches(|c| c == '-')
102             .chars()
103             .next()
104             .unwrap_or('V');
105         self.version_short = Some(c);
106     }
107 
gen_completions_to<W: Write>(&mut self, for_shell: Shell, buf: &mut W)108     pub fn gen_completions_to<W: Write>(&mut self, for_shell: Shell, buf: &mut W) {
109         if !self.is_set(AS::Propagated) {
110             self.propagate_help_version();
111             self.build_bin_names();
112             self.propagate_globals();
113             self.propagate_settings();
114             self.set(AS::Propagated);
115         }
116 
117         ComplGen::new(self).generate(for_shell, buf)
118     }
119 
gen_completions(&mut self, for_shell: Shell, od: OsString)120     pub fn gen_completions(&mut self, for_shell: Shell, od: OsString) {
121         use std::error::Error;
122 
123         let out_dir = PathBuf::from(od);
124         let name = &*self.meta.bin_name.as_ref().unwrap().clone();
125         let file_name = match for_shell {
126             Shell::Bash => format!("{}.bash", name),
127             Shell::Fish => format!("{}.fish", name),
128             Shell::Zsh => format!("_{}", name),
129             Shell::PowerShell => format!("_{}.ps1", name),
130             Shell::Elvish => format!("{}.elv", name),
131         };
132 
133         let mut file = match File::create(out_dir.join(file_name)) {
134             Err(why) => panic!("couldn't create completion file: {}", why.description()),
135             Ok(file) => file,
136         };
137         self.gen_completions_to(for_shell, &mut file)
138     }
139 
140     #[inline]
app_debug_asserts(&self) -> bool141     fn app_debug_asserts(&self) -> bool {
142         assert!(self.verify_positionals());
143         let should_err = self.groups.iter().all(|g| {
144             g.args.iter().all(|arg| {
145                 self.flags.iter().any(|f| &f.b.name == arg)
146                     || self.opts.iter().any(|o| &o.b.name == arg)
147                     || self.positionals.values().any(|p| &p.b.name == arg)
148                     || self.groups.iter().any(|g| &g.name == arg)
149             })
150         });
151         let g = self.groups.iter().find(|g| {
152             g.args.iter().any(|arg| {
153                 !(self.flags.iter().any(|f| &f.b.name == arg)
154                     || self.opts.iter().any(|o| &o.b.name == arg)
155                     || self.positionals.values().any(|p| &p.b.name == arg)
156                     || self.groups.iter().any(|g| &g.name == arg))
157             })
158         });
159         assert!(
160             should_err,
161             "The group '{}' contains the arg '{}' that doesn't actually exist.",
162             g.unwrap().name,
163             g.unwrap()
164                 .args
165                 .iter()
166                 .find(|arg| !(self.flags.iter().any(|f| &&f.b.name == arg)
167                     || self.opts.iter().any(|o| &&o.b.name == arg)
168                     || self.positionals.values().any(|p| &&p.b.name == arg)
169                     || self.groups.iter().any(|g| &&g.name == arg)))
170                 .unwrap()
171         );
172         true
173     }
174 
175     #[inline]
debug_asserts(&self, a: &Arg) -> bool176     fn debug_asserts(&self, a: &Arg) -> bool {
177         assert!(
178             !arg_names!(self).any(|name| name == a.b.name),
179             "Non-unique argument name: {} is already in use",
180             a.b.name
181         );
182         if let Some(l) = a.s.long {
183             assert!(
184                 !self.contains_long(l),
185                 "Argument long must be unique\n\n\t--{} is already in use",
186                 l
187             );
188         }
189         if let Some(s) = a.s.short {
190             assert!(
191                 !self.contains_short(s),
192                 "Argument short must be unique\n\n\t-{} is already in use",
193                 s
194             );
195         }
196         let i = if a.index.is_none() {
197             self.positionals.len() + 1
198         } else {
199             a.index.unwrap() as usize
200         };
201         assert!(
202             !self.positionals.contains_key(i),
203             "Argument \"{}\" has the same index as another positional \
204              argument\n\n\tPerhaps try .multiple(true) to allow one positional argument \
205              to take multiple values",
206             a.b.name
207         );
208         assert!(
209             !(a.is_set(ArgSettings::Required) && a.is_set(ArgSettings::Global)),
210             "Global arguments cannot be required.\n\n\t'{}' is marked as \
211              global and required",
212             a.b.name
213         );
214         if a.b.is_set(ArgSettings::Last) {
215             assert!(
216                 !self
217                     .positionals
218                     .values()
219                     .any(|p| p.b.is_set(ArgSettings::Last)),
220                 "Only one positional argument may have last(true) set. Found two."
221             );
222             assert!(a.s.long.is_none(),
223                     "Flags or Options may not have last(true) set. {} has both a long and last(true) set.",
224                     a.b.name);
225             assert!(a.s.short.is_none(),
226                     "Flags or Options may not have last(true) set. {} has both a short and last(true) set.",
227                     a.b.name);
228         }
229         true
230     }
231 
232     #[inline]
add_conditional_reqs(&mut self, a: &Arg<'a, 'b>)233     fn add_conditional_reqs(&mut self, a: &Arg<'a, 'b>) {
234         if let Some(ref r_ifs) = a.r_ifs {
235             for &(arg, val) in r_ifs {
236                 self.r_ifs.push((arg, val, a.b.name));
237             }
238         }
239     }
240 
241     #[inline]
add_arg_groups(&mut self, a: &Arg<'a, 'b>)242     fn add_arg_groups(&mut self, a: &Arg<'a, 'b>) {
243         if let Some(ref grps) = a.b.groups {
244             for g in grps {
245                 let mut found = false;
246                 if let Some(ref mut ag) = self.groups.iter_mut().find(|grp| &grp.name == g) {
247                     ag.args.push(a.b.name);
248                     found = true;
249                 }
250                 if !found {
251                     let mut ag = ArgGroup::with_name(g);
252                     ag.args.push(a.b.name);
253                     self.groups.push(ag);
254                 }
255             }
256         }
257     }
258 
259     #[inline]
add_reqs(&mut self, a: &Arg<'a, 'b>)260     fn add_reqs(&mut self, a: &Arg<'a, 'b>) {
261         if a.is_set(ArgSettings::Required) {
262             // If the arg is required, add all it's requirements to master required list
263             self.required.push(a.b.name);
264             if let Some(ref areqs) = a.b.requires {
265                 for name in areqs
266                     .iter()
267                     .filter(|&&(val, _)| val.is_none())
268                     .map(|&(_, name)| name)
269                 {
270                     self.required.push(name);
271                 }
272             }
273         }
274     }
275 
276     #[inline]
implied_settings(&mut self, a: &Arg<'a, 'b>)277     fn implied_settings(&mut self, a: &Arg<'a, 'b>) {
278         if a.is_set(ArgSettings::Last) {
279             // if an arg has `Last` set, we need to imply DontCollapseArgsInUsage so that args
280             // in the usage string don't get confused or left out.
281             self.set(AS::DontCollapseArgsInUsage);
282             self.set(AS::ContainsLast);
283         }
284         if let Some(l) = a.s.long {
285             if l == "version" {
286                 self.unset(AS::NeedsLongVersion);
287             } else if l == "help" {
288                 self.unset(AS::NeedsLongHelp);
289             }
290         }
291     }
292 
293     // actually adds the arguments
add_arg(&mut self, a: Arg<'a, 'b>)294     pub fn add_arg(&mut self, a: Arg<'a, 'b>) {
295         // if it's global we have to clone anyways
296         if a.is_set(ArgSettings::Global) {
297             return self.add_arg_ref(&a);
298         }
299         debug_assert!(self.debug_asserts(&a));
300         self.add_conditional_reqs(&a);
301         self.add_arg_groups(&a);
302         self.add_reqs(&a);
303         self.implied_settings(&a);
304         if a.index.is_some() || (a.s.short.is_none() && a.s.long.is_none()) {
305             let i = if a.index.is_none() {
306                 self.positionals.len() + 1
307             } else {
308                 a.index.unwrap() as usize
309             };
310             self.positionals
311                 .insert(i, PosBuilder::from_arg(a, i as u64));
312         } else if a.is_set(ArgSettings::TakesValue) {
313             let mut ob = OptBuilder::from(a);
314             ob.s.unified_ord = self.flags.len() + self.opts.len();
315             self.opts.push(ob);
316         } else {
317             let mut fb = FlagBuilder::from(a);
318             fb.s.unified_ord = self.flags.len() + self.opts.len();
319             self.flags.push(fb);
320         }
321     }
322     // actually adds the arguments but from a borrow (which means we have to do some cloning)
add_arg_ref(&mut self, a: &Arg<'a, 'b>)323     pub fn add_arg_ref(&mut self, a: &Arg<'a, 'b>) {
324         debug_assert!(self.debug_asserts(a));
325         self.add_conditional_reqs(a);
326         self.add_arg_groups(a);
327         self.add_reqs(a);
328         self.implied_settings(a);
329         if a.index.is_some() || (a.s.short.is_none() && a.s.long.is_none()) {
330             let i = if a.index.is_none() {
331                 self.positionals.len() + 1
332             } else {
333                 a.index.unwrap() as usize
334             };
335             let pb = PosBuilder::from_arg_ref(a, i as u64);
336             self.positionals.insert(i, pb);
337         } else if a.is_set(ArgSettings::TakesValue) {
338             let mut ob = OptBuilder::from(a);
339             ob.s.unified_ord = self.flags.len() + self.opts.len();
340             self.opts.push(ob);
341         } else {
342             let mut fb = FlagBuilder::from(a);
343             fb.s.unified_ord = self.flags.len() + self.opts.len();
344             self.flags.push(fb);
345         }
346         if a.is_set(ArgSettings::Global) {
347             self.global_args.push(a.into());
348         }
349     }
350 
add_group(&mut self, group: ArgGroup<'a>)351     pub fn add_group(&mut self, group: ArgGroup<'a>) {
352         if group.required {
353             self.required.push(group.name);
354             if let Some(ref reqs) = group.requires {
355                 self.required.extend_from_slice(reqs);
356             }
357             //            if let Some(ref bl) = group.conflicts {
358             //                self.blacklist.extend_from_slice(bl);
359             //            }
360         }
361         if self.groups.iter().any(|g| g.name == group.name) {
362             let grp = self
363                 .groups
364                 .iter_mut()
365                 .find(|g| g.name == group.name)
366                 .expect(INTERNAL_ERROR_MSG);
367             grp.args.extend_from_slice(&group.args);
368             grp.requires = group.requires.clone();
369             grp.conflicts = group.conflicts.clone();
370             grp.required = group.required;
371         } else {
372             self.groups.push(group);
373         }
374     }
375 
add_subcommand(&mut self, mut subcmd: App<'a, 'b>)376     pub fn add_subcommand(&mut self, mut subcmd: App<'a, 'b>) {
377         debugln!(
378             "Parser::add_subcommand: term_w={:?}, name={}",
379             self.meta.term_w,
380             subcmd.p.meta.name
381         );
382         subcmd.p.meta.term_w = self.meta.term_w;
383         if subcmd.p.meta.name == "help" {
384             self.unset(AS::NeedsSubcommandHelp);
385         }
386 
387         self.subcommands.push(subcmd);
388     }
389 
propagate_settings(&mut self)390     pub fn propagate_settings(&mut self) {
391         debugln!(
392             "Parser::propagate_settings: self={}, g_settings={:#?}",
393             self.meta.name,
394             self.g_settings
395         );
396         for sc in &mut self.subcommands {
397             debugln!(
398                 "Parser::propagate_settings: sc={}, settings={:#?}, g_settings={:#?}",
399                 sc.p.meta.name,
400                 sc.p.settings,
401                 sc.p.g_settings
402             );
403             // We have to create a new scope in order to tell rustc the borrow of `sc` is
404             // done and to recursively call this method
405             {
406                 let vsc = self.settings.is_set(AS::VersionlessSubcommands);
407                 let gv = self.settings.is_set(AS::GlobalVersion);
408 
409                 if vsc {
410                     sc.p.set(AS::DisableVersion);
411                 }
412                 if gv && sc.p.meta.version.is_none() && self.meta.version.is_some() {
413                     sc.p.set(AS::GlobalVersion);
414                     sc.p.meta.version = Some(self.meta.version.unwrap());
415                 }
416                 sc.p.settings = sc.p.settings | self.g_settings;
417                 sc.p.g_settings = sc.p.g_settings | self.g_settings;
418                 sc.p.meta.term_w = self.meta.term_w;
419                 sc.p.meta.max_w = self.meta.max_w;
420             }
421             sc.p.propagate_settings();
422         }
423     }
424 
derive_display_order(&mut self)425     pub fn derive_display_order(&mut self) {
426         if self.is_set(AS::DeriveDisplayOrder) {
427             let unified = self.is_set(AS::UnifiedHelpMessage);
428             for (i, o) in self
429                 .opts
430                 .iter_mut()
431                 .enumerate()
432                 .filter(|&(_, ref o)| o.s.disp_ord == 999)
433             {
434                 o.s.disp_ord = if unified { o.s.unified_ord } else { i };
435             }
436             for (i, f) in self
437                 .flags
438                 .iter_mut()
439                 .enumerate()
440                 .filter(|&(_, ref f)| f.s.disp_ord == 999)
441             {
442                 f.s.disp_ord = if unified { f.s.unified_ord } else { i };
443             }
444             for (i, sc) in &mut self
445                 .subcommands
446                 .iter_mut()
447                 .enumerate()
448                 .filter(|&(_, ref sc)| sc.p.meta.disp_ord == 999)
449             {
450                 sc.p.meta.disp_ord = i;
451             }
452         }
453         for sc in &mut self.subcommands {
454             sc.p.derive_display_order();
455         }
456     }
457 
required(&self) -> Iter<&str>458     pub fn required(&self) -> Iter<&str> {
459         self.required.iter()
460     }
461 
462     #[inline]
has_args(&self) -> bool463     pub fn has_args(&self) -> bool {
464         !(self.flags.is_empty() && self.opts.is_empty() && self.positionals.is_empty())
465     }
466 
467     #[inline]
has_opts(&self) -> bool468     pub fn has_opts(&self) -> bool {
469         !self.opts.is_empty()
470     }
471 
472     #[inline]
has_flags(&self) -> bool473     pub fn has_flags(&self) -> bool {
474         !self.flags.is_empty()
475     }
476 
477     #[inline]
has_positionals(&self) -> bool478     pub fn has_positionals(&self) -> bool {
479         !self.positionals.is_empty()
480     }
481 
482     #[inline]
has_subcommands(&self) -> bool483     pub fn has_subcommands(&self) -> bool {
484         !self.subcommands.is_empty()
485     }
486 
487     #[inline]
has_visible_opts(&self) -> bool488     pub fn has_visible_opts(&self) -> bool {
489         if self.opts.is_empty() {
490             return false;
491         }
492         self.opts.iter().any(|o| !o.is_set(ArgSettings::Hidden))
493     }
494 
495     #[inline]
has_visible_flags(&self) -> bool496     pub fn has_visible_flags(&self) -> bool {
497         if self.flags.is_empty() {
498             return false;
499         }
500         self.flags.iter().any(|f| !f.is_set(ArgSettings::Hidden))
501     }
502 
503     #[inline]
has_visible_positionals(&self) -> bool504     pub fn has_visible_positionals(&self) -> bool {
505         if self.positionals.is_empty() {
506             return false;
507         }
508         self.positionals
509             .values()
510             .any(|p| !p.is_set(ArgSettings::Hidden))
511     }
512 
513     #[inline]
has_visible_subcommands(&self) -> bool514     pub fn has_visible_subcommands(&self) -> bool {
515         self.has_subcommands()
516             && self
517                 .subcommands
518                 .iter()
519                 .filter(|sc| sc.p.meta.name != "help")
520                 .any(|sc| !sc.p.is_set(AS::Hidden))
521     }
522 
523     #[inline]
is_set(&self, s: AS) -> bool524     pub fn is_set(&self, s: AS) -> bool {
525         self.settings.is_set(s)
526     }
527 
528     #[inline]
set(&mut self, s: AS)529     pub fn set(&mut self, s: AS) {
530         self.settings.set(s)
531     }
532 
533     #[inline]
unset(&mut self, s: AS)534     pub fn unset(&mut self, s: AS) {
535         self.settings.unset(s)
536     }
537 
verify_positionals(&self) -> bool538     pub fn verify_positionals(&self) -> bool {
539         // Because you must wait until all arguments have been supplied, this is the first chance
540         // to make assertions on positional argument indexes
541         //
542         // First we verify that the index highest supplied index, is equal to the number of
543         // positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3
544         // but no 2)
545         if let Some((idx, p)) = self.positionals.iter().rev().next() {
546             assert!(
547                 !(idx != self.positionals.len()),
548                 "Found positional argument \"{}\" whose index is {} but there \
549                  are only {} positional arguments defined",
550                 p.b.name,
551                 idx,
552                 self.positionals.len()
553             );
554         }
555 
556         // Next we verify that only the highest index has a .multiple(true) (if any)
557         if self.positionals.values().any(|a| {
558             a.b.is_set(ArgSettings::Multiple) && (a.index as usize != self.positionals.len())
559         }) {
560             let mut it = self.positionals.values().rev();
561             let last = it.next().unwrap();
562             let second_to_last = it.next().unwrap();
563             // Either the final positional is required
564             // Or the second to last has a terminator or .last(true) set
565             let ok = last.is_set(ArgSettings::Required)
566                 || (second_to_last.v.terminator.is_some()
567                     || second_to_last.b.is_set(ArgSettings::Last))
568                 || last.is_set(ArgSettings::Last);
569             assert!(
570                 ok,
571                 "When using a positional argument with .multiple(true) that is *not the \
572                  last* positional argument, the last positional argument (i.e the one \
573                  with the highest index) *must* have .required(true) or .last(true) set."
574             );
575             let ok = second_to_last.is_set(ArgSettings::Multiple) || last.is_set(ArgSettings::Last);
576             assert!(
577                 ok,
578                 "Only the last positional argument, or second to last positional \
579                  argument may be set to .multiple(true)"
580             );
581 
582             let count = self
583                 .positionals
584                 .values()
585                 .filter(|p| p.b.settings.is_set(ArgSettings::Multiple) && p.v.num_vals.is_none())
586                 .count();
587             let ok = count <= 1
588                 || (last.is_set(ArgSettings::Last)
589                     && last.is_set(ArgSettings::Multiple)
590                     && second_to_last.is_set(ArgSettings::Multiple)
591                     && count == 2);
592             assert!(
593                 ok,
594                 "Only one positional argument with .multiple(true) set is allowed per \
595                  command, unless the second one also has .last(true) set"
596             );
597         }
598 
599         let mut found = false;
600         if self.is_set(AS::AllowMissingPositional) {
601             // Check that if a required positional argument is found, all positions with a lower
602             // index are also required.
603             let mut foundx2 = false;
604             for p in self.positionals.values().rev() {
605                 if foundx2 && !p.b.settings.is_set(ArgSettings::Required) {
606                     assert!(
607                         p.b.is_set(ArgSettings::Required),
608                         "Found positional argument which is not required with a lower \
609                          index than a required positional argument by two or more: {:?} \
610                          index {}",
611                         p.b.name,
612                         p.index
613                     );
614                 } else if p.b.is_set(ArgSettings::Required) && !p.b.is_set(ArgSettings::Last) {
615                     // Args that .last(true) don't count since they can be required and have
616                     // positionals with a lower index that aren't required
617                     // Imagine: prog <req1> [opt1] -- <req2>
618                     // Both of these are valid invocations:
619                     //      $ prog r1 -- r2
620                     //      $ prog r1 o1 -- r2
621                     if found {
622                         foundx2 = true;
623                         continue;
624                     }
625                     found = true;
626                     continue;
627                 } else {
628                     found = false;
629                 }
630             }
631         } else {
632             // Check that if a required positional argument is found, all positions with a lower
633             // index are also required
634             for p in self.positionals.values().rev() {
635                 if found {
636                     assert!(
637                         p.b.is_set(ArgSettings::Required),
638                         "Found positional argument which is not required with a lower \
639                          index than a required positional argument: {:?} index {}",
640                         p.b.name,
641                         p.index
642                     );
643                 } else if p.b.is_set(ArgSettings::Required) && !p.b.is_set(ArgSettings::Last) {
644                     // Args that .last(true) don't count since they can be required and have
645                     // positionals with a lower index that aren't required
646                     // Imagine: prog <req1> [opt1] -- <req2>
647                     // Both of these are valid invocations:
648                     //      $ prog r1 -- r2
649                     //      $ prog r1 o1 -- r2
650                     found = true;
651                     continue;
652                 }
653             }
654         }
655         if self
656             .positionals
657             .values()
658             .any(|p| p.b.is_set(ArgSettings::Last) && p.b.is_set(ArgSettings::Required))
659             && self.has_subcommands()
660             && !self.is_set(AS::SubcommandsNegateReqs)
661         {
662             panic!(
663                 "Having a required positional argument with .last(true) set *and* child \
664                  subcommands without setting SubcommandsNegateReqs isn't compatible."
665             );
666         }
667 
668         true
669     }
670 
propagate_globals(&mut self)671     pub fn propagate_globals(&mut self) {
672         for sc in &mut self.subcommands {
673             // We have to create a new scope in order to tell rustc the borrow of `sc` is
674             // done and to recursively call this method
675             {
676                 for a in &self.global_args {
677                     sc.p.add_arg_ref(a);
678                 }
679             }
680             sc.p.propagate_globals();
681         }
682     }
683 
684     // Checks if the arg matches a subcommand name, or any of it's aliases (if defined)
possible_subcommand(&self, arg_os: &OsStr) -> (bool, Option<&str>)685     fn possible_subcommand(&self, arg_os: &OsStr) -> (bool, Option<&str>) {
686         debugln!("Parser::possible_subcommand: arg={:?}", arg_os);
687         fn starts(h: &str, n: &OsStr) -> bool {
688             let n_bytes = n.as_bytes();
689             let h_bytes = OsStr::new(h).as_bytes();
690 
691             h_bytes.starts_with(n_bytes)
692         }
693 
694         if self.is_set(AS::ArgsNegateSubcommands) && self.is_set(AS::ValidArgFound) {
695             return (false, None);
696         }
697         if !self.is_set(AS::InferSubcommands) {
698             if let Some(sc) = find_subcmd!(self, arg_os) {
699                 return (true, Some(&sc.p.meta.name));
700             }
701         } else {
702             let v = self
703                 .subcommands
704                 .iter()
705                 .filter(|s| {
706                     starts(&s.p.meta.name[..], &*arg_os)
707                         || (s.p.meta.aliases.is_some()
708                             && s.p
709                                 .meta
710                                 .aliases
711                                 .as_ref()
712                                 .unwrap()
713                                 .iter()
714                                 .filter(|&&(a, _)| starts(a, &*arg_os))
715                                 .count()
716                                 == 1)
717                 })
718                 .map(|sc| &sc.p.meta.name)
719                 .collect::<Vec<_>>();
720 
721             for sc in &v {
722                 if OsStr::new(sc) == arg_os {
723                     return (true, Some(sc));
724                 }
725             }
726 
727             if v.len() == 1 {
728                 return (true, Some(v[0]));
729             }
730         }
731         (false, None)
732     }
733 
parse_help_subcommand<I, T>(&self, it: &mut I) -> ClapResult<ParseResult<'a>> where I: Iterator<Item = T>, T: Into<OsString>,734     fn parse_help_subcommand<I, T>(&self, it: &mut I) -> ClapResult<ParseResult<'a>>
735     where
736         I: Iterator<Item = T>,
737         T: Into<OsString>,
738     {
739         debugln!("Parser::parse_help_subcommand;");
740         let cmds: Vec<OsString> = it.map(|c| c.into()).collect();
741         let mut help_help = false;
742         let mut bin_name = self
743             .meta
744             .bin_name
745             .as_ref()
746             .unwrap_or(&self.meta.name)
747             .clone();
748         let mut sc = {
749             let mut sc: &Parser = self;
750             for (i, cmd) in cmds.iter().enumerate() {
751                 if &*cmd.to_string_lossy() == "help" {
752                     // cmd help help
753                     help_help = true;
754                 }
755                 if let Some(c) = sc
756                     .subcommands
757                     .iter()
758                     .find(|s| &*s.p.meta.name == cmd)
759                     .map(|sc| &sc.p)
760                 {
761                     sc = c;
762                     if i == cmds.len() - 1 {
763                         break;
764                     }
765                 } else if let Some(c) = sc
766                     .subcommands
767                     .iter()
768                     .find(|s| {
769                         if let Some(ref als) = s.p.meta.aliases {
770                             als.iter().any(|&(a, _)| a == &*cmd.to_string_lossy())
771                         } else {
772                             false
773                         }
774                     })
775                     .map(|sc| &sc.p)
776                 {
777                     sc = c;
778                     if i == cmds.len() - 1 {
779                         break;
780                     }
781                 } else {
782                     return Err(Error::unrecognized_subcommand(
783                         cmd.to_string_lossy().into_owned(),
784                         self.meta.bin_name.as_ref().unwrap_or(&self.meta.name),
785                         self.color(),
786                     ));
787                 }
788                 bin_name = format!("{} {}", bin_name, &*sc.meta.name);
789             }
790             sc.clone()
791         };
792         if help_help {
793             let mut pb = PosBuilder::new("subcommand", 1);
794             pb.b.help = Some("The subcommand whose help message to display");
795             pb.set(ArgSettings::Multiple);
796             sc.positionals.insert(1, pb);
797             sc.settings = sc.settings | self.g_settings;
798         } else {
799             sc.create_help_and_version();
800         }
801         if sc.meta.bin_name != self.meta.bin_name {
802             sc.meta.bin_name = Some(format!("{} {}", bin_name, sc.meta.name));
803         }
804         Err(sc._help(false))
805     }
806 
807     // allow wrong self convention due to self.valid_neg_num = true and it's a private method
808     #[cfg_attr(feature = "lints", allow(wrong_self_convention))]
is_new_arg(&mut self, arg_os: &OsStr, needs_val_of: ParseResult) -> bool809     fn is_new_arg(&mut self, arg_os: &OsStr, needs_val_of: ParseResult) -> bool {
810         debugln!("Parser::is_new_arg:{:?}:{:?}", arg_os, needs_val_of);
811         let app_wide_settings = if self.is_set(AS::AllowLeadingHyphen) {
812             true
813         } else if self.is_set(AS::AllowNegativeNumbers) {
814             let a = arg_os.to_string_lossy();
815             if a.parse::<i64>().is_ok() || a.parse::<f64>().is_ok() {
816                 self.set(AS::ValidNegNumFound);
817                 true
818             } else {
819                 false
820             }
821         } else {
822             false
823         };
824         let arg_allows_tac = match needs_val_of {
825             ParseResult::Opt(name) => {
826                 let o = self
827                     .opts
828                     .iter()
829                     .find(|o| o.b.name == name)
830                     .expect(INTERNAL_ERROR_MSG);
831                 o.is_set(ArgSettings::AllowLeadingHyphen) || app_wide_settings
832             }
833             ParseResult::Pos(name) => {
834                 let p = self
835                     .positionals
836                     .values()
837                     .find(|p| p.b.name == name)
838                     .expect(INTERNAL_ERROR_MSG);
839                 p.is_set(ArgSettings::AllowLeadingHyphen) || app_wide_settings
840             }
841             ParseResult::ValuesDone => return true,
842             _ => false,
843         };
844         debugln!("Parser::is_new_arg: arg_allows_tac={:?}", arg_allows_tac);
845 
846         // Is this a new argument, or values from a previous option?
847         let mut ret = if arg_os.starts_with(b"--") {
848             debugln!("Parser::is_new_arg: -- found");
849             if arg_os.len() == 2 && !arg_allows_tac {
850                 return true; // We have to return true so override everything else
851             } else if arg_allows_tac {
852                 return false;
853             }
854             true
855         } else if arg_os.starts_with(b"-") {
856             debugln!("Parser::is_new_arg: - found");
857             // a singe '-' by itself is a value and typically means "stdin" on unix systems
858             arg_os.len() != 1
859         } else {
860             debugln!("Parser::is_new_arg: probably value");
861             false
862         };
863 
864         ret = ret && !arg_allows_tac;
865 
866         debugln!("Parser::is_new_arg: starts_new_arg={:?}", ret);
867         ret
868     }
869 
870     // The actual parsing function
871     #[cfg_attr(
872         feature = "cargo-clippy",
873         allow(clippy::while_let_on_iterator, clippy::nonminimal_bool)
874     )]
get_matches_with<I, T>( &mut self, matcher: &mut ArgMatcher<'a>, it: &mut Peekable<I>, ) -> ClapResult<()> where I: Iterator<Item = T>, T: Into<OsString> + Clone,875     pub fn get_matches_with<I, T>(
876         &mut self,
877         matcher: &mut ArgMatcher<'a>,
878         it: &mut Peekable<I>,
879     ) -> ClapResult<()>
880     where
881         I: Iterator<Item = T>,
882         T: Into<OsString> + Clone,
883     {
884         debugln!("Parser::get_matches_with;");
885         // Verify all positional assertions pass
886         debug_assert!(self.app_debug_asserts());
887         if self.positionals.values().any(|a| {
888             a.b.is_set(ArgSettings::Multiple) && (a.index as usize != self.positionals.len())
889         }) && self
890             .positionals
891             .values()
892             .last()
893             .map_or(false, |p| !p.is_set(ArgSettings::Last))
894         {
895             self.settings.set(AS::LowIndexMultiplePositional);
896         }
897         let has_args = self.has_args();
898 
899         // Next we create the `--help` and `--version` arguments and add them if
900         // necessary
901         self.create_help_and_version();
902 
903         let mut subcmd_name: Option<String> = None;
904         let mut needs_val_of: ParseResult<'a> = ParseResult::NotFound;
905         let mut pos_counter = 1;
906         let mut sc_is_external = false;
907         while let Some(arg) = it.next() {
908             let arg_os = arg.into();
909             debugln!(
910                 "Parser::get_matches_with: Begin parsing '{:?}' ({:?})",
911                 arg_os,
912                 &*arg_os.as_bytes()
913             );
914 
915             self.unset(AS::ValidNegNumFound);
916             // Is this a new argument, or values from a previous option?
917             let starts_new_arg = self.is_new_arg(&arg_os, needs_val_of);
918             if !self.is_set(AS::TrailingValues)
919                 && arg_os.starts_with(b"--")
920                 && arg_os.len() == 2
921                 && starts_new_arg
922             {
923                 debugln!("Parser::get_matches_with: setting TrailingVals=true");
924                 self.set(AS::TrailingValues);
925                 continue;
926             }
927 
928             // Has the user already passed '--'? Meaning only positional args follow
929             if !self.is_set(AS::TrailingValues) {
930                 // Does the arg match a subcommand name, or any of it's aliases (if defined)
931                 {
932                     match needs_val_of {
933                         ParseResult::Opt(_) | ParseResult::Pos(_) => (),
934                         _ => {
935                             let (is_match, sc_name) = self.possible_subcommand(&arg_os);
936                             debugln!(
937                                 "Parser::get_matches_with: possible_sc={:?}, sc={:?}",
938                                 is_match,
939                                 sc_name
940                             );
941                             if is_match {
942                                 let sc_name = sc_name.expect(INTERNAL_ERROR_MSG);
943                                 if sc_name == "help" && self.is_set(AS::NeedsSubcommandHelp) {
944                                     self.parse_help_subcommand(it)?;
945                                 }
946                                 subcmd_name = Some(sc_name.to_owned());
947                                 break;
948                             }
949                         }
950                     }
951                 }
952 
953                 if starts_new_arg {
954                     let check_all = self.is_set(AS::AllArgsOverrideSelf);
955                     {
956                         let any_arg = find_any_by_name!(self, self.cache.unwrap_or(""));
957                         matcher.process_arg_overrides(
958                             any_arg,
959                             &mut self.overrides,
960                             &mut self.required,
961                             check_all,
962                         );
963                     }
964 
965                     if arg_os.starts_with(b"--") {
966                         needs_val_of = self.parse_long_arg(matcher, &arg_os, it)?;
967                         debugln!(
968                             "Parser:get_matches_with: After parse_long_arg {:?}",
969                             needs_val_of
970                         );
971                         match needs_val_of {
972                             ParseResult::Flag | ParseResult::Opt(..) | ParseResult::ValuesDone => {
973                                 continue
974                             }
975                             _ => (),
976                         }
977                     } else if arg_os.starts_with(b"-") && arg_os.len() != 1 {
978                         // Try to parse short args like normal, if AllowLeadingHyphen or
979                         // AllowNegativeNumbers is set, parse_short_arg will *not* throw
980                         // an error, and instead return Ok(None)
981                         needs_val_of = self.parse_short_arg(matcher, &arg_os)?;
982                         // If it's None, we then check if one of those two AppSettings was set
983                         debugln!(
984                             "Parser:get_matches_with: After parse_short_arg {:?}",
985                             needs_val_of
986                         );
987                         match needs_val_of {
988                             ParseResult::MaybeNegNum => {
989                                 if !(arg_os.to_string_lossy().parse::<i64>().is_ok()
990                                     || arg_os.to_string_lossy().parse::<f64>().is_ok())
991                                 {
992                                     return Err(Error::unknown_argument(
993                                         &*arg_os.to_string_lossy(),
994                                         "",
995                                         &*usage::create_error_usage(self, matcher, None),
996                                         self.color(),
997                                     ));
998                                 }
999                             }
1000                             ParseResult::Opt(..) | ParseResult::Flag | ParseResult::ValuesDone => {
1001                                 continue
1002                             }
1003                             _ => (),
1004                         }
1005                     }
1006                 } else if let ParseResult::Opt(name) = needs_val_of {
1007                     // Check to see if parsing a value from a previous arg
1008                     let arg = self
1009                         .opts
1010                         .iter()
1011                         .find(|o| o.b.name == name)
1012                         .expect(INTERNAL_ERROR_MSG);
1013                     // get the OptBuilder so we can check the settings
1014                     needs_val_of = self.add_val_to_arg(arg, &arg_os, matcher)?;
1015                     // get the next value from the iterator
1016                     continue;
1017                 }
1018             }
1019 
1020             if !(self.is_set(AS::ArgsNegateSubcommands) && self.is_set(AS::ValidArgFound))
1021                 && !self.is_set(AS::InferSubcommands)
1022                 && !self.is_set(AS::AllowExternalSubcommands)
1023             {
1024                 if let Some(cdate) =
1025                     suggestions::did_you_mean(&*arg_os.to_string_lossy(), sc_names!(self))
1026                 {
1027                     return Err(Error::invalid_subcommand(
1028                         arg_os.to_string_lossy().into_owned(),
1029                         cdate,
1030                         self.meta.bin_name.as_ref().unwrap_or(&self.meta.name),
1031                         &*usage::create_error_usage(self, matcher, None),
1032                         self.color(),
1033                     ));
1034                 }
1035             }
1036 
1037             let low_index_mults = self.is_set(AS::LowIndexMultiplePositional)
1038                 && pos_counter == (self.positionals.len() - 1);
1039             let missing_pos = self.is_set(AS::AllowMissingPositional)
1040                 && (pos_counter == (self.positionals.len() - 1)
1041                     && !self.is_set(AS::TrailingValues));
1042             debugln!(
1043                 "Parser::get_matches_with: Positional counter...{}",
1044                 pos_counter
1045             );
1046             debugln!(
1047                 "Parser::get_matches_with: Low index multiples...{:?}",
1048                 low_index_mults
1049             );
1050             if low_index_mults || missing_pos {
1051                 if let Some(na) = it.peek() {
1052                     let n = (*na).clone().into();
1053                     needs_val_of = if needs_val_of != ParseResult::ValuesDone {
1054                         if let Some(p) = self.positionals.get(pos_counter) {
1055                             ParseResult::Pos(p.b.name)
1056                         } else {
1057                             ParseResult::ValuesDone
1058                         }
1059                     } else {
1060                         ParseResult::ValuesDone
1061                     };
1062                     let sc_match = { self.possible_subcommand(&n).0 };
1063                     if self.is_new_arg(&n, needs_val_of)
1064                         || sc_match
1065                         || suggestions::did_you_mean(&n.to_string_lossy(), sc_names!(self))
1066                             .is_some()
1067                     {
1068                         debugln!("Parser::get_matches_with: Bumping the positional counter...");
1069                         pos_counter += 1;
1070                     }
1071                 } else {
1072                     debugln!("Parser::get_matches_with: Bumping the positional counter...");
1073                     pos_counter += 1;
1074                 }
1075             } else if (self.is_set(AS::AllowMissingPositional) && self.is_set(AS::TrailingValues))
1076                 || (self.is_set(AS::ContainsLast) && self.is_set(AS::TrailingValues))
1077             {
1078                 // Came to -- and one postional has .last(true) set, so we go immediately
1079                 // to the last (highest index) positional
1080                 debugln!("Parser::get_matches_with: .last(true) and --, setting last pos");
1081                 pos_counter = self.positionals.len();
1082             }
1083             if let Some(p) = self.positionals.get(pos_counter) {
1084                 if p.is_set(ArgSettings::Last) && !self.is_set(AS::TrailingValues) {
1085                     return Err(Error::unknown_argument(
1086                         &*arg_os.to_string_lossy(),
1087                         "",
1088                         &*usage::create_error_usage(self, matcher, None),
1089                         self.color(),
1090                     ));
1091                 }
1092                 if !self.is_set(AS::TrailingValues)
1093                     && (self.is_set(AS::TrailingVarArg) && pos_counter == self.positionals.len())
1094                 {
1095                     self.settings.set(AS::TrailingValues);
1096                 }
1097                 if self.cache.map_or(true, |name| name != p.b.name) {
1098                     let check_all = self.is_set(AS::AllArgsOverrideSelf);
1099                     {
1100                         let any_arg = find_any_by_name!(self, self.cache.unwrap_or(""));
1101                         matcher.process_arg_overrides(
1102                             any_arg,
1103                             &mut self.overrides,
1104                             &mut self.required,
1105                             check_all,
1106                         );
1107                     }
1108                     self.cache = Some(p.b.name);
1109                 }
1110                 let _ = self.add_val_to_arg(p, &arg_os, matcher)?;
1111 
1112                 matcher.inc_occurrence_of(p.b.name);
1113                 let _ = self
1114                     .groups_for_arg(p.b.name)
1115                     .map(|vec| matcher.inc_occurrences_of(&*vec));
1116 
1117                 self.settings.set(AS::ValidArgFound);
1118                 // Only increment the positional counter if it doesn't allow multiples
1119                 if !p.b.settings.is_set(ArgSettings::Multiple) {
1120                     pos_counter += 1;
1121                 }
1122                 self.settings.set(AS::ValidArgFound);
1123             } else if self.is_set(AS::AllowExternalSubcommands) {
1124                 // Get external subcommand name
1125                 let sc_name = match arg_os.to_str() {
1126                     Some(s) => s.to_string(),
1127                     None => {
1128                         if !self.is_set(AS::StrictUtf8) {
1129                             return Err(Error::invalid_utf8(
1130                                 &*usage::create_error_usage(self, matcher, None),
1131                                 self.color(),
1132                             ));
1133                         }
1134                         arg_os.to_string_lossy().into_owned()
1135                     }
1136                 };
1137 
1138                 // Collect the external subcommand args
1139                 let mut sc_m = ArgMatcher::new();
1140                 // Due to borrow rules, this has to be a while let...
1141                 #[cfg_attr(feature = "cargo-clippy", allow(clippy::while_let_on_iterator))]
1142                 while let Some(v) = it.next() {
1143                     let a = v.into();
1144                     if a.to_str().is_none() && !self.is_set(AS::StrictUtf8) {
1145                         return Err(Error::invalid_utf8(
1146                             &*usage::create_error_usage(self, matcher, None),
1147                             self.color(),
1148                         ));
1149                     }
1150                     sc_m.add_val_to("", &a);
1151                 }
1152 
1153                 matcher.subcommand(SubCommand {
1154                     name: sc_name,
1155                     matches: sc_m.into(),
1156                 });
1157                 sc_is_external = true;
1158             } else if !((self.is_set(AS::AllowLeadingHyphen)
1159                 || self.is_set(AS::AllowNegativeNumbers))
1160                 && arg_os.starts_with(b"-"))
1161                 && !self.is_set(AS::InferSubcommands)
1162             {
1163                 return Err(Error::unknown_argument(
1164                     &*arg_os.to_string_lossy(),
1165                     "",
1166                     &*usage::create_error_usage(self, matcher, None),
1167                     self.color(),
1168                 ));
1169             } else if !has_args || self.is_set(AS::InferSubcommands) && self.has_subcommands() {
1170                 if let Some(cdate) =
1171                     suggestions::did_you_mean(&*arg_os.to_string_lossy(), sc_names!(self))
1172                 {
1173                     return Err(Error::invalid_subcommand(
1174                         arg_os.to_string_lossy().into_owned(),
1175                         cdate,
1176                         self.meta.bin_name.as_ref().unwrap_or(&self.meta.name),
1177                         &*usage::create_error_usage(self, matcher, None),
1178                         self.color(),
1179                     ));
1180                 } else {
1181                     return Err(Error::unrecognized_subcommand(
1182                         arg_os.to_string_lossy().into_owned(),
1183                         self.meta.bin_name.as_ref().unwrap_or(&self.meta.name),
1184                         self.color(),
1185                     ));
1186                 }
1187             } else {
1188                 return Err(Error::unknown_argument(
1189                     &*arg_os.to_string_lossy(),
1190                     "",
1191                     &*usage::create_error_usage(self, matcher, None),
1192                     self.color(),
1193                 ));
1194             }
1195         }
1196 
1197         if !sc_is_external {
1198             if let Some(ref pos_sc_name) = subcmd_name {
1199                 let sc_name = {
1200                     find_subcmd!(self, pos_sc_name)
1201                         .expect(INTERNAL_ERROR_MSG)
1202                         .p
1203                         .meta
1204                         .name
1205                         .clone()
1206                 };
1207                 self.parse_subcommand(&*sc_name, matcher, it)?;
1208             } else if self.is_set(AS::SubcommandRequired) {
1209                 let bn = self.meta.bin_name.as_ref().unwrap_or(&self.meta.name);
1210                 return Err(Error::missing_subcommand(
1211                     bn,
1212                     &usage::create_error_usage(self, matcher, None),
1213                     self.color(),
1214                 ));
1215             } else if self.is_set(AS::SubcommandRequiredElseHelp) {
1216                 debugln!("Parser::get_matches_with: SubcommandRequiredElseHelp=true");
1217                 let mut out = vec![];
1218                 self.write_help_err(&mut out)?;
1219                 return Err(Error {
1220                     message: String::from_utf8_lossy(&*out).into_owned(),
1221                     kind: ErrorKind::MissingArgumentOrSubcommand,
1222                     info: None,
1223                 });
1224             }
1225         }
1226 
1227         // In case the last arg was new, we  need to process it's overrides
1228         let check_all = self.is_set(AS::AllArgsOverrideSelf);
1229         {
1230             let any_arg = find_any_by_name!(self, self.cache.unwrap_or(""));
1231             matcher.process_arg_overrides(
1232                 any_arg,
1233                 &mut self.overrides,
1234                 &mut self.required,
1235                 check_all,
1236             );
1237         }
1238 
1239         self.remove_overrides(matcher);
1240 
1241         Validator::new(self).validate(needs_val_of, subcmd_name, matcher)
1242     }
1243 
remove_overrides(&mut self, matcher: &mut ArgMatcher)1244     fn remove_overrides(&mut self, matcher: &mut ArgMatcher) {
1245         debugln!("Parser::remove_overrides:{:?};", self.overrides);
1246         for &(overr, name) in &self.overrides {
1247             debugln!("Parser::remove_overrides:iter:({},{});", overr, name);
1248             if matcher.is_present(overr) {
1249                 debugln!(
1250                     "Parser::remove_overrides:iter:({},{}): removing {};",
1251                     overr,
1252                     name,
1253                     name
1254                 );
1255                 matcher.remove(name);
1256                 for i in (0..self.required.len()).rev() {
1257                     debugln!(
1258                         "Parser::remove_overrides:iter:({},{}): removing required {};",
1259                         overr,
1260                         name,
1261                         name
1262                     );
1263                     if self.required[i] == name {
1264                         self.required.swap_remove(i);
1265                         break;
1266                     }
1267                 }
1268             }
1269         }
1270     }
1271 
propagate_help_version(&mut self)1272     fn propagate_help_version(&mut self) {
1273         debugln!("Parser::propagate_help_version;");
1274         self.create_help_and_version();
1275         for sc in &mut self.subcommands {
1276             sc.p.propagate_help_version();
1277         }
1278     }
1279 
build_bin_names(&mut self)1280     fn build_bin_names(&mut self) {
1281         debugln!("Parser::build_bin_names;");
1282         for sc in &mut self.subcommands {
1283             debug!("Parser::build_bin_names:iter: bin_name set...");
1284             if sc.p.meta.bin_name.is_none() {
1285                 sdebugln!("No");
1286                 let bin_name = format!(
1287                     "{}{}{}",
1288                     self.meta
1289                         .bin_name
1290                         .as_ref()
1291                         .unwrap_or(&self.meta.name.clone()),
1292                     if self.meta.bin_name.is_some() {
1293                         " "
1294                     } else {
1295                         ""
1296                     },
1297                     &*sc.p.meta.name
1298                 );
1299                 debugln!(
1300                     "Parser::build_bin_names:iter: Setting bin_name of {} to {}",
1301                     self.meta.name,
1302                     bin_name
1303                 );
1304                 sc.p.meta.bin_name = Some(bin_name);
1305             } else {
1306                 sdebugln!("yes ({:?})", sc.p.meta.bin_name);
1307             }
1308             debugln!(
1309                 "Parser::build_bin_names:iter: Calling build_bin_names from...{}",
1310                 sc.p.meta.name
1311             );
1312             sc.p.build_bin_names();
1313         }
1314     }
1315 
parse_subcommand<I, T>( &mut self, sc_name: &str, matcher: &mut ArgMatcher<'a>, it: &mut Peekable<I>, ) -> ClapResult<()> where I: Iterator<Item = T>, T: Into<OsString> + Clone,1316     fn parse_subcommand<I, T>(
1317         &mut self,
1318         sc_name: &str,
1319         matcher: &mut ArgMatcher<'a>,
1320         it: &mut Peekable<I>,
1321     ) -> ClapResult<()>
1322     where
1323         I: Iterator<Item = T>,
1324         T: Into<OsString> + Clone,
1325     {
1326         use std::fmt::Write;
1327         debugln!("Parser::parse_subcommand;");
1328         let mut mid_string = String::new();
1329         if !self.is_set(AS::SubcommandsNegateReqs) {
1330             let mut hs: Vec<&str> = self.required.iter().map(|n| &**n).collect();
1331             for k in matcher.arg_names() {
1332                 hs.push(k);
1333             }
1334             let reqs = usage::get_required_usage_from(self, &hs, Some(matcher), None, false);
1335 
1336             for s in &reqs {
1337                 write!(&mut mid_string, " {}", s).expect(INTERNAL_ERROR_MSG);
1338             }
1339         }
1340         mid_string.push(' ');
1341         if let Some(ref mut sc) = self
1342             .subcommands
1343             .iter_mut()
1344             .find(|s| s.p.meta.name == sc_name)
1345         {
1346             let mut sc_matcher = ArgMatcher::new();
1347             // bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by
1348             // a space
1349             sc.p.meta.usage = Some(format!(
1350                 "{}{}{}",
1351                 self.meta.bin_name.as_ref().unwrap_or(&String::new()),
1352                 if self.meta.bin_name.is_some() {
1353                     &*mid_string
1354                 } else {
1355                     ""
1356                 },
1357                 &*sc.p.meta.name
1358             ));
1359             sc.p.meta.bin_name = Some(format!(
1360                 "{}{}{}",
1361                 self.meta.bin_name.as_ref().unwrap_or(&String::new()),
1362                 if self.meta.bin_name.is_some() {
1363                     " "
1364                 } else {
1365                     ""
1366                 },
1367                 &*sc.p.meta.name
1368             ));
1369             debugln!(
1370                 "Parser::parse_subcommand: About to parse sc={}",
1371                 sc.p.meta.name
1372             );
1373             debugln!("Parser::parse_subcommand: sc settings={:#?}", sc.p.settings);
1374             sc.p.get_matches_with(&mut sc_matcher, it)?;
1375             matcher.subcommand(SubCommand {
1376                 name: sc.p.meta.name.clone(),
1377                 matches: sc_matcher.into(),
1378             });
1379         }
1380         Ok(())
1381     }
1382 
groups_for_arg(&self, name: &str) -> Option<Vec<&'a str>>1383     pub fn groups_for_arg(&self, name: &str) -> Option<Vec<&'a str>> {
1384         debugln!("Parser::groups_for_arg: name={}", name);
1385 
1386         if self.groups.is_empty() {
1387             debugln!("Parser::groups_for_arg: No groups defined");
1388             return None;
1389         }
1390         let mut res = vec![];
1391         debugln!("Parser::groups_for_arg: Searching through groups...");
1392         for grp in &self.groups {
1393             for a in &grp.args {
1394                 if a == &name {
1395                     sdebugln!("\tFound '{}'", grp.name);
1396                     res.push(&*grp.name);
1397                 }
1398             }
1399         }
1400         if res.is_empty() {
1401             return None;
1402         }
1403 
1404         Some(res)
1405     }
1406 
args_in_group(&self, group: &str) -> Vec<String>1407     pub fn args_in_group(&self, group: &str) -> Vec<String> {
1408         debug_assert!(self.app_debug_asserts());
1409 
1410         let mut g_vec = vec![];
1411         let mut args = vec![];
1412 
1413         for n in &self
1414             .groups
1415             .iter()
1416             .find(|g| g.name == group)
1417             .expect(INTERNAL_ERROR_MSG)
1418             .args
1419         {
1420             if let Some(f) = self.flags.iter().find(|f| &f.b.name == n) {
1421                 args.push(f.to_string());
1422             } else if let Some(f) = self.opts.iter().find(|o| &o.b.name == n) {
1423                 args.push(f.to_string());
1424             } else if let Some(p) = self.positionals.values().find(|p| &p.b.name == n) {
1425                 args.push(p.b.name.to_owned());
1426             } else {
1427                 g_vec.push(*n);
1428             }
1429         }
1430 
1431         for av in g_vec.iter().map(|g| self.args_in_group(g)) {
1432             args.extend(av);
1433         }
1434         args.dedup();
1435         args.iter().map(ToOwned::to_owned).collect()
1436     }
1437 
arg_names_in_group(&self, group: &str) -> Vec<&'a str>1438     pub fn arg_names_in_group(&self, group: &str) -> Vec<&'a str> {
1439         let mut g_vec = vec![];
1440         let mut args = vec![];
1441 
1442         for n in &self
1443             .groups
1444             .iter()
1445             .find(|g| g.name == group)
1446             .expect(INTERNAL_ERROR_MSG)
1447             .args
1448         {
1449             if self.groups.iter().any(|g| g.name == *n) {
1450                 args.extend(self.arg_names_in_group(n));
1451                 g_vec.push(*n);
1452             } else if !args.contains(n) {
1453                 args.push(*n);
1454             }
1455         }
1456 
1457         args.iter().copied().collect()
1458     }
1459 
create_help_and_version(&mut self)1460     pub fn create_help_and_version(&mut self) {
1461         debugln!("Parser::create_help_and_version;");
1462         // name is "hclap_help" because flags are sorted by name
1463         if !self.is_set(AS::DisableHelpFlags) && !self.contains_long("help") {
1464             debugln!("Parser::create_help_and_version: Building --help");
1465             if self.help_short.is_none() && !self.contains_short('h') {
1466                 self.help_short = Some('h');
1467             }
1468             let arg = FlagBuilder {
1469                 b: Base {
1470                     name: "hclap_help",
1471                     help: self.help_message.or(Some("Prints help information")),
1472                     ..Default::default()
1473                 },
1474                 s: Switched {
1475                     short: self.help_short,
1476                     long: Some("help"),
1477                     ..Default::default()
1478                 },
1479             };
1480             self.flags.push(arg);
1481         }
1482         if !self.is_set(AS::DisableVersion) && !self.contains_long("version") {
1483             debugln!("Parser::create_help_and_version: Building --version");
1484             if self.version_short.is_none() && !self.contains_short('V') {
1485                 self.version_short = Some('V');
1486             }
1487             // name is "vclap_version" because flags are sorted by name
1488             let arg = FlagBuilder {
1489                 b: Base {
1490                     name: "vclap_version",
1491                     help: self.version_message.or(Some("Prints version information")),
1492                     ..Default::default()
1493                 },
1494                 s: Switched {
1495                     short: self.version_short,
1496                     long: Some("version"),
1497                     ..Default::default()
1498                 },
1499             };
1500             self.flags.push(arg);
1501         }
1502         if !self.subcommands.is_empty()
1503             && !self.is_set(AS::DisableHelpSubcommand)
1504             && self.is_set(AS::NeedsSubcommandHelp)
1505         {
1506             debugln!("Parser::create_help_and_version: Building help");
1507             self.subcommands.push(
1508                 App::new("help")
1509                     .about("Prints this message or the help of the given subcommand(s)"),
1510             );
1511         }
1512     }
1513 
1514     // Retrieves the names of all args the user has supplied thus far, except required ones
1515     // because those will be listed in self.required
check_for_help_and_version_str(&self, arg: &OsStr) -> ClapResult<()>1516     fn check_for_help_and_version_str(&self, arg: &OsStr) -> ClapResult<()> {
1517         debugln!("Parser::check_for_help_and_version_str;");
1518         debug!(
1519             "Parser::check_for_help_and_version_str: Checking if --{} is help or version...",
1520             arg.to_str().unwrap()
1521         );
1522         if arg == "help" && self.is_set(AS::NeedsLongHelp) {
1523             sdebugln!("Help");
1524             return Err(self._help(true));
1525         }
1526         if arg == "version" && self.is_set(AS::NeedsLongVersion) {
1527             sdebugln!("Version");
1528             return Err(self._version(true));
1529         }
1530         sdebugln!("Neither");
1531 
1532         Ok(())
1533     }
1534 
check_for_help_and_version_char(&self, arg: char) -> ClapResult<()>1535     fn check_for_help_and_version_char(&self, arg: char) -> ClapResult<()> {
1536         debugln!("Parser::check_for_help_and_version_char;");
1537         debug!(
1538             "Parser::check_for_help_and_version_char: Checking if -{} is help or version...",
1539             arg
1540         );
1541         if let Some(h) = self.help_short {
1542             if arg == h && self.is_set(AS::NeedsLongHelp) {
1543                 sdebugln!("Help");
1544                 return Err(self._help(false));
1545             }
1546         }
1547         if let Some(v) = self.version_short {
1548             if arg == v && self.is_set(AS::NeedsLongVersion) {
1549                 sdebugln!("Version");
1550                 return Err(self._version(false));
1551             }
1552         }
1553         sdebugln!("Neither");
1554         Ok(())
1555     }
1556 
use_long_help(&self) -> bool1557     fn use_long_help(&self) -> bool {
1558         // In this case, both must be checked. This allows the retention of
1559         // original formatting, but also ensures that the actual -h or --help
1560         // specified by the user is sent through. If HiddenShortHelp is not included,
1561         // then items specified with hidden_short_help will also be hidden.
1562         let should_long = |v: &Base| {
1563             v.long_help.is_some()
1564                 || v.is_set(ArgSettings::HiddenLongHelp)
1565                 || v.is_set(ArgSettings::HiddenShortHelp)
1566         };
1567 
1568         self.meta.long_about.is_some()
1569             || self.flags.iter().any(|f| should_long(&f.b))
1570             || self.opts.iter().any(|o| should_long(&o.b))
1571             || self.positionals.values().any(|p| should_long(&p.b))
1572             || self
1573                 .subcommands
1574                 .iter()
1575                 .any(|s| s.p.meta.long_about.is_some())
1576     }
1577 
_help(&self, mut use_long: bool) -> Error1578     fn _help(&self, mut use_long: bool) -> Error {
1579         debugln!("Parser::_help: use_long={:?}", use_long);
1580         use_long = use_long && self.use_long_help();
1581         let mut buf = vec![];
1582         match Help::write_parser_help(&mut buf, self, use_long) {
1583             Err(e) => e,
1584             _ => Error {
1585                 message: String::from_utf8(buf).unwrap_or_default(),
1586                 kind: ErrorKind::HelpDisplayed,
1587                 info: None,
1588             },
1589         }
1590     }
1591 
_version(&self, use_long: bool) -> Error1592     fn _version(&self, use_long: bool) -> Error {
1593         debugln!("Parser::_version: ");
1594         let out = io::stdout();
1595         let mut buf_w = BufWriter::new(out.lock());
1596         match self.print_version(&mut buf_w, use_long) {
1597             Err(e) => e,
1598             _ => Error {
1599                 message: String::new(),
1600                 kind: ErrorKind::VersionDisplayed,
1601                 info: None,
1602             },
1603         }
1604     }
1605 
parse_long_arg<I, T>( &mut self, matcher: &mut ArgMatcher<'a>, full_arg: &OsStr, it: &mut Peekable<I>, ) -> ClapResult<ParseResult<'a>> where I: Iterator<Item = T>, T: Into<OsString> + Clone,1606     fn parse_long_arg<I, T>(
1607         &mut self,
1608         matcher: &mut ArgMatcher<'a>,
1609         full_arg: &OsStr,
1610         it: &mut Peekable<I>,
1611     ) -> ClapResult<ParseResult<'a>>
1612     where
1613         I: Iterator<Item = T>,
1614         T: Into<OsString> + Clone,
1615     {
1616         // maybe here lifetime should be 'a
1617         debugln!("Parser::parse_long_arg;");
1618 
1619         // Update the current index
1620         self.cur_idx.set(self.cur_idx.get() + 1);
1621 
1622         let mut val = None;
1623         debug!("Parser::parse_long_arg: Does it contain '='...");
1624         let arg = if full_arg.contains_byte(b'=') {
1625             let (p0, p1) = full_arg.trim_left_matches(b'-').split_at_byte(b'=');
1626             sdebugln!("Yes '{:?}'", p1);
1627             val = Some(p1);
1628             p0
1629         } else {
1630             sdebugln!("No");
1631             full_arg.trim_left_matches(b'-')
1632         };
1633 
1634         if let Some(opt) = find_opt_by_long!(@os self, arg) {
1635             debugln!(
1636                 "Parser::parse_long_arg: Found valid opt '{}'",
1637                 opt.to_string()
1638             );
1639             self.settings.set(AS::ValidArgFound);
1640             let ret = self.parse_opt(val, opt, val.is_some(), matcher)?;
1641             if self.cache.map_or(true, |name| name != opt.b.name) {
1642                 self.cache = Some(opt.b.name);
1643             }
1644 
1645             return Ok(ret);
1646         } else if let Some(flag) = find_flag_by_long!(@os self, arg) {
1647             debugln!(
1648                 "Parser::parse_long_arg: Found valid flag '{}'",
1649                 flag.to_string()
1650             );
1651             self.settings.set(AS::ValidArgFound);
1652             // Only flags could be help or version, and we need to check the raw long
1653             // so this is the first point to check
1654             self.check_for_help_and_version_str(arg)?;
1655 
1656             self.parse_flag(flag, matcher)?;
1657 
1658             // Handle conflicts, requirements, etc.
1659             if self.cache.map_or(true, |name| name != flag.b.name) {
1660                 self.cache = Some(flag.b.name);
1661             }
1662 
1663             return Ok(ParseResult::Flag);
1664         } else if self.is_set(AS::AllowLeadingHyphen) {
1665             return Ok(ParseResult::MaybeHyphenValue);
1666         } else if self.is_set(AS::ValidNegNumFound) {
1667             return Ok(ParseResult::MaybeNegNum);
1668         }
1669 
1670         debugln!("Parser::parse_long_arg: Didn't match anything");
1671 
1672         let args_rest: Vec<_> = it.map(|x| x.into()).collect();
1673         let args_rest2: Vec<_> = args_rest
1674             .iter()
1675             .map(|x| x.to_str().expect(INVALID_UTF8))
1676             .collect();
1677         self.did_you_mean_error(arg.to_str().expect(INVALID_UTF8), matcher, &args_rest2[..])
1678             .map(|_| ParseResult::NotFound)
1679     }
1680 
parse_short_arg( &mut self, matcher: &mut ArgMatcher<'a>, full_arg: &OsStr, ) -> ClapResult<ParseResult<'a>>1681     fn parse_short_arg(
1682         &mut self,
1683         matcher: &mut ArgMatcher<'a>,
1684         full_arg: &OsStr,
1685     ) -> ClapResult<ParseResult<'a>> {
1686         debugln!("Parser::parse_short_arg: full_arg={:?}", full_arg);
1687         let arg_os = full_arg.trim_left_matches(b'-');
1688         let arg = arg_os.to_string_lossy();
1689 
1690         // If AllowLeadingHyphen is set, we want to ensure `-val` gets parsed as `-val` and not
1691         // `-v` `-a` `-l` assuming `v` `a` and `l` are all, or mostly, valid shorts.
1692         if self.is_set(AS::AllowLeadingHyphen) {
1693             if arg.chars().any(|c| !self.contains_short(c)) {
1694                 debugln!(
1695                     "Parser::parse_short_arg: LeadingHyphenAllowed yet -{} isn't valid",
1696                     arg
1697                 );
1698                 return Ok(ParseResult::MaybeHyphenValue);
1699             }
1700         } else if self.is_set(AS::ValidNegNumFound) {
1701             // TODO: Add docs about having AllowNegativeNumbers and `-2` as a valid short
1702             // May be better to move this to *after* not finding a valid flag/opt?
1703             debugln!("Parser::parse_short_arg: Valid negative num...");
1704             return Ok(ParseResult::MaybeNegNum);
1705         }
1706 
1707         let mut ret = ParseResult::NotFound;
1708         for c in arg.chars() {
1709             debugln!("Parser::parse_short_arg:iter:{}", c);
1710 
1711             // update each index because `-abcd` is four indices to clap
1712             self.cur_idx.set(self.cur_idx.get() + 1);
1713 
1714             // Check for matching short options, and return the name if there is no trailing
1715             // concatenated value: -oval
1716             // Option: -o
1717             // Value: val
1718             if let Some(opt) = find_opt_by_short!(self, c) {
1719                 debugln!("Parser::parse_short_arg:iter:{}: Found valid opt", c);
1720                 self.settings.set(AS::ValidArgFound);
1721                 // Check for trailing concatenated value
1722                 let p: Vec<_> = arg.splitn(2, c).collect();
1723                 debugln!(
1724                     "Parser::parse_short_arg:iter:{}: p[0]={:?}, p[1]={:?}",
1725                     c,
1726                     p[0].as_bytes(),
1727                     p[1].as_bytes()
1728                 );
1729                 let i = p[0].as_bytes().len() + 1;
1730                 let val = if !p[1].as_bytes().is_empty() {
1731                     debugln!(
1732                         "Parser::parse_short_arg:iter:{}: val={:?} (bytes), val={:?} (ascii)",
1733                         c,
1734                         arg_os.split_at(i).1.as_bytes(),
1735                         arg_os.split_at(i).1
1736                     );
1737                     Some(arg_os.split_at(i).1)
1738                 } else {
1739                     None
1740                 };
1741 
1742                 // Default to "we're expecting a value later"
1743                 let ret = self.parse_opt(val, opt, false, matcher)?;
1744 
1745                 if self.cache.map_or(true, |name| name != opt.b.name) {
1746                     self.cache = Some(opt.b.name);
1747                 }
1748 
1749                 return Ok(ret);
1750             } else if let Some(flag) = find_flag_by_short!(self, c) {
1751                 debugln!("Parser::parse_short_arg:iter:{}: Found valid flag", c);
1752                 self.settings.set(AS::ValidArgFound);
1753                 // Only flags can be help or version
1754                 self.check_for_help_and_version_char(c)?;
1755                 ret = self.parse_flag(flag, matcher)?;
1756 
1757                 // Handle conflicts, requirements, overrides, etc.
1758                 // Must be called here due to mutabililty
1759                 if self.cache.map_or(true, |name| name != flag.b.name) {
1760                     self.cache = Some(flag.b.name);
1761                 }
1762             } else {
1763                 let arg = format!("-{}", c);
1764                 return Err(Error::unknown_argument(
1765                     &*arg,
1766                     "",
1767                     &*usage::create_error_usage(self, matcher, None),
1768                     self.color(),
1769                 ));
1770             }
1771         }
1772         Ok(ret)
1773     }
1774 
parse_opt( &self, val: Option<&OsStr>, opt: &OptBuilder<'a, 'b>, had_eq: bool, matcher: &mut ArgMatcher<'a>, ) -> ClapResult<ParseResult<'a>>1775     fn parse_opt(
1776         &self,
1777         val: Option<&OsStr>,
1778         opt: &OptBuilder<'a, 'b>,
1779         had_eq: bool,
1780         matcher: &mut ArgMatcher<'a>,
1781     ) -> ClapResult<ParseResult<'a>> {
1782         debugln!("Parser::parse_opt; opt={}, val={:?}", opt.b.name, val);
1783         debugln!("Parser::parse_opt; opt.settings={:?}", opt.b.settings);
1784         let mut has_eq = false;
1785         let no_val = val.is_none();
1786         let empty_vals = opt.is_set(ArgSettings::EmptyValues);
1787         let min_vals_zero = opt.v.min_vals.unwrap_or(1) == 0;
1788         let needs_eq = opt.is_set(ArgSettings::RequireEquals);
1789 
1790         debug!("Parser::parse_opt; Checking for val...");
1791         if let Some(fv) = val {
1792             has_eq = fv.starts_with(&[b'=']) || had_eq;
1793             let v = fv.trim_left_matches(b'=');
1794             if !empty_vals && (v.is_empty() || (needs_eq && !has_eq)) {
1795                 sdebugln!("Found Empty - Error");
1796                 return Err(Error::empty_value(
1797                     opt,
1798                     &*usage::create_error_usage(self, matcher, None),
1799                     self.color(),
1800                 ));
1801             }
1802             sdebugln!("Found - {:?}, len: {}", v, v.len());
1803             debugln!(
1804                 "Parser::parse_opt: {:?} contains '='...{:?}",
1805                 fv,
1806                 fv.starts_with(&[b'='])
1807             );
1808             self.add_val_to_arg(opt, v, matcher)?;
1809         } else if needs_eq && !(empty_vals || min_vals_zero) {
1810             sdebugln!("None, but requires equals...Error");
1811             return Err(Error::empty_value(
1812                 opt,
1813                 &*usage::create_error_usage(self, matcher, None),
1814                 self.color(),
1815             ));
1816         } else {
1817             sdebugln!("None");
1818         }
1819 
1820         matcher.inc_occurrence_of(opt.b.name);
1821         // Increment or create the group "args"
1822         if let Some(vec) = self.groups_for_arg(opt.b.name) {
1823             matcher.inc_occurrences_of(&*vec);
1824         }
1825 
1826         let needs_delim = opt.is_set(ArgSettings::RequireDelimiter);
1827         let mult = opt.is_set(ArgSettings::Multiple);
1828         if no_val && min_vals_zero && !has_eq && needs_eq {
1829             debugln!("Parser::parse_opt: More arg vals not required...");
1830             return Ok(ParseResult::ValuesDone);
1831         } else if no_val || (mult && !needs_delim) && !has_eq && matcher.needs_more_vals(opt) {
1832             debugln!("Parser::parse_opt: More arg vals required...");
1833             return Ok(ParseResult::Opt(opt.b.name));
1834         }
1835         debugln!("Parser::parse_opt: More arg vals not required...");
1836         Ok(ParseResult::ValuesDone)
1837     }
1838 
add_val_to_arg<A>( &self, arg: &A, val: &OsStr, matcher: &mut ArgMatcher<'a>, ) -> ClapResult<ParseResult<'a>> where A: AnyArg<'a, 'b> + Display,1839     fn add_val_to_arg<A>(
1840         &self,
1841         arg: &A,
1842         val: &OsStr,
1843         matcher: &mut ArgMatcher<'a>,
1844     ) -> ClapResult<ParseResult<'a>>
1845     where
1846         A: AnyArg<'a, 'b> + Display,
1847     {
1848         debugln!("Parser::add_val_to_arg; arg={}, val={:?}", arg.name(), val);
1849         debugln!(
1850             "Parser::add_val_to_arg; trailing_vals={:?}, DontDelimTrailingVals={:?}",
1851             self.is_set(AS::TrailingValues),
1852             self.is_set(AS::DontDelimitTrailingValues)
1853         );
1854         if !(self.is_set(AS::TrailingValues) && self.is_set(AS::DontDelimitTrailingValues)) {
1855             if let Some(delim) = arg.val_delim() {
1856                 if val.is_empty() {
1857                     Ok(self.add_single_val_to_arg(arg, val, matcher)?)
1858                 } else {
1859                     let mut iret = ParseResult::ValuesDone;
1860                     for v in val.split(delim as u32 as u8) {
1861                         iret = self.add_single_val_to_arg(arg, v, matcher)?;
1862                     }
1863                     // If there was a delimiter used, we're not looking for more values
1864                     if val.contains_byte(delim as u32 as u8)
1865                         || arg.is_set(ArgSettings::RequireDelimiter)
1866                     {
1867                         iret = ParseResult::ValuesDone;
1868                     }
1869                     Ok(iret)
1870                 }
1871             } else {
1872                 self.add_single_val_to_arg(arg, val, matcher)
1873             }
1874         } else {
1875             self.add_single_val_to_arg(arg, val, matcher)
1876         }
1877     }
1878 
add_single_val_to_arg<A>( &self, arg: &A, v: &OsStr, matcher: &mut ArgMatcher<'a>, ) -> ClapResult<ParseResult<'a>> where A: AnyArg<'a, 'b> + Display,1879     fn add_single_val_to_arg<A>(
1880         &self,
1881         arg: &A,
1882         v: &OsStr,
1883         matcher: &mut ArgMatcher<'a>,
1884     ) -> ClapResult<ParseResult<'a>>
1885     where
1886         A: AnyArg<'a, 'b> + Display,
1887     {
1888         debugln!("Parser::add_single_val_to_arg;");
1889         debugln!("Parser::add_single_val_to_arg: adding val...{:?}", v);
1890 
1891         // update the current index because each value is a distinct index to clap
1892         self.cur_idx.set(self.cur_idx.get() + 1);
1893 
1894         // @TODO @docs @p4: docs for indices should probably note that a terminator isn't a value
1895         // and therefore not reported in indices
1896         if let Some(t) = arg.val_terminator() {
1897             if t == v {
1898                 return Ok(ParseResult::ValuesDone);
1899             }
1900         }
1901 
1902         matcher.add_val_to(arg.name(), v);
1903         matcher.add_index_to(arg.name(), self.cur_idx.get());
1904 
1905         // Increment or create the group "args"
1906         if let Some(grps) = self.groups_for_arg(arg.name()) {
1907             for grp in grps {
1908                 matcher.add_val_to(&*grp, v);
1909             }
1910         }
1911 
1912         if matcher.needs_more_vals(arg) {
1913             return Ok(ParseResult::Opt(arg.name()));
1914         }
1915         Ok(ParseResult::ValuesDone)
1916     }
1917 
parse_flag( &self, flag: &FlagBuilder<'a, 'b>, matcher: &mut ArgMatcher<'a>, ) -> ClapResult<ParseResult<'a>>1918     fn parse_flag(
1919         &self,
1920         flag: &FlagBuilder<'a, 'b>,
1921         matcher: &mut ArgMatcher<'a>,
1922     ) -> ClapResult<ParseResult<'a>> {
1923         debugln!("Parser::parse_flag;");
1924 
1925         matcher.inc_occurrence_of(flag.b.name);
1926         matcher.add_index_to(flag.b.name, self.cur_idx.get());
1927 
1928         // Increment or create the group "args"
1929         if let Some(vec) = self.groups_for_arg(flag.b.name) {
1930             matcher.inc_occurrences_of(&*vec);
1931         }
1932 
1933         Ok(ParseResult::Flag)
1934     }
1935 
did_you_mean_error( &self, arg: &str, matcher: &mut ArgMatcher<'a>, args_rest: &[&str], ) -> ClapResult<()>1936     fn did_you_mean_error(
1937         &self,
1938         arg: &str,
1939         matcher: &mut ArgMatcher<'a>,
1940         args_rest: &[&str],
1941     ) -> ClapResult<()> {
1942         // Didn't match a flag or option
1943         let suffix =
1944             suggestions::did_you_mean_flag_suffix(arg, args_rest, longs!(self), &self.subcommands);
1945 
1946         // Add the arg to the matches to build a proper usage string
1947         if let Some(name) = suffix.1 {
1948             if let Some(opt) = find_opt_by_long!(self, name) {
1949                 if let Some(grps) = self.groups_for_arg(&*opt.b.name) {
1950                     matcher.inc_occurrences_of(&*grps);
1951                 }
1952                 matcher.insert(&*opt.b.name);
1953             } else if let Some(flg) = find_flag_by_long!(self, name) {
1954                 if let Some(grps) = self.groups_for_arg(&*flg.b.name) {
1955                     matcher.inc_occurrences_of(&*grps);
1956                 }
1957                 matcher.insert(&*flg.b.name);
1958             }
1959         }
1960 
1961         let used_arg = format!("--{}", arg);
1962         Err(Error::unknown_argument(
1963             &*used_arg,
1964             &*suffix.0,
1965             &*usage::create_error_usage(self, matcher, None),
1966             self.color(),
1967         ))
1968     }
1969 
1970     // Prints the version to the user and exits if quit=true
print_version<W: Write>(&self, w: &mut W, use_long: bool) -> ClapResult<()>1971     fn print_version<W: Write>(&self, w: &mut W, use_long: bool) -> ClapResult<()> {
1972         self.write_version(w, use_long)?;
1973         w.flush().map_err(Error::from)
1974     }
1975 
write_version<W: Write>(&self, w: &mut W, use_long: bool) -> io::Result<()>1976     pub fn write_version<W: Write>(&self, w: &mut W, use_long: bool) -> io::Result<()> {
1977         let ver = if use_long {
1978             self.meta
1979                 .long_version
1980                 .unwrap_or_else(|| self.meta.version.unwrap_or(""))
1981         } else {
1982             self.meta
1983                 .version
1984                 .unwrap_or_else(|| self.meta.long_version.unwrap_or(""))
1985         };
1986         if let Some(bn) = self.meta.bin_name.as_ref() {
1987             if bn.contains(' ') {
1988                 // Incase we're dealing with subcommands i.e. git mv is translated to git-mv
1989                 write!(w, "{} {}", bn.replace(" ", "-"), ver)
1990             } else {
1991                 write!(w, "{} {}", &self.meta.name[..], ver)
1992             }
1993         } else {
1994             write!(w, "{} {}", &self.meta.name[..], ver)
1995         }
1996     }
1997 
print_help(&self) -> ClapResult<()>1998     pub fn print_help(&self) -> ClapResult<()> {
1999         let out = io::stdout();
2000         let mut buf_w = BufWriter::new(out.lock());
2001         self.write_help(&mut buf_w)
2002     }
2003 
write_help<W: Write>(&self, w: &mut W) -> ClapResult<()>2004     pub fn write_help<W: Write>(&self, w: &mut W) -> ClapResult<()> {
2005         Help::write_parser_help(w, self, false)
2006     }
2007 
write_long_help<W: Write>(&self, w: &mut W) -> ClapResult<()>2008     pub fn write_long_help<W: Write>(&self, w: &mut W) -> ClapResult<()> {
2009         Help::write_parser_help(w, self, true)
2010     }
2011 
write_help_err<W: Write>(&self, w: &mut W) -> ClapResult<()>2012     pub fn write_help_err<W: Write>(&self, w: &mut W) -> ClapResult<()> {
2013         Help::write_parser_help_to_stderr(w, self)
2014     }
2015 
add_defaults(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()>2016     pub fn add_defaults(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
2017         debugln!("Parser::add_defaults;");
2018         macro_rules! add_val {
2019             (@default $_self:ident, $a:ident, $m:ident) => {
2020                 if let Some(ref val) = $a.v.default_val {
2021                     debugln!("Parser::add_defaults:iter:{}: has default vals", $a.b.name);
2022                     if $m.get($a.b.name).map(|ma| ma.vals.len()).map(|len| len == 0).unwrap_or(false) {
2023                         debugln!("Parser::add_defaults:iter:{}: has no user defined vals", $a.b.name);
2024                         $_self.add_val_to_arg($a, OsStr::new(val), $m)?;
2025 
2026                         if $_self.cache.map_or(true, |name| name != $a.name()) {
2027                             $_self.cache = Some($a.name());
2028                         }
2029                     } else if $m.get($a.b.name).is_some() {
2030                         debugln!("Parser::add_defaults:iter:{}: has user defined vals", $a.b.name);
2031                     } else {
2032                         debugln!("Parser::add_defaults:iter:{}: wasn't used", $a.b.name);
2033 
2034                         $_self.add_val_to_arg($a, OsStr::new(val), $m)?;
2035 
2036                         if $_self.cache.map_or(true, |name| name != $a.name()) {
2037                             $_self.cache = Some($a.name());
2038                         }
2039                     }
2040                 } else {
2041                     debugln!("Parser::add_defaults:iter:{}: doesn't have default vals", $a.b.name);
2042                 }
2043             };
2044             ($_self:ident, $a:ident, $m:ident) => {
2045                 if let Some(ref vm) = $a.v.default_vals_ifs {
2046                     sdebugln!(" has conditional defaults");
2047                     let mut done = false;
2048                     if $m.get($a.b.name).is_none() {
2049                         for &(arg, val, default) in vm.values() {
2050                             let add = if let Some(a) = $m.get(arg) {
2051                                 if let Some(v) = val {
2052                                     a.vals.iter().any(|value| v == value)
2053                                 } else {
2054                                     true
2055                                 }
2056                             } else {
2057                                 false
2058                             };
2059                             if add {
2060                                 $_self.add_val_to_arg($a, OsStr::new(default), $m)?;
2061                                 if $_self.cache.map_or(true, |name| name != $a.name()) {
2062                                     $_self.cache = Some($a.name());
2063                                 }
2064                                 done = true;
2065                                 break;
2066                             }
2067                         }
2068                     }
2069 
2070                     if done {
2071                         continue; // outer loop (outside macro)
2072                     }
2073                 } else {
2074                     sdebugln!(" doesn't have conditional defaults");
2075                 }
2076                 add_val!(@default $_self, $a, $m)
2077             };
2078         }
2079 
2080         for o in &self.opts {
2081             debug!("Parser::add_defaults:iter:{}:", o.b.name);
2082             add_val!(self, o, matcher);
2083         }
2084         for p in self.positionals.values() {
2085             debug!("Parser::add_defaults:iter:{}:", p.b.name);
2086             add_val!(self, p, matcher);
2087         }
2088         Ok(())
2089     }
2090 
add_env(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()>2091     pub fn add_env(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
2092         macro_rules! add_val {
2093             ($_self:ident, $a:ident, $m:ident) => {
2094                 if let Some(ref val) = $a.v.env {
2095                     if $m
2096                         .get($a.b.name)
2097                         .map(|ma| ma.vals.len())
2098                         .map(|len| len == 0)
2099                         .unwrap_or(false)
2100                     {
2101                         if let Some(ref val) = val.1 {
2102                             $_self.add_val_to_arg($a, OsStr::new(val), $m)?;
2103 
2104                             if $_self.cache.map_or(true, |name| name != $a.name()) {
2105                                 $_self.cache = Some($a.name());
2106                             }
2107                         }
2108                     } else {
2109                         if let Some(ref val) = val.1 {
2110                             $_self.add_val_to_arg($a, OsStr::new(val), $m)?;
2111 
2112                             if $_self.cache.map_or(true, |name| name != $a.name()) {
2113                                 $_self.cache = Some($a.name());
2114                             }
2115                         }
2116                     }
2117                 }
2118             };
2119         }
2120 
2121         for o in &self.opts {
2122             add_val!(self, o, matcher);
2123         }
2124         for p in self.positionals.values() {
2125             add_val!(self, p, matcher);
2126         }
2127         Ok(())
2128     }
2129 
flags(&self) -> Iter<FlagBuilder<'a, 'b>>2130     pub fn flags(&self) -> Iter<FlagBuilder<'a, 'b>> {
2131         self.flags.iter()
2132     }
2133 
opts(&self) -> Iter<OptBuilder<'a, 'b>>2134     pub fn opts(&self) -> Iter<OptBuilder<'a, 'b>> {
2135         self.opts.iter()
2136     }
2137 
positionals(&self) -> map::Values<PosBuilder<'a, 'b>>2138     pub fn positionals(&self) -> map::Values<PosBuilder<'a, 'b>> {
2139         self.positionals.values()
2140     }
2141 
subcommands(&self) -> Iter<App>2142     pub fn subcommands(&self) -> Iter<App> {
2143         self.subcommands.iter()
2144     }
2145 
2146     // Should we color the output? None=determined by output location, true=yes, false=no
2147     #[doc(hidden)]
color(&self) -> ColorWhen2148     pub fn color(&self) -> ColorWhen {
2149         debugln!("Parser::color;");
2150         debug!("Parser::color: Color setting...");
2151         if self.is_set(AS::ColorNever) {
2152             sdebugln!("Never");
2153             ColorWhen::Never
2154         } else if self.is_set(AS::ColorAlways) {
2155             sdebugln!("Always");
2156             ColorWhen::Always
2157         } else {
2158             sdebugln!("Auto");
2159             ColorWhen::Auto
2160         }
2161     }
2162 
find_any_arg(&self, name: &str) -> Option<&AnyArg<'a, 'b>>2163     pub fn find_any_arg(&self, name: &str) -> Option<&AnyArg<'a, 'b>> {
2164         if let Some(f) = find_by_name!(self, name, flags, iter) {
2165             return Some(f);
2166         }
2167         if let Some(o) = find_by_name!(self, name, opts, iter) {
2168             return Some(o);
2169         }
2170         if let Some(p) = find_by_name!(self, name, positionals, values) {
2171             return Some(p);
2172         }
2173         None
2174     }
2175 
2176     /// Check is a given string matches the binary name for this parser
is_bin_name(&self, value: &str) -> bool2177     fn is_bin_name(&self, value: &str) -> bool {
2178         self.meta
2179             .bin_name
2180             .as_ref()
2181             .map(|name| value == name)
2182             .unwrap_or(false)
2183     }
2184 
2185     /// Check is a given string is an alias for this parser
is_alias(&self, value: &str) -> bool2186     fn is_alias(&self, value: &str) -> bool {
2187         self.meta
2188             .aliases
2189             .as_ref()
2190             .map(|aliases| {
2191                 for alias in aliases {
2192                     if alias.0 == value {
2193                         return true;
2194                     }
2195                 }
2196                 false
2197             })
2198             .unwrap_or(false)
2199     }
2200 
2201     // Only used for completion scripts due to bin_name messiness
2202     #[cfg_attr(feature = "lints", allow(block_in_if_condition_stmt))]
find_subcommand(&'b self, sc: &str) -> Option<&'b App<'a, 'b>>2203     pub fn find_subcommand(&'b self, sc: &str) -> Option<&'b App<'a, 'b>> {
2204         debugln!("Parser::find_subcommand: sc={}", sc);
2205         debugln!(
2206             "Parser::find_subcommand: Currently in Parser...{}",
2207             self.meta.bin_name.as_ref().unwrap()
2208         );
2209         for s in &self.subcommands {
2210             if s.p.is_bin_name(sc) {
2211                 return Some(s);
2212             }
2213             // XXX: why do we split here?
2214             // isn't `sc` supposed to be single word already?
2215             let last = sc.split(' ').rev().next().expect(INTERNAL_ERROR_MSG);
2216             if s.p.is_alias(last) {
2217                 return Some(s);
2218             }
2219 
2220             if let Some(app) = s.p.find_subcommand(sc) {
2221                 return Some(app);
2222             }
2223         }
2224         None
2225     }
2226 
2227     #[inline]
contains_long(&self, l: &str) -> bool2228     fn contains_long(&self, l: &str) -> bool {
2229         longs!(self).any(|al| al == &l)
2230     }
2231 
2232     #[inline]
contains_short(&self, s: char) -> bool2233     fn contains_short(&self, s: char) -> bool {
2234         shorts!(self).any(|arg_s| arg_s == &s)
2235     }
2236 }
2237