1 // Std
2 use std::{
3     cell::Cell,
4     ffi::{OsStr, OsString},
5 };
6 
7 // Internal
8 use crate::{
9     build::app::Propagation,
10     build::AppSettings as AS,
11     build::{App, Arg, ArgSettings},
12     mkeymap::KeyType,
13     output::{fmt::Colorizer, Help, HelpWriter, Usage},
14     parse::errors::Error as ClapError,
15     parse::errors::ErrorKind,
16     parse::errors::Result as ClapResult,
17     parse::features::suggestions,
18     parse::{ArgMatcher, SubCommand},
19     parse::{Validator, ValueType},
20     util::{termcolor::ColorChoice, ArgStr, ChildGraph, Id},
21     INTERNAL_ERROR_MSG, INVALID_UTF8,
22 };
23 
24 #[derive(Debug, PartialEq, Clone)]
25 pub(crate) enum ParseResult {
26     Flag(Id),
27     FlagSubCommand(String),
28     // subcommand name, whether there are more shorts args remaining
29     FlagSubCommandShort(String, bool),
30     Opt(Id),
31     Pos(Id),
32     MaybeHyphenValue,
33     MaybeNegNum,
34     NotFound,
35     ValuesDone(Id),
36 }
37 
38 #[derive(Debug)]
39 pub(crate) struct Input {
40     items: Vec<OsString>,
41     cursor: usize,
42 }
43 
44 impl<I, T> From<I> for Input
45 where
46     I: Iterator<Item = T>,
47     T: Into<OsString> + Clone,
48 {
from(val: I) -> Self49     fn from(val: I) -> Self {
50         Self {
51             items: val.map(|x| x.into()).collect(),
52             cursor: 0,
53         }
54     }
55 }
56 
57 impl Input {
next(&mut self, new: Option<&[&str]>) -> Option<(&OsStr, Option<&OsStr>)>58     pub(crate) fn next(&mut self, new: Option<&[&str]>) -> Option<(&OsStr, Option<&OsStr>)> {
59         if let Some(new) = new {
60             let mut new_items: Vec<OsString> = new.iter().map(OsString::from).collect();
61 
62             for i in self.cursor..self.items.len() {
63                 new_items.push(self.items[i].clone());
64             }
65 
66             self.items = new_items;
67             self.cursor = 0;
68         }
69 
70         if self.cursor >= self.items.len() {
71             None
72         } else {
73             self.cursor += 1;
74 
75             if self.cursor >= self.items.len() {
76                 Some((&self.items[self.cursor - 1], None))
77             } else {
78                 Some((&self.items[self.cursor - 1], Some(&self.items[self.cursor])))
79             }
80         }
81     }
82 
remaining(&self) -> &[OsString]83     pub(crate) fn remaining(&self) -> &[OsString] {
84         &self.items[self.cursor..]
85     }
86 }
87 
88 pub(crate) struct Parser<'help, 'app> {
89     pub(crate) app: &'app mut App<'help>,
90     pub(crate) required: ChildGraph<Id>,
91     pub(crate) overridden: Vec<Id>,
92     pub(crate) seen: Vec<Id>,
93     pub(crate) cur_idx: Cell<usize>,
94     pub(crate) skip_idxs: usize,
95 }
96 
97 // Initializing Methods
98 impl<'help, 'app> Parser<'help, 'app> {
new(app: &'app mut App<'help>) -> Self99     pub(crate) fn new(app: &'app mut App<'help>) -> Self {
100         let mut reqs = ChildGraph::with_capacity(5);
101         for a in app
102             .args
103             .args
104             .iter()
105             .filter(|a| a.settings.is_set(ArgSettings::Required))
106         {
107             reqs.insert(a.id.clone());
108         }
109 
110         Parser {
111             app,
112             required: reqs,
113             overridden: Vec::new(),
114             seen: Vec::new(),
115             cur_idx: Cell::new(0),
116             skip_idxs: 0,
117         }
118     }
119 
_verify_positionals(&self) -> bool120     fn _verify_positionals(&self) -> bool {
121         debug!("Parser::_verify_positionals");
122         // Because you must wait until all arguments have been supplied, this is the first chance
123         // to make assertions on positional argument indexes
124         //
125         // First we verify that the index highest supplied index, is equal to the number of
126         // positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3
127         // but no 2)
128 
129         let highest_idx = self
130             .app
131             .args
132             .keys
133             .iter()
134             .filter_map(|x| {
135                 if let KeyType::Position(n) = x.key {
136                     Some(n)
137                 } else {
138                     None
139                 }
140             })
141             .max()
142             .unwrap_or(0);
143 
144         //_highest_idx(&self.positionals);
145 
146         let num_p = self
147             .app
148             .args
149             .keys
150             .iter()
151             .map(|x| &x.key)
152             .filter(|x| x.is_position())
153             .count();
154 
155         assert!(
156             highest_idx == num_p as u64,
157             "Found positional argument whose index is {} but there \
158              are only {} positional arguments defined",
159             highest_idx,
160             num_p
161         );
162 
163         // Next we verify that only the highest index has a .multiple(true) (if any)
164         let only_highest = |a: &Arg| {
165             a.is_set(ArgSettings::MultipleValues) && (a.index.unwrap_or(0) != highest_idx)
166         };
167         if self.app.get_positionals().any(only_highest) {
168             // First we make sure if there is a positional that allows multiple values
169             // the one before it (second to last) has one of these:
170             //  * a value terminator
171             //  * ArgSettings::Last
172             //  * The last arg is Required
173 
174             // We can't pass the closure (it.next()) to the macro directly because each call to
175             // find() (iterator, not macro) gets called repeatedly.
176             let last = &self.app.args[&KeyType::Position(highest_idx)];
177             let second_to_last = &self.app.args[&KeyType::Position(highest_idx - 1)];
178 
179             // Either the final positional is required
180             // Or the second to last has a terminator or .last(true) set
181             let ok = last.is_set(ArgSettings::Required)
182                 || (second_to_last.terminator.is_some()
183                     || second_to_last.is_set(ArgSettings::Last))
184                 || last.is_set(ArgSettings::Last);
185             assert!(
186                 ok,
187                 "When using a positional argument with .multiple(true) that is *not the \
188                  last* positional argument, the last positional argument (i.e the one \
189                  with the highest index) *must* have .required(true) or .last(true) set."
190             );
191 
192             // We make sure if the second to last is Multiple the last is ArgSettings::Last
193             let ok = second_to_last.is_set(ArgSettings::MultipleValues)
194                 || last.is_set(ArgSettings::Last);
195             assert!(
196                 ok,
197                 "Only the last positional argument, or second to last positional \
198                  argument may be set to .multiple(true)"
199             );
200 
201             // Next we check how many have both Multiple and not a specific number of values set
202             let count = self
203                 .app
204                 .get_positionals()
205                 .filter(|p| p.settings.is_set(ArgSettings::MultipleValues) && p.num_vals.is_none())
206                 .count();
207             let ok = count <= 1
208                 || (last.is_set(ArgSettings::Last)
209                     && last.is_set(ArgSettings::MultipleValues)
210                     && second_to_last.is_set(ArgSettings::MultipleValues)
211                     && count == 2);
212             assert!(
213                 ok,
214                 "Only one positional argument with .multiple(true) set is allowed per \
215                  command, unless the second one also has .last(true) set"
216             );
217         }
218 
219         if self.is_set(AS::AllowMissingPositional) {
220             // Check that if a required positional argument is found, all positions with a lower
221             // index are also required.
222             let mut found = false;
223             let mut foundx2 = false;
224 
225             for p in self.app.get_positionals() {
226                 if foundx2 && !p.is_set(ArgSettings::Required) {
227                     assert!(
228                         p.is_set(ArgSettings::Required),
229                         "Found positional argument which is not required with a lower \
230                          index than a required positional argument by two or more: {:?} \
231                          index {:?}",
232                         p.name,
233                         p.index
234                     );
235                 } else if p.is_set(ArgSettings::Required) && !p.is_set(ArgSettings::Last) {
236                     // Args that .last(true) don't count since they can be required and have
237                     // positionals with a lower index that aren't required
238                     // Imagine: prog <req1> [opt1] -- <req2>
239                     // Both of these are valid invocations:
240                     //      $ prog r1 -- r2
241                     //      $ prog r1 o1 -- r2
242                     if found {
243                         foundx2 = true;
244                         continue;
245                     }
246                     found = true;
247                     continue;
248                 } else {
249                     found = false;
250                 }
251             }
252         } else {
253             // Check that if a required positional argument is found, all positions with a lower
254             // index are also required
255             let mut found = false;
256             for p in (1..=num_p)
257                 .rev()
258                 .filter_map(|n| self.app.args.get(&KeyType::Position(n as u64)))
259             {
260                 if found {
261                     assert!(
262                         p.is_set(ArgSettings::Required),
263                         "Found positional argument which is not required with a lower \
264                          index than a required positional argument: {:?} index {:?}",
265                         p.name,
266                         p.index
267                     );
268                 } else if p.is_set(ArgSettings::Required) && !p.is_set(ArgSettings::Last) {
269                     // Args that .last(true) don't count since they can be required and have
270                     // positionals with a lower index that aren't required
271                     // Imagine: prog <req1> [opt1] -- <req2>
272                     // Both of these are valid invocations:
273                     //      $ prog r1 -- r2
274                     //      $ prog r1 o1 -- r2
275                     found = true;
276                     continue;
277                 }
278             }
279         }
280         assert!(
281             self.app
282                 .get_positionals()
283                 .filter(|p| p.is_set(ArgSettings::Last))
284                 .count()
285                 < 2,
286             "Only one positional argument may have last(true) set. Found two."
287         );
288         if self
289             .app
290             .get_positionals()
291             .any(|p| p.is_set(ArgSettings::Last) && p.is_set(ArgSettings::Required))
292             && self.has_subcommands()
293             && !self.is_set(AS::SubcommandsNegateReqs)
294         {
295             panic!(
296                 "Having a required positional argument with .last(true) set *and* child \
297                  subcommands without setting SubcommandsNegateReqs isn't compatible."
298             );
299         }
300 
301         true
302     }
303 
304     #[allow(clippy::blocks_in_if_conditions)]
305     // Does all the initializing and prepares the parser
_build(&mut self)306     pub(crate) fn _build(&mut self) {
307         debug!("Parser::_build");
308 
309         #[cfg(debug_assertions)]
310         self._verify_positionals();
311 
312         // Set the LowIndexMultiple flag if required
313         if self.app.get_positionals().any(|a| {
314             a.is_set(ArgSettings::MultipleValues)
315                 && (a.index.unwrap_or(0) as usize
316                     != self
317                         .app
318                         .args
319                         .keys
320                         .iter()
321                         .filter(|x| x.key.is_position())
322                         .count())
323         }) && self.app.get_positionals().last().map_or(false, |p_name| {
324             !self.app[&p_name.id].is_set(ArgSettings::Last)
325         }) {
326             self.app.settings.set(AS::LowIndexMultiplePositional);
327         }
328 
329         for group in &self.app.groups {
330             if group.required {
331                 let idx = self.required.insert(group.id.clone());
332                 for a in &group.requires {
333                     self.required.insert_child(idx, a.clone());
334                 }
335             }
336         }
337     }
338 }
339 
340 // Parsing Methods
341 impl<'help, 'app> Parser<'help, 'app> {
342     // The actual parsing function
343     #[allow(clippy::cognitive_complexity)]
get_matches_with( &mut self, matcher: &mut ArgMatcher, it: &mut Input, ) -> ClapResult<()>344     pub(crate) fn get_matches_with(
345         &mut self,
346         matcher: &mut ArgMatcher,
347         it: &mut Input,
348     ) -> ClapResult<()> {
349         debug!("Parser::get_matches_with");
350         // Verify all positional assertions pass
351         self._build();
352 
353         let has_args = self.has_args();
354 
355         let mut subcmd_name: Option<String> = None;
356         let mut keep_state = false;
357         let mut external_subcommand = false;
358         let mut needs_val_of: ParseResult = ParseResult::NotFound;
359         let mut pos_counter = 1;
360         let mut replace: Option<&[&str]> = None;
361 
362         while let Some((arg_os, next_arg)) = it.next(replace) {
363             replace = None;
364 
365             let arg_os = ArgStr::new(arg_os);
366             debug!(
367                 "Parser::get_matches_with: Begin parsing '{:?}' ({:?})",
368                 arg_os,
369                 arg_os.as_raw_bytes()
370             );
371 
372             for (key, val) in &self.app.replacers {
373                 if *key == arg_os {
374                     debug!(
375                         "Parser::get_matches_with: found replacer: {:?}, target: {:?}",
376                         key, val
377                     );
378                     replace = Some(val);
379                 }
380             }
381 
382             if replace.is_some() {
383                 continue;
384             }
385 
386             self.unset(AS::ValidNegNumFound);
387 
388             // Is this a new argument, or values from a previous option?
389             let starts_new_arg = self.is_new_arg(&arg_os, &needs_val_of);
390 
391             if !self.is_set(AS::TrailingValues) && arg_os == "--" && starts_new_arg {
392                 debug!("Parser::get_matches_with: setting TrailingVals=true");
393                 self.set(AS::TrailingValues);
394                 continue;
395             }
396 
397             // Has the user already passed '--'? Meaning only positional args follow
398             if !self.is_set(AS::TrailingValues) {
399                 // Does the arg match a subcommand name, or any of its aliases (if defined)
400                 match needs_val_of {
401                     ParseResult::Opt(_) | ParseResult::Pos(_)
402                         if !self.is_set(AS::SubcommandPrecedenceOverArg) => {}
403                     _ => {
404                         let sc_name = self.possible_subcommand(&arg_os);
405                         debug!(
406                             "Parser::get_matches_with: possible_sc={:?}, sc={:?}",
407                             sc_name.is_some(),
408                             sc_name
409                         );
410 
411                         if let Some(sc_name) = sc_name {
412                             if sc_name == "help" && !self.is_set(AS::NoAutoHelp) {
413                                 self.parse_help_subcommand(it.remaining())?;
414                             }
415 
416                             subcmd_name = Some(sc_name.to_owned());
417                             break;
418                         }
419                     }
420                 }
421 
422                 if starts_new_arg {
423                     if arg_os.starts_with("--") {
424                         needs_val_of = self.parse_long_arg(matcher, &arg_os)?;
425                         debug!(
426                             "Parser::get_matches_with: After parse_long_arg {:?}",
427                             needs_val_of
428                         );
429                         match needs_val_of {
430                             ParseResult::Flag(ref id)
431                             | ParseResult::Opt(ref id)
432                             | ParseResult::ValuesDone(ref id) => {
433                                 self.maybe_inc_pos_counter(&mut pos_counter, id);
434                                 continue;
435                             }
436                             ParseResult::FlagSubCommand(ref name) => {
437                                 debug!("Parser::get_matches_with: FlagSubCommand found in long arg {:?}", name);
438                                 subcmd_name = Some(name.to_owned());
439                                 break;
440                             }
441                             ParseResult::FlagSubCommandShort(_, _) => unreachable!(),
442                             _ => (),
443                         }
444                     } else if arg_os.starts_with("-") && arg_os.len() != 1 {
445                         // Try to parse short args like normal, if AllowLeadingHyphen or
446                         // AllowNegativeNumbers is set, parse_short_arg will *not* throw
447                         // an error, and instead return Ok(None)
448                         needs_val_of = self.parse_short_arg(matcher, &arg_os)?;
449                         // If it's None, we then check if one of those two AppSettings was set
450                         debug!(
451                             "Parser::get_matches_with: After parse_short_arg {:?}",
452                             needs_val_of
453                         );
454                         match needs_val_of {
455                             ParseResult::MaybeNegNum => {
456                                 let lossy_arg = arg_os.to_string_lossy();
457                                 if !(lossy_arg.parse::<i64>().is_ok()
458                                     || lossy_arg.parse::<f64>().is_ok())
459                                 {
460                                     return Err(ClapError::unknown_argument(
461                                         lossy_arg.to_string(),
462                                         None,
463                                         Usage::new(self).create_usage_with_title(&[]),
464                                         self.app.color(),
465                                     ));
466                                 }
467                             }
468                             ParseResult::Opt(ref id)
469                             | ParseResult::Flag(ref id)
470                             | ParseResult::ValuesDone(ref id) => {
471                                 self.maybe_inc_pos_counter(&mut pos_counter, id);
472                                 continue;
473                             }
474                             ParseResult::FlagSubCommandShort(ref name, done) => {
475                                 // There are more short args, revist the current short args skipping the subcommand
476                                 keep_state = !done;
477                                 if keep_state {
478                                     it.cursor -= 1;
479                                     self.skip_idxs = self.cur_idx.get();
480                                 }
481 
482                                 subcmd_name = Some(name.to_owned());
483                                 break;
484                             }
485                             ParseResult::FlagSubCommand(_) => unreachable!(),
486                             _ => (),
487                         }
488                     }
489                 } else if let ParseResult::Opt(id) = needs_val_of {
490                     // Check to see if parsing a value from a previous arg
491 
492                     // get the option so we can check the settings
493                     needs_val_of = self.add_val_to_arg(
494                         &self.app[&id],
495                         &arg_os,
496                         matcher,
497                         ValueType::CommandLine,
498                     )?;
499                     // get the next value from the iterator
500                     continue;
501                 }
502 
503                 if !(self.is_set(AS::ArgsNegateSubcommands) && self.is_set(AS::ValidArgFound)
504                     || self.is_set(AS::AllowExternalSubcommands)
505                     || self.is_set(AS::InferSubcommands))
506                 {
507                     let cands = suggestions::did_you_mean(
508                         &*arg_os.to_string_lossy(),
509                         self.app.all_subcommand_names(),
510                     );
511                     if !cands.is_empty() {
512                         let cands: Vec<_> =
513                             cands.iter().map(|cand| format!("'{}'", cand)).collect();
514                         return Err(ClapError::invalid_subcommand(
515                             arg_os.to_string_lossy().to_string(),
516                             cands.join(" or "),
517                             self.app
518                                 .bin_name
519                                 .as_ref()
520                                 .unwrap_or(&self.app.name)
521                                 .to_string(),
522                             Usage::new(self).create_usage_with_title(&[]),
523                             self.app.color(),
524                         ));
525                     }
526                 }
527             }
528 
529             let positional_count = self
530                 .app
531                 .args
532                 .keys
533                 .iter()
534                 .filter(|x| x.key.is_position())
535                 .count();
536             let is_second_to_last = positional_count > 1 && (pos_counter == (positional_count - 1));
537 
538             let low_index_mults = self.is_set(AS::LowIndexMultiplePositional) && is_second_to_last;
539             let missing_pos = self.is_set(AS::AllowMissingPositional)
540                 && is_second_to_last
541                 && !self.is_set(AS::TrailingValues);
542 
543             debug!(
544                 "Parser::get_matches_with: Positional counter...{}",
545                 pos_counter
546             );
547             debug!(
548                 "Parser::get_matches_with: Low index multiples...{:?}",
549                 low_index_mults
550             );
551 
552             if low_index_mults || missing_pos {
553                 if let Some(n) = next_arg {
554                     needs_val_of = match needs_val_of {
555                         ParseResult::ValuesDone(id) => ParseResult::ValuesDone(id),
556 
557                         _ => {
558                             if let Some(p) = self
559                                 .app
560                                 .get_positionals()
561                                 .find(|p| p.index == Some(pos_counter as u64))
562                             {
563                                 ParseResult::Pos(p.id.clone())
564                             } else {
565                                 ParseResult::ValuesDone(Id::empty_hash())
566                             }
567                         }
568                     };
569 
570                     let n = ArgStr::new(n);
571                     let sc_match = { self.possible_subcommand(&n).is_some() };
572 
573                     if self.is_new_arg(&n, &needs_val_of)
574                         || sc_match
575                         || !suggestions::did_you_mean(
576                             &n.to_string_lossy(),
577                             self.app.all_subcommand_names(),
578                         )
579                         .is_empty()
580                     {
581                         debug!("Parser::get_matches_with: Bumping the positional counter...");
582                         pos_counter += 1;
583                     }
584                 } else {
585                     debug!("Parser::get_matches_with: Bumping the positional counter...");
586                     pos_counter += 1;
587                 }
588             } else if (self.is_set(AS::AllowMissingPositional) && self.is_set(AS::TrailingValues))
589                 || (self.is_set(AS::ContainsLast) && self.is_set(AS::TrailingValues))
590             {
591                 // Came to -- and one positional has .last(true) set, so we go immediately
592                 // to the last (highest index) positional
593                 debug!("Parser::get_matches_with: .last(true) and --, setting last pos");
594                 pos_counter = self
595                     .app
596                     .args
597                     .keys
598                     .iter()
599                     .filter(|x| x.key.is_position())
600                     .count();
601             }
602 
603             if let Some(p) = self
604                 .app
605                 .args
606                 .args
607                 .iter()
608                 .find(|a| a.is_positional() && a.index == Some(pos_counter as u64))
609             {
610                 if p.is_set(ArgSettings::Last) && !self.is_set(AS::TrailingValues) {
611                     return Err(ClapError::unknown_argument(
612                         arg_os.to_string_lossy().to_string(),
613                         None,
614                         Usage::new(self).create_usage_with_title(&[]),
615                         self.app.color(),
616                     ));
617                 }
618 
619                 if !self.is_set(AS::TrailingValues)
620                     && (self.is_set(AS::TrailingVarArg)
621                         && pos_counter
622                             == self
623                                 .app
624                                 .args
625                                 .keys
626                                 .iter()
627                                 .filter(|x| x.key.is_position())
628                                 .count())
629                 {
630                     self.app.settings.set(AS::TrailingValues);
631                 }
632 
633                 self.seen.push(p.id.clone());
634                 self.add_val_to_arg(p, &arg_os, matcher, ValueType::CommandLine)?;
635 
636                 matcher.inc_occurrence_of(&p.id);
637                 for grp in self.app.groups_for_arg(&p.id) {
638                     matcher.inc_occurrence_of(&grp);
639                 }
640 
641                 self.app.settings.set(AS::ValidArgFound);
642                 // Only increment the positional counter if it doesn't allow multiples
643                 if !p.settings.is_set(ArgSettings::MultipleValues) {
644                     pos_counter += 1;
645                 }
646                 self.app.settings.set(AS::ValidArgFound);
647             } else if self.is_set(AS::AllowExternalSubcommands) {
648                 // Get external subcommand name
649                 let sc_name = match arg_os.to_str() {
650                     Some(s) => s.to_string(),
651                     None => {
652                         if !self.is_set(AS::StrictUtf8) {
653                             return Err(ClapError::invalid_utf8(
654                                 Usage::new(self).create_usage_with_title(&[]),
655                                 self.app.color(),
656                             ));
657                         }
658                         arg_os.to_string_lossy().into_owned()
659                     }
660                 };
661 
662                 // Collect the external subcommand args
663                 let mut sc_m = ArgMatcher::default();
664 
665                 while let Some((v, _)) = it.next(None) {
666                     if v.to_str().is_none() && !self.is_set(AS::StrictUtf8) {
667                         return Err(ClapError::invalid_utf8(
668                             Usage::new(self).create_usage_with_title(&[]),
669                             self.app.color(),
670                         ));
671                     }
672                     sc_m.add_val_to(&Id::empty_hash(), v.to_os_string(), ValueType::CommandLine);
673                 }
674 
675                 matcher.subcommand(SubCommand {
676                     name: sc_name.clone(),
677                     id: sc_name.into(),
678                     matches: sc_m.into_inner(),
679                 });
680 
681                 external_subcommand = true;
682 
683                 break;
684             } else if !((self.is_set(AS::AllowLeadingHyphen)
685                 || self.is_set(AS::AllowNegativeNumbers))
686                 && arg_os.starts_with("-"))
687                 && !self.is_set(AS::InferSubcommands)
688             {
689                 return Err(ClapError::unknown_argument(
690                     arg_os.to_string_lossy().to_string(),
691                     None,
692                     Usage::new(self).create_usage_with_title(&[]),
693                     self.app.color(),
694                 ));
695             } else if !has_args || self.is_set(AS::InferSubcommands) && self.has_subcommands() {
696                 let cands = suggestions::did_you_mean(
697                     &*arg_os.to_string_lossy(),
698                     self.app.all_subcommand_names(),
699                 );
700                 if !cands.is_empty() {
701                     let cands: Vec<_> = cands.iter().map(|cand| format!("'{}'", cand)).collect();
702                     return Err(ClapError::invalid_subcommand(
703                         arg_os.to_string_lossy().to_string(),
704                         cands.join(" or "),
705                         self.app
706                             .bin_name
707                             .as_ref()
708                             .unwrap_or(&self.app.name)
709                             .to_string(),
710                         Usage::new(self).create_usage_with_title(&[]),
711                         self.app.color(),
712                     ));
713                 } else {
714                     return Err(ClapError::unrecognized_subcommand(
715                         arg_os.to_string_lossy().to_string(),
716                         self.app
717                             .bin_name
718                             .as_ref()
719                             .unwrap_or(&self.app.name)
720                             .to_string(),
721                         self.app.color(),
722                     ));
723                 }
724             } else {
725                 return Err(ClapError::unknown_argument(
726                     arg_os.to_string_lossy().to_string(),
727                     None,
728                     Usage::new(self).create_usage_with_title(&[]),
729                     self.app.color(),
730                 ));
731             }
732         }
733 
734         if !external_subcommand {
735             if let Some(ref pos_sc_name) = subcmd_name {
736                 let sc_name = self
737                     .app
738                     .find_subcommand(pos_sc_name)
739                     .expect(INTERNAL_ERROR_MSG)
740                     .name
741                     .clone();
742                 self.parse_subcommand(&sc_name, matcher, it, keep_state)?;
743             } else if self.is_set(AS::SubcommandRequired) {
744                 let bn = self.app.bin_name.as_ref().unwrap_or(&self.app.name);
745                 return Err(ClapError::missing_subcommand(
746                     bn.to_string(),
747                     Usage::new(self).create_usage_with_title(&[]),
748                     self.app.color(),
749                 ));
750             } else if self.is_set(AS::SubcommandRequiredElseHelp) {
751                 debug!("Parser::get_matches_with: SubcommandRequiredElseHelp=true");
752                 let message = self.write_help_err()?;
753                 return Err(ClapError {
754                     message,
755                     kind: ErrorKind::MissingArgumentOrSubcommand,
756                     info: vec![],
757                 });
758             }
759         }
760 
761         self.remove_overrides(matcher);
762 
763         Validator::new(self).validate(needs_val_of, subcmd_name.is_some(), matcher)
764     }
765 
766     // Should we color the help?
color_help(&self) -> ColorChoice767     pub(crate) fn color_help(&self) -> ColorChoice {
768         debug!("Parser::color_help");
769 
770         if self.is_set(AS::ColoredHelp) {
771             self.app.color()
772         } else {
773             ColorChoice::Never
774         }
775     }
776 
777     // HACK:
778     // When we have a group that is NOT multiple AND has both
779     // an option and a positional arg, only one of them must be passed.
780     //
781     // The problem here is that clap decides which positional arg it's looking at
782     // (the one from group or the following one) based on the counter that is incremented
783     // every time clap stores a positional arg.
784     //
785     // When a non positional option is passed, this counter is not incremented.
786     // In other words, the group has already been "occupied" by the option, but the
787     // counter still points to the positional argument that belongs to this group.
788     // If the option is followed by yet another positional arg, it will land in
789     // the group, erroneously.
790     //
791     // This is a pretty much fundamental problem with the current parsing algorithm
792     // and the function below is simply a hack that solves the problem at hand,
793     // but it does so at cost of minor regression in error messages (see tests/groups.rs).
794     //
795     // In order to resolve it properly, we need to rewrite the parser entirely.
796     // I don't really feel like it right now, sorry.
797     // The parser is big and scary and full of legacy.
maybe_inc_pos_counter(&self, pos_counter: &mut usize, id: &Id)798     fn maybe_inc_pos_counter(&self, pos_counter: &mut usize, id: &Id) {
799         debug!("Parser::maybe_inc_pos_counter: arg = {:?}", id);
800 
801         let arg = &self.app[id];
802 
803         debug!("Parser::maybe_inc_pos_counter: is it positional?");
804         // will be incremented by other means.
805         if arg.is_positional() {
806             debug!("Yes");
807             return;
808         }
809         debug!("No");
810 
811         for group in self.app.groups_for_arg(&arg.id) {
812             debug!("Parser::maybe_inc_pos_counter: group={:?}", group);
813             let group = self.app.groups.iter().find(|g| g.id == group);
814 
815             debug!("Parser::maybe_inc_pos_counter: Checking args in the group...");
816             if let Some(group) = group {
817                 for arg in group.args.iter() {
818                     debug!("Parser::maybe_inc_pos_counter: arg={:?}", arg);
819                     if self.app[arg].is_positional() {
820                         debug!("Parser::maybe_inc_pos_counter: Incrementing counter!");
821                         *pos_counter += 1;
822                     }
823                 }
824             }
825         }
826     }
827 
828     // Checks if the arg matches a subcommand name, or any of its aliases (if defined)
possible_subcommand(&self, arg_os: &ArgStr) -> Option<&str>829     fn possible_subcommand(&self, arg_os: &ArgStr) -> Option<&str> {
830         debug!("Parser::possible_subcommand: arg={:?}", arg_os);
831 
832         if self.is_set(AS::ArgsNegateSubcommands) && self.is_set(AS::ValidArgFound) {
833             return None;
834         }
835 
836         if self.is_set(AS::InferSubcommands) {
837             let v = self
838                 .app
839                 .all_subcommand_names()
840                 .filter(|s| arg_os.is_prefix_of(s))
841                 .collect::<Vec<_>>();
842 
843             if v.len() == 1 {
844                 return Some(v[0]);
845             }
846 
847             for sc in &v {
848                 if sc == arg_os {
849                     return Some(sc);
850                 }
851             }
852         } else if let Some(sc) = self.app.find_subcommand(arg_os) {
853             return Some(&sc.name);
854         }
855 
856         None
857     }
858 
859     // Checks if the arg matches a long flag subcommand name, or any of its aliases (if defined)
possible_long_flag_subcommand(&self, arg_os: &ArgStr) -> Option<&str>860     fn possible_long_flag_subcommand(&self, arg_os: &ArgStr) -> Option<&str> {
861         debug!("Parser::possible_long_flag_subcommand: arg={:?}", arg_os);
862         if self.is_set(AS::InferSubcommands) {
863             let options = self
864                 .app
865                 .get_subcommands()
866                 .fold(Vec::new(), |mut options, sc| {
867                     if let Some(long) = sc.long_flag {
868                         if arg_os.is_prefix_of(long) {
869                             options.push(long);
870                         }
871                         options.extend(
872                             sc.get_all_aliases()
873                                 .filter(|alias| arg_os.is_prefix_of(alias)),
874                         )
875                     }
876                     options
877                 });
878             if options.len() == 1 {
879                 return Some(options[0]);
880             }
881 
882             for sc in &options {
883                 if sc == arg_os {
884                     return Some(sc);
885                 }
886             }
887         } else if let Some(sc_name) = self.app.find_long_subcmd(arg_os) {
888             return Some(sc_name);
889         }
890         None
891     }
892 
parse_help_subcommand(&self, cmds: &[OsString]) -> ClapResult<ParseResult>893     fn parse_help_subcommand(&self, cmds: &[OsString]) -> ClapResult<ParseResult> {
894         debug!("Parser::parse_help_subcommand");
895 
896         let mut help_help = false;
897         let mut bin_name = self.app.bin_name.as_ref().unwrap_or(&self.app.name).clone();
898 
899         let mut sc = {
900             // @TODO @perf: cloning all these Apps isn't great, but since it's just displaying the
901             // help message there are bigger fish to fry
902             let mut sc = self.app.clone();
903 
904             for (i, cmd) in cmds.iter().enumerate() {
905                 if cmd == OsStr::new("help") {
906                     // cmd help help
907                     help_help = true;
908                     break; // Maybe?
909                 }
910                 if let Some(id) = sc.find_subcommand(cmd).map(|x| x.id.clone()) {
911                     sc._propagate(Propagation::To(id));
912                 }
913 
914                 if let Some(mut c) = sc.find_subcommand(cmd).cloned() {
915                     c._build();
916                     sc = c;
917 
918                     if i == cmds.len() - 1 {
919                         break;
920                     }
921                 } else if let Some(mut c) = sc.find_subcommand(&cmd.to_string_lossy()).cloned() {
922                     c._build();
923                     sc = c;
924 
925                     if i == cmds.len() - 1 {
926                         break;
927                     }
928                 } else {
929                     return Err(ClapError::unrecognized_subcommand(
930                         cmd.to_string_lossy().to_string(),
931                         self.app
932                             .bin_name
933                             .as_ref()
934                             .unwrap_or(&self.app.name)
935                             .to_string(),
936                         self.app.color(),
937                     ));
938                 }
939 
940                 bin_name = format!("{} {}", bin_name, &sc.name);
941             }
942 
943             sc
944         };
945 
946         let parser = Parser::new(&mut sc);
947 
948         if help_help {
949             let mut pb = Arg::new("subcommand")
950                 .index(1)
951                 .setting(ArgSettings::MultipleValues)
952                 .about("The subcommand whose help message to display");
953 
954             pb._build();
955             //parser.positionals.insert(1, pb.name);
956             parser.app.settings = parser.app.settings | self.app.g_settings;
957             parser.app.g_settings = self.app.g_settings;
958         }
959 
960         if parser.app.bin_name != self.app.bin_name {
961             parser.app.bin_name = Some(format!("{} {}", bin_name, parser.app.name));
962         }
963 
964         Err(parser.help_err(false))
965     }
966 
is_new_arg(&mut self, arg_os: &ArgStr, needs_val_of: &ParseResult) -> bool967     fn is_new_arg(&mut self, arg_os: &ArgStr, needs_val_of: &ParseResult) -> bool {
968         debug!("Parser::is_new_arg: {:?}:{:?}", arg_os, needs_val_of);
969 
970         let app_wide_settings = if self.is_set(AS::AllowLeadingHyphen) {
971             true
972         } else if self.is_set(AS::AllowNegativeNumbers) {
973             let a = arg_os.to_string_lossy();
974 
975             if a.parse::<i64>().is_ok() || a.parse::<f64>().is_ok() {
976                 self.set(AS::ValidNegNumFound);
977                 true
978             } else {
979                 false
980             }
981         } else {
982             false
983         };
984 
985         let arg_allows_tac = match needs_val_of {
986             ParseResult::Opt(name) | ParseResult::Pos(name) => {
987                 app_wide_settings || self.app[name].is_set(ArgSettings::AllowHyphenValues)
988             }
989 
990             ParseResult::ValuesDone(..) => return true,
991             _ => false,
992         };
993 
994         debug!("Parser::is_new_arg: arg_allows_tac={:?}", arg_allows_tac);
995 
996         // Is this a new argument, or values from a previous option?
997         let mut ret = if arg_os.starts_with("--") {
998             debug!("Parser::is_new_arg: -- found");
999 
1000             if arg_os.len() == 2 && !arg_allows_tac {
1001                 return true; // We have to return true so override everything else
1002             } else if arg_allows_tac {
1003                 return false;
1004             }
1005 
1006             true
1007         } else if arg_os.starts_with("-") {
1008             debug!("Parser::is_new_arg: - found");
1009             // a singe '-' by itself is a value and typically means "stdin" on unix systems
1010             arg_os.len() != 1
1011         } else {
1012             debug!("Parser::is_new_arg: probably value");
1013             false
1014         };
1015 
1016         ret = ret && !arg_allows_tac;
1017 
1018         debug!("Parser::is_new_arg: starts_new_arg={:?}", ret);
1019         ret
1020     }
1021 
parse_subcommand( &mut self, sc_name: &str, matcher: &mut ArgMatcher, it: &mut Input, keep_state: bool, ) -> ClapResult<()>1022     fn parse_subcommand(
1023         &mut self,
1024         sc_name: &str,
1025         matcher: &mut ArgMatcher,
1026         it: &mut Input,
1027         keep_state: bool,
1028     ) -> ClapResult<()> {
1029         use std::fmt::Write;
1030 
1031         debug!("Parser::parse_subcommand");
1032 
1033         let mut mid_string = String::new();
1034 
1035         if !self.is_set(AS::SubcommandsNegateReqs) {
1036             let reqs = Usage::new(self).get_required_usage_from(&[], None, true); // maybe Some(m)
1037 
1038             for s in &reqs {
1039                 write!(&mut mid_string, " {}", s).expect(INTERNAL_ERROR_MSG);
1040             }
1041         }
1042 
1043         mid_string.push_str(" ");
1044 
1045         if let Some(x) = self.app.find_subcommand(sc_name) {
1046             let id = x.id.clone();
1047             self.app._propagate(Propagation::To(id));
1048         }
1049 
1050         if let Some(sc) = self.app.subcommands.iter_mut().find(|s| s.name == sc_name) {
1051             let mut sc_matcher = ArgMatcher::default();
1052             // Display subcommand name, short and long in usage
1053             let mut sc_names = sc.name.clone();
1054             let mut flag_subcmd = false;
1055             if let Some(l) = sc.long_flag {
1056                 sc_names.push_str(&format!(", --{}", l));
1057                 flag_subcmd = true;
1058             }
1059             if let Some(s) = sc.short_flag {
1060                 sc_names.push_str(&format!(", -{}", s));
1061                 flag_subcmd = true;
1062             }
1063 
1064             if flag_subcmd {
1065                 sc_names = format!("{{{}}}", sc_names);
1066             }
1067 
1068             sc.usage = Some(format!(
1069                 "{}{}{}",
1070                 self.app.bin_name.as_ref().unwrap_or(&String::new()),
1071                 if self.app.bin_name.is_some() {
1072                     &*mid_string
1073                 } else {
1074                     ""
1075                 },
1076                 sc_names
1077             ));
1078 
1079             // bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by
1080             // a space
1081             sc.bin_name = Some(format!(
1082                 "{}{}{}",
1083                 self.app.bin_name.as_ref().unwrap_or(&String::new()),
1084                 if self.app.bin_name.is_some() { " " } else { "" },
1085                 &*sc.name
1086             ));
1087 
1088             // Ensure all args are built and ready to parse
1089             sc._build();
1090 
1091             debug!("Parser::parse_subcommand: About to parse sc={}", sc.name);
1092 
1093             {
1094                 let mut p = Parser::new(sc);
1095                 // HACK: maintain indexes between parsers
1096                 // FlagSubCommand short arg needs to revist the current short args, but skip the subcommand itself
1097                 if keep_state {
1098                     p.cur_idx.set(self.cur_idx.get());
1099                     p.skip_idxs = self.skip_idxs;
1100                 }
1101                 p.get_matches_with(&mut sc_matcher, it)?;
1102             }
1103             let name = &sc.name;
1104             matcher.subcommand(SubCommand {
1105                 id: Id::from_ref(&*name), // @TODO @maybe: should be sc.id?
1106                 name: name.to_string(),
1107                 matches: sc_matcher.into_inner(),
1108             });
1109         }
1110         Ok(())
1111     }
1112 
1113     // Retrieves the names of all args the user has supplied thus far, except required ones
1114     // because those will be listed in self.required
check_for_help_and_version_str(&self, arg: &ArgStr) -> ClapResult<()>1115     fn check_for_help_and_version_str(&self, arg: &ArgStr) -> ClapResult<()> {
1116         debug!("Parser::check_for_help_and_version_str");
1117         debug!(
1118             "Parser::check_for_help_and_version_str: Checking if --{:?} is help or version...",
1119             arg
1120         );
1121 
1122         // Needs to use app.settings.is_set instead of just is_set() because is_set() checks
1123         // both global and local settings, we only want to check local
1124         if arg == "help" && !self.app.settings.is_set(AS::NoAutoHelp) {
1125             debug!("Help");
1126             return Err(self.help_err(true));
1127         }
1128         if arg == "version" && !self.app.settings.is_set(AS::NoAutoVersion) {
1129             debug!("Version");
1130             return Err(self.version_err(true));
1131         }
1132         debug!("Neither");
1133 
1134         Ok(())
1135     }
1136 
check_for_help_and_version_char(&self, arg: char) -> ClapResult<()>1137     fn check_for_help_and_version_char(&self, arg: char) -> ClapResult<()> {
1138         debug!("Parser::check_for_help_and_version_char");
1139         debug!(
1140             "Parser::check_for_help_and_version_char: Checking if -{} is help or version...",
1141             arg
1142         );
1143         // Needs to use app.settings.is_set instead of just is_set() because is_set() checks
1144         // both global and local settings, we only want to check local
1145         if let Some(help) = self.app.find(&Id::help_hash()) {
1146             if let Some(h) = help.short {
1147                 if arg == h && !self.app.settings.is_set(AS::NoAutoHelp) {
1148                     debug!("Help");
1149                     return Err(self.help_err(false));
1150                 }
1151             }
1152         }
1153         if let Some(version) = self.app.find(&Id::version_hash()) {
1154             if let Some(v) = version.short {
1155                 if arg == v && !self.app.settings.is_set(AS::NoAutoVersion) {
1156                     debug!("Version");
1157                     return Err(self.version_err(false));
1158                 }
1159             }
1160         }
1161         debug!("Neither");
1162         Ok(())
1163     }
1164 
use_long_help(&self) -> bool1165     fn use_long_help(&self) -> bool {
1166         debug!("Parser::use_long_help");
1167         // In this case, both must be checked. This allows the retention of
1168         // original formatting, but also ensures that the actual -h or --help
1169         // specified by the user is sent through. If HiddenShortHelp is not included,
1170         // then items specified with hidden_short_help will also be hidden.
1171         let should_long = |v: &Arg| {
1172             v.long_about.is_some()
1173                 || v.is_set(ArgSettings::HiddenLongHelp)
1174                 || v.is_set(ArgSettings::HiddenShortHelp)
1175         };
1176 
1177         self.app.long_about.is_some()
1178             || self.app.before_long_help.is_some()
1179             || self.app.after_long_help.is_some()
1180             || self.app.args.args.iter().any(should_long)
1181             || self.app.subcommands.iter().any(|s| s.long_about.is_some())
1182     }
1183 
parse_long_arg( &mut self, matcher: &mut ArgMatcher, full_arg: &ArgStr, ) -> ClapResult<ParseResult>1184     fn parse_long_arg(
1185         &mut self,
1186         matcher: &mut ArgMatcher,
1187         full_arg: &ArgStr,
1188     ) -> ClapResult<ParseResult> {
1189         // maybe here lifetime should be 'a
1190         debug!("Parser::parse_long_arg");
1191 
1192         // Update the curent index
1193         self.cur_idx.set(self.cur_idx.get() + 1);
1194 
1195         let mut val = None;
1196         debug!("Parser::parse_long_arg: Does it contain '='...");
1197         let matches;
1198         let arg = if full_arg.contains_byte(b'=') {
1199             matches = full_arg.trim_start_matches(b'-');
1200             let (p0, p1) = matches.split_at_byte(b'=');
1201             debug!("Yes '{:?}'", p1);
1202             val = Some(p1);
1203             p0
1204         } else {
1205             debug!("No");
1206             full_arg.trim_start_matches(b'-')
1207         };
1208         if let Some(opt) = self.app.args.get(&KeyType::Long(arg.to_os_string())) {
1209             debug!(
1210                 "Parser::parse_long_arg: Found valid opt or flag '{}'",
1211                 opt.to_string()
1212             );
1213             self.app.settings.set(AS::ValidArgFound);
1214 
1215             self.seen.push(opt.id.clone());
1216 
1217             if opt.is_set(ArgSettings::TakesValue) {
1218                 return Ok(self.parse_opt(&val, opt, val.is_some(), matcher)?);
1219             }
1220             self.check_for_help_and_version_str(&arg)?;
1221             self.parse_flag(opt, matcher)?;
1222 
1223             return Ok(ParseResult::Flag(opt.id.clone()));
1224         } else if let Some(sc_name) = self.possible_long_flag_subcommand(&arg) {
1225             return Ok(ParseResult::FlagSubCommand(sc_name.to_string()));
1226         } else if self.is_set(AS::AllowLeadingHyphen) {
1227             return Ok(ParseResult::MaybeHyphenValue);
1228         } else if self.is_set(AS::ValidNegNumFound) {
1229             return Ok(ParseResult::MaybeNegNum);
1230         }
1231 
1232         debug!("Parser::parse_long_arg: Didn't match anything");
1233         self.did_you_mean_error(arg.to_str().expect(INVALID_UTF8), matcher)
1234             .map(|_| ParseResult::NotFound)
1235     }
1236 
parse_short_arg( &mut self, matcher: &mut ArgMatcher, full_arg: &ArgStr, ) -> ClapResult<ParseResult>1237     fn parse_short_arg(
1238         &mut self,
1239         matcher: &mut ArgMatcher,
1240         full_arg: &ArgStr,
1241     ) -> ClapResult<ParseResult> {
1242         debug!("Parser::parse_short_arg: full_arg={:?}", full_arg);
1243         let arg_os = full_arg.trim_start_matches(b'-');
1244         let arg = arg_os.to_string_lossy();
1245 
1246         // If AllowLeadingHyphen is set, we want to ensure `-val` gets parsed as `-val` and not
1247         // `-v` `-a` `-l` assuming `v` `a` and `l` are all, or mostly, valid shorts.
1248         if self.is_set(AS::AllowLeadingHyphen) {
1249             if arg.chars().any(|c| !self.contains_short(c)) {
1250                 debug!(
1251                     "Parser::parse_short_arg: LeadingHyphenAllowed yet -{} isn't valid",
1252                     arg
1253                 );
1254                 return Ok(ParseResult::MaybeHyphenValue);
1255             }
1256         } else if self.is_set(AS::ValidNegNumFound) {
1257             // TODO: Add docs about having AllowNegativeNumbers and `-2` as a valid short
1258             // May be better to move this to *after* not finding a valid flag/opt?
1259             debug!("Parser::parse_short_arg: Valid negative num...");
1260             return Ok(ParseResult::MaybeNegNum);
1261         }
1262 
1263         let mut ret = ParseResult::NotFound;
1264         let skip = self.skip_idxs;
1265         self.skip_idxs = 0;
1266         for c in arg.chars().skip(skip) {
1267             debug!("Parser::parse_short_arg:iter:{}", c);
1268 
1269             // update each index because `-abcd` is four indices to clap
1270             self.cur_idx.set(self.cur_idx.get() + 1);
1271 
1272             // Check for matching short options, and return the name if there is no trailing
1273             // concatenated value: -oval
1274             // Option: -o
1275             // Value: val
1276             if let Some(opt) = self.app.args.get(&KeyType::Short(c)) {
1277                 debug!(
1278                     "Parser::parse_short_arg:iter:{}: Found valid opt or flag",
1279                     c
1280                 );
1281                 self.app.settings.set(AS::ValidArgFound);
1282                 self.seen.push(opt.id.clone());
1283                 if !opt.is_set(ArgSettings::TakesValue) {
1284                     self.check_for_help_and_version_char(c)?;
1285                     ret = self.parse_flag(opt, matcher)?;
1286                     continue;
1287                 }
1288 
1289                 // Check for trailing concatenated value
1290                 let i = arg_os.split(c).next().unwrap().len() + c.len_utf8();
1291                 debug!(
1292                     "Parser::parse_short_arg:iter:{}: i={}, arg_os={:?}",
1293                     c, i, arg_os
1294                 );
1295                 let val = if i != arg_os.len() {
1296                     // This is always a valid place to split, because the separator is UTF-8.
1297                     let val = arg_os.split_at_unchecked(i).1;
1298                     debug!(
1299                         "Parser::parse_short_arg:iter:{}: val={:?} (bytes), val={:?} (ascii)",
1300                         c,
1301                         val.as_raw_bytes(),
1302                         val
1303                     );
1304                     Some(val)
1305                 } else {
1306                     None
1307                 };
1308 
1309                 // Default to "we're expecting a value later"
1310                 return self.parse_opt(&val, opt, false, matcher);
1311             } else if let Some(sc_name) = self.app.find_short_subcmd(c) {
1312                 debug!("Parser::parse_short_arg:iter:{}: subcommand={}", c, sc_name);
1313                 let name = sc_name.to_string();
1314                 let done_short_args = self.cur_idx.get() == arg.len();
1315                 return Ok(ParseResult::FlagSubCommandShort(name, done_short_args));
1316             } else {
1317                 let arg = format!("-{}", c);
1318 
1319                 return Err(ClapError::unknown_argument(
1320                     arg,
1321                     None,
1322                     Usage::new(self).create_usage_with_title(&[]),
1323                     self.app.color(),
1324                 ));
1325             }
1326         }
1327         Ok(ret)
1328     }
1329 
parse_opt( &self, val: &Option<ArgStr>, opt: &Arg<'help>, had_eq: bool, matcher: &mut ArgMatcher, ) -> ClapResult<ParseResult>1330     fn parse_opt(
1331         &self,
1332         val: &Option<ArgStr>,
1333         opt: &Arg<'help>,
1334         had_eq: bool,
1335         matcher: &mut ArgMatcher,
1336     ) -> ClapResult<ParseResult> {
1337         debug!("Parser::parse_opt; opt={}, val={:?}", opt.name, val);
1338         debug!("Parser::parse_opt; opt.settings={:?}", opt.settings);
1339         let mut has_eq = false;
1340         let no_val = val.is_none();
1341         let empty_vals = opt.is_set(ArgSettings::AllowEmptyValues);
1342         let min_vals_zero = opt.min_vals.unwrap_or(1) == 0;
1343         let needs_eq = opt.is_set(ArgSettings::RequireEquals);
1344 
1345         debug!("Parser::parse_opt; Checking for val...");
1346         if let Some(fv) = val {
1347             has_eq = fv.starts_with("=") || had_eq;
1348             let v = fv.trim_start_n_matches(1, b'=');
1349             if !empty_vals && (v.is_empty() || (needs_eq && !has_eq)) {
1350                 debug!("Found Empty - Error");
1351                 return Err(ClapError::empty_value(
1352                     opt,
1353                     Usage::new(self).create_usage_with_title(&[]),
1354                     self.app.color(),
1355                 ));
1356             }
1357             debug!("Found - {:?}, len: {}", v, v.len());
1358             debug!(
1359                 "Parser::parse_opt: {:?} contains '='...{:?}",
1360                 fv,
1361                 fv.starts_with("=")
1362             );
1363             self.add_val_to_arg(opt, &v, matcher, ValueType::CommandLine)?;
1364         } else if needs_eq && !(empty_vals || min_vals_zero) {
1365             debug!("None, but requires equals...Error");
1366             return Err(ClapError::empty_value(
1367                 opt,
1368                 Usage::new(self).create_usage_with_title(&[]),
1369                 self.app.color(),
1370             ));
1371         } else if needs_eq && min_vals_zero {
1372             debug!("None and requires equals, but min_vals == 0");
1373             if !opt.default_missing_vals.is_empty() {
1374                 debug!("Parser::parse_opt: has default_missing_vals");
1375                 for val in &opt.default_missing_vals {
1376                     debug!(
1377                         "Parser::parse_opt: adding value from default_missing_values; val = {:?}",
1378                         val
1379                     );
1380                     self.add_val_to_arg(opt, &ArgStr::new(val), matcher, ValueType::CommandLine)?;
1381                 }
1382             };
1383         } else {
1384             debug!("None");
1385         }
1386 
1387         matcher.inc_occurrence_of(&opt.id);
1388         // Increment or create the group "args"
1389         for grp in self.app.groups_for_arg(&opt.id) {
1390             matcher.inc_occurrence_of(&grp);
1391         }
1392 
1393         let needs_delim = opt.is_set(ArgSettings::RequireDelimiter);
1394         let mult = opt.is_set(ArgSettings::MultipleValues);
1395         // @TODO @soundness: if doesn't have an equal, but requires equal is ValuesDone?!
1396         if no_val && min_vals_zero && !has_eq && needs_eq {
1397             debug!("Parser::parse_opt: More arg vals not required...");
1398             return Ok(ParseResult::ValuesDone(opt.id.clone()));
1399         } else if no_val || (mult && !needs_delim) && !has_eq && matcher.needs_more_vals(opt) {
1400             debug!("Parser::parse_opt: More arg vals required...");
1401             return Ok(ParseResult::Opt(opt.id.clone()));
1402         }
1403         debug!("Parser::parse_opt: More arg vals not required...");
1404         Ok(ParseResult::ValuesDone(opt.id.clone()))
1405     }
1406 
add_val_to_arg( &self, arg: &Arg<'help>, val: &ArgStr, matcher: &mut ArgMatcher, ty: ValueType, ) -> ClapResult<ParseResult>1407     fn add_val_to_arg(
1408         &self,
1409         arg: &Arg<'help>,
1410         val: &ArgStr,
1411         matcher: &mut ArgMatcher,
1412         ty: ValueType,
1413     ) -> ClapResult<ParseResult> {
1414         debug!("Parser::add_val_to_arg; arg={}, val={:?}", arg.name, val);
1415         debug!(
1416             "Parser::add_val_to_arg; trailing_vals={:?}, DontDelimTrailingVals={:?}",
1417             self.is_set(AS::TrailingValues),
1418             self.is_set(AS::DontDelimitTrailingValues)
1419         );
1420         if !(self.is_set(AS::TrailingValues) && self.is_set(AS::DontDelimitTrailingValues)) {
1421             if let Some(delim) = arg.val_delim {
1422                 if val.is_empty() {
1423                     Ok(self.add_single_val_to_arg(arg, val, matcher, ty)?)
1424                 } else {
1425                     let mut iret = ParseResult::ValuesDone(arg.id.clone());
1426                     for v in val.split(delim) {
1427                         iret = self.add_single_val_to_arg(arg, &v, matcher, ty)?;
1428                     }
1429                     // If there was a delimiter used, we're not looking for more values
1430                     if val.contains_char(delim) || arg.is_set(ArgSettings::RequireDelimiter) {
1431                         iret = ParseResult::ValuesDone(arg.id.clone());
1432                     }
1433                     Ok(iret)
1434                 }
1435             } else {
1436                 self.add_single_val_to_arg(arg, val, matcher, ty)
1437             }
1438         } else {
1439             self.add_single_val_to_arg(arg, val, matcher, ty)
1440         }
1441     }
1442 
add_single_val_to_arg( &self, arg: &Arg<'help>, v: &ArgStr, matcher: &mut ArgMatcher, ty: ValueType, ) -> ClapResult<ParseResult>1443     fn add_single_val_to_arg(
1444         &self,
1445         arg: &Arg<'help>,
1446         v: &ArgStr,
1447         matcher: &mut ArgMatcher,
1448         ty: ValueType,
1449     ) -> ClapResult<ParseResult> {
1450         debug!("Parser::add_single_val_to_arg: adding val...{:?}", v);
1451 
1452         // update the current index because each value is a distinct index to clap
1453         self.cur_idx.set(self.cur_idx.get() + 1);
1454 
1455         // @TODO @docs @p4 docs should probably note that terminator doesn't get an index
1456         if let Some(t) = arg.terminator {
1457             if t == v {
1458                 return Ok(ParseResult::ValuesDone(arg.id.clone()));
1459             }
1460         }
1461 
1462         matcher.add_val_to(&arg.id, v.to_os_string(), ty);
1463         matcher.add_index_to(&arg.id, self.cur_idx.get(), ty);
1464 
1465         // Increment or create the group "args"
1466         for grp in self.app.groups_for_arg(&arg.id) {
1467             matcher.add_val_to(&grp, v.to_os_string(), ty);
1468         }
1469 
1470         if matcher.needs_more_vals(arg) {
1471             return Ok(ParseResult::Opt(arg.id.clone()));
1472         }
1473         Ok(ParseResult::ValuesDone(arg.id.clone()))
1474     }
1475 
parse_flag(&self, flag: &Arg<'help>, matcher: &mut ArgMatcher) -> ClapResult<ParseResult>1476     fn parse_flag(&self, flag: &Arg<'help>, matcher: &mut ArgMatcher) -> ClapResult<ParseResult> {
1477         debug!("Parser::parse_flag");
1478 
1479         matcher.inc_occurrence_of(&flag.id);
1480         matcher.add_index_to(&flag.id, self.cur_idx.get(), ValueType::CommandLine);
1481         // Increment or create the group "args"
1482         for grp in self.app.groups_for_arg(&flag.id) {
1483             matcher.inc_occurrence_of(&grp);
1484         }
1485 
1486         Ok(ParseResult::Flag(flag.id.clone()))
1487     }
1488 
remove_overrides(&mut self, matcher: &mut ArgMatcher)1489     fn remove_overrides(&mut self, matcher: &mut ArgMatcher) {
1490         debug!("Parser::remove_overrides");
1491         let mut to_rem: Vec<Id> = Vec::new();
1492         let mut self_override: Vec<Id> = Vec::new();
1493         let mut arg_overrides = Vec::new();
1494         for name in matcher.arg_names() {
1495             debug!("Parser::remove_overrides:iter:{:?}", name);
1496             if let Some(arg) = self.app.find(name) {
1497                 let mut handle_self_override = |o: &Id| {
1498                     if (arg.is_set(ArgSettings::MultipleValues)
1499                         || arg.is_set(ArgSettings::MultipleOccurrences))
1500                         || !arg.has_switch()
1501                     {
1502                         return true;
1503                     }
1504                     debug!(
1505                         "Parser::remove_overrides:iter:{:?}:iter:{:?}: self override",
1506                         name, o
1507                     );
1508                     self_override.push(o.clone());
1509                     false
1510                 };
1511                 for o in &arg.overrides {
1512                     debug!("Parser::remove_overrides:iter:{:?} => {:?}", name, o);
1513                     if *o == arg.id {
1514                         if handle_self_override(o) {
1515                             continue;
1516                         }
1517                     } else {
1518                         arg_overrides.push((arg.id.clone(), o));
1519                         arg_overrides.push((o.clone(), &arg.id));
1520                     }
1521                 }
1522                 if self.is_set(AS::AllArgsOverrideSelf) {
1523                     let _ = handle_self_override(&arg.id);
1524                 }
1525             }
1526         }
1527 
1528         // remove future overrides in reverse seen order
1529         for arg in self.seen.iter().rev() {
1530             for (a, overr) in arg_overrides.iter().filter(|(a, _)| a == arg) {
1531                 if !to_rem.contains(&a) {
1532                     to_rem.push((*overr).clone());
1533                 }
1534             }
1535         }
1536 
1537         // Do self overrides
1538         for name in &self_override {
1539             debug!("Parser::remove_overrides:iter:self:{:?}: resetting", name);
1540             if let Some(ma) = matcher.get_mut(name) {
1541                 if ma.occurs < 2 {
1542                     continue;
1543                 }
1544                 ma.occurs = 1;
1545 
1546                 let len = ma.vals.len().saturating_sub(1);
1547                 ma.vals.drain(0..len);
1548             }
1549         }
1550 
1551         // Finally remove conflicts
1552         for name in &to_rem {
1553             debug!("Parser::remove_overrides:iter:{:?}: removing", name);
1554             matcher.remove(name);
1555             self.overridden.push(name.clone());
1556         }
1557     }
1558 
add_defaults(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()>1559     pub(crate) fn add_defaults(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1560         debug!("Parser::add_defaults");
1561 
1562         for o in self.app.get_opts_with_no_heading() {
1563             debug!("Parser::add_defaults:iter:{}:", o.name);
1564             self.add_value(o, matcher, ValueType::DefaultValue)?;
1565         }
1566 
1567         for p in self.app.get_positionals() {
1568             debug!("Parser::add_defaults:iter:{}:", p.name);
1569             self.add_value(p, matcher, ValueType::DefaultValue)?;
1570         }
1571 
1572         Ok(())
1573     }
1574 
add_value( &self, arg: &Arg<'help>, matcher: &mut ArgMatcher, ty: ValueType, ) -> ClapResult<()>1575     fn add_value(
1576         &self,
1577         arg: &Arg<'help>,
1578         matcher: &mut ArgMatcher,
1579         ty: ValueType,
1580     ) -> ClapResult<()> {
1581         if !arg.default_vals_ifs.is_empty() {
1582             debug!("Parser::add_value: has conditional defaults");
1583 
1584             let mut done = false;
1585             if matcher.get(&arg.id).is_none() {
1586                 for (id, val, default) in arg.default_vals_ifs.values() {
1587                     let add = if let Some(a) = matcher.get(&id) {
1588                         if let Some(v) = val {
1589                             a.vals.iter().any(|value| v == value)
1590                         } else {
1591                             true
1592                         }
1593                     } else {
1594                         false
1595                     };
1596 
1597                     if add {
1598                         self.add_val_to_arg(arg, &ArgStr::new(default), matcher, ty)?;
1599                         done = true;
1600                         break;
1601                     }
1602                 }
1603             }
1604 
1605             if done {
1606                 return Ok(());
1607             }
1608         } else {
1609             debug!("Parser::add_value: doesn't have conditional defaults");
1610         }
1611 
1612         if !arg.default_vals.is_empty() {
1613             debug!("Parser::add_value:iter:{}: has default vals", arg.name);
1614             if matcher
1615                 .get(&arg.id)
1616                 .map(|ma| ma.vals.len())
1617                 .map(|len| len == 0)
1618                 .unwrap_or(false)
1619             {
1620                 debug!(
1621                     "Parser::add_value:iter:{}: has no user defined vals",
1622                     arg.name
1623                 );
1624 
1625                 for val in &arg.default_vals {
1626                     self.add_val_to_arg(arg, &ArgStr::new(val), matcher, ty)?;
1627                 }
1628             } else if matcher.get(&arg.id).is_some() {
1629                 debug!("Parser::add_value:iter:{}: has user defined vals", arg.name);
1630 
1631             // do nothing
1632             } else {
1633                 debug!("Parser::add_value:iter:{}: wasn't used", arg.name);
1634 
1635                 for val in &arg.default_vals {
1636                     self.add_val_to_arg(arg, &ArgStr::new(val), matcher, ty)?;
1637                 }
1638             }
1639         } else {
1640             debug!(
1641                 "Parser::add_value:iter:{}: doesn't have default vals",
1642                 arg.name
1643             );
1644 
1645             // do nothing
1646         }
1647 
1648         Ok(())
1649     }
1650 
add_env(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()>1651     pub(crate) fn add_env(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1652         for a in self.app.args.args.iter() {
1653             // Use env only if the arg was not present among command line args
1654             if matcher.get(&a.id).map_or(true, |a| a.occurs == 0) {
1655                 if let Some(ref val) = a.env {
1656                     if let Some(ref val) = val.1 {
1657                         self.add_val_to_arg(a, &ArgStr::new(val), matcher, ValueType::EnvVariable)?;
1658                     }
1659                 }
1660             }
1661         }
1662         Ok(())
1663     }
1664 }
1665 
1666 // Error, Help, and Version Methods
1667 impl<'help, 'app> Parser<'help, 'app> {
did_you_mean_error(&mut self, arg: &str, matcher: &mut ArgMatcher) -> ClapResult<()>1668     fn did_you_mean_error(&mut self, arg: &str, matcher: &mut ArgMatcher) -> ClapResult<()> {
1669         debug!("Parser::did_you_mean_error: arg={}", arg);
1670         // Didn't match a flag or option
1671         let longs = self
1672             .app
1673             .args
1674             .keys
1675             .iter()
1676             .map(|x| &x.key)
1677             .filter_map(|x| match x {
1678                 KeyType::Long(l) => Some(l.to_string_lossy().into_owned()),
1679                 _ => None,
1680             })
1681             .collect::<Vec<_>>();
1682         debug!("Parser::did_you_mean_error: longs={:?}", longs);
1683 
1684         let did_you_mean = suggestions::did_you_mean_flag(
1685             arg,
1686             longs.iter().map(|ref x| &x[..]),
1687             self.app.subcommands.as_mut_slice(),
1688         );
1689 
1690         // Add the arg to the matches to build a proper usage string
1691         if let Some(ref name) = did_you_mean {
1692             if let Some(opt) = self
1693                 .app
1694                 .args
1695                 .get(&KeyType::Long(OsString::from(name.0.clone())))
1696             {
1697                 for g in self.app.groups_for_arg(&opt.id) {
1698                     matcher.inc_occurrence_of(&g);
1699                 }
1700                 matcher.insert(&opt.id);
1701             }
1702         }
1703 
1704         let used: Vec<Id> = matcher
1705             .arg_names()
1706             .filter(|n| {
1707                 self.app.find(n).map_or(true, |a| {
1708                     !(self.required.contains(&a.id) || a.is_set(ArgSettings::Hidden))
1709                 })
1710             })
1711             .cloned()
1712             .collect();
1713 
1714         Err(ClapError::unknown_argument(
1715             format!("--{}", arg),
1716             did_you_mean,
1717             Usage::new(self).create_usage_with_title(&*used),
1718             self.app.color(),
1719         ))
1720     }
1721 
write_help_err(&self) -> ClapResult<Colorizer>1722     pub(crate) fn write_help_err(&self) -> ClapResult<Colorizer> {
1723         let mut c = Colorizer::new(true, self.color_help());
1724         Help::new(HelpWriter::Buffer(&mut c), self, false).write_help()?;
1725         Ok(c)
1726     }
1727 
help_err(&self, mut use_long: bool) -> ClapError1728     fn help_err(&self, mut use_long: bool) -> ClapError {
1729         debug!(
1730             "Parser::help_err: use_long={:?}",
1731             use_long && self.use_long_help()
1732         );
1733 
1734         use_long = use_long && self.use_long_help();
1735         let mut c = Colorizer::new(false, self.color_help());
1736 
1737         match Help::new(HelpWriter::Buffer(&mut c), self, use_long).write_help() {
1738             Err(e) => e.into(),
1739             _ => ClapError {
1740                 message: c,
1741                 kind: ErrorKind::DisplayHelp,
1742                 info: vec![],
1743             },
1744         }
1745     }
1746 
version_err(&self, use_long: bool) -> ClapError1747     fn version_err(&self, use_long: bool) -> ClapError {
1748         debug!("Parser::version_err");
1749 
1750         let msg = self.app._render_version(use_long);
1751         let mut c = Colorizer::new(false, self.color_help());
1752         c.none(msg);
1753         ClapError {
1754             message: c,
1755             kind: ErrorKind::DisplayVersion,
1756             info: vec![],
1757         }
1758     }
1759 }
1760 
1761 // Query Methods
1762 impl<'help, 'app> Parser<'help, 'app> {
contains_short(&self, s: char) -> bool1763     fn contains_short(&self, s: char) -> bool {
1764         self.app.contains_short(s)
1765     }
1766 
has_args(&self) -> bool1767     pub(crate) fn has_args(&self) -> bool {
1768         self.app.has_args()
1769     }
1770 
has_opts(&self) -> bool1771     pub(crate) fn has_opts(&self) -> bool {
1772         self.app.has_opts()
1773     }
1774 
has_flags(&self) -> bool1775     pub(crate) fn has_flags(&self) -> bool {
1776         self.app.has_flags()
1777     }
1778 
has_positionals(&self) -> bool1779     pub(crate) fn has_positionals(&self) -> bool {
1780         self.app.args.keys.iter().any(|x| x.key.is_position())
1781     }
1782 
has_subcommands(&self) -> bool1783     pub(crate) fn has_subcommands(&self) -> bool {
1784         self.app.has_subcommands()
1785     }
1786 
has_visible_subcommands(&self) -> bool1787     pub(crate) fn has_visible_subcommands(&self) -> bool {
1788         self.app.has_visible_subcommands()
1789     }
1790 
is_set(&self, s: AS) -> bool1791     pub(crate) fn is_set(&self, s: AS) -> bool {
1792         self.app.is_set(s)
1793     }
1794 
set(&mut self, s: AS)1795     pub(crate) fn set(&mut self, s: AS) {
1796         self.app.set(s)
1797     }
1798 
unset(&mut self, s: AS)1799     pub(crate) fn unset(&mut self, s: AS) {
1800         self.app.unset(s)
1801     }
1802 }
1803