• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Std
2 use std::{
3     cell::Cell,
4     ffi::{OsStr, OsString},
5 };
6 
7 // Third Party
8 use clap_lex::RawOsStr;
9 use clap_lex::RawOsString;
10 
11 // Internal
12 use crate::builder::{Arg, Command};
13 use crate::error::Error as ClapError;
14 use crate::error::Result as ClapResult;
15 use crate::mkeymap::KeyType;
16 use crate::output::Usage;
17 use crate::parser::features::suggestions;
18 use crate::parser::AnyValue;
19 use crate::parser::{ArgMatcher, SubCommand};
20 use crate::parser::{Validator, ValueSource};
21 use crate::util::Id;
22 use crate::ArgAction;
23 use crate::INTERNAL_ERROR_MSG;
24 
25 pub(crate) struct Parser<'cmd> {
26     cmd: &'cmd mut Command,
27     cur_idx: Cell<usize>,
28     /// Index of the previous flag subcommand in a group of flags.
29     flag_subcmd_at: Option<usize>,
30     /// Counter indicating the number of items to skip
31     /// when revisiting the group of flags which includes the flag subcommand.
32     flag_subcmd_skip: usize,
33 }
34 
35 // Initializing Methods
36 impl<'cmd> Parser<'cmd> {
new(cmd: &'cmd mut Command) -> Self37     pub(crate) fn new(cmd: &'cmd mut Command) -> Self {
38         Parser {
39             cmd,
40             cur_idx: Cell::new(0),
41             flag_subcmd_at: None,
42             flag_subcmd_skip: 0,
43         }
44     }
45 }
46 
47 // Parsing Methods
48 impl<'cmd> Parser<'cmd> {
49     // The actual parsing function
50     #[allow(clippy::cognitive_complexity)]
get_matches_with( &mut self, matcher: &mut ArgMatcher, raw_args: &mut clap_lex::RawArgs, mut args_cursor: clap_lex::ArgCursor, ) -> ClapResult<()>51     pub(crate) fn get_matches_with(
52         &mut self,
53         matcher: &mut ArgMatcher,
54         raw_args: &mut clap_lex::RawArgs,
55         mut args_cursor: clap_lex::ArgCursor,
56     ) -> ClapResult<()> {
57         debug!("Parser::get_matches_with");
58         // Verify all positional assertions pass
59 
60         let mut subcmd_name: Option<String> = None;
61         let mut keep_state = false;
62         let mut parse_state = ParseState::ValuesDone;
63         let mut pos_counter = 1;
64 
65         // Already met any valid arg(then we shouldn't expect subcommands after it).
66         let mut valid_arg_found = false;
67         // If the user already passed '--'. Meaning only positional args follow.
68         let mut trailing_values = false;
69 
70         // Count of positional args
71         let positional_count = self
72             .cmd
73             .get_keymap()
74             .keys()
75             .filter(|x| x.is_position())
76             .count();
77         // If any arg sets .last(true)
78         let contains_last = self.cmd.get_arguments().any(|x| x.is_last_set());
79 
80         while let Some(arg_os) = raw_args.next(&mut args_cursor) {
81             // Recover the replaced items if any.
82             if let Some(replaced_items) = arg_os
83                 .to_value()
84                 .ok()
85                 .and_then(|a| self.cmd.get_replacement(a))
86             {
87                 debug!(
88                     "Parser::get_matches_with: found replacer: {:?}, target: {:?}",
89                     arg_os, replaced_items
90                 );
91                 raw_args.insert(&args_cursor, replaced_items);
92                 continue;
93             }
94 
95             debug!(
96                 "Parser::get_matches_with: Begin parsing '{:?}' ({:?})",
97                 arg_os.to_value_os(),
98                 arg_os.to_value_os().as_raw_bytes()
99             );
100 
101             // Has the user already passed '--'? Meaning only positional args follow
102             if !trailing_values {
103                 if self.cmd.is_subcommand_precedence_over_arg_set()
104                     || !matches!(parse_state, ParseState::Opt(_) | ParseState::Pos(_))
105                 {
106                     // Does the arg match a subcommand name, or any of its aliases (if defined)
107                     let sc_name = self.possible_subcommand(arg_os.to_value(), valid_arg_found);
108                     debug!("Parser::get_matches_with: sc={:?}", sc_name);
109                     if let Some(sc_name) = sc_name {
110                         if sc_name == "help" && !self.cmd.is_disable_help_subcommand_set() {
111                             ok!(self.parse_help_subcommand(raw_args.remaining(&mut args_cursor)));
112                             unreachable!("`parse_help_subcommand` always errors");
113                         } else {
114                             subcmd_name = Some(sc_name.to_owned());
115                         }
116                         break;
117                     }
118                 }
119 
120                 if arg_os.is_escape() {
121                     if matches!(&parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if
122                         self.cmd[opt].is_allow_hyphen_values_set())
123                     {
124                         // ParseResult::MaybeHyphenValue, do nothing
125                     } else {
126                         debug!("Parser::get_matches_with: setting TrailingVals=true");
127                         trailing_values = true;
128                         matcher.start_trailing();
129                         continue;
130                     }
131                 } else if let Some((long_arg, long_value)) = arg_os.to_long() {
132                     let parse_result = ok!(self.parse_long_arg(
133                         matcher,
134                         long_arg,
135                         long_value,
136                         &parse_state,
137                         pos_counter,
138                         &mut valid_arg_found,
139                     ));
140                     debug!(
141                         "Parser::get_matches_with: After parse_long_arg {:?}",
142                         parse_result
143                     );
144                     match parse_result {
145                         ParseResult::NoArg => {
146                             unreachable!("`to_long` always has the flag specified")
147                         }
148                         ParseResult::ValuesDone => {
149                             parse_state = ParseState::ValuesDone;
150                             continue;
151                         }
152                         ParseResult::Opt(id) => {
153                             parse_state = ParseState::Opt(id);
154                             continue;
155                         }
156                         ParseResult::FlagSubCommand(name) => {
157                             debug!(
158                                 "Parser::get_matches_with: FlagSubCommand found in long arg {:?}",
159                                 &name
160                             );
161                             subcmd_name = Some(name);
162                             break;
163                         }
164                         ParseResult::EqualsNotProvided { arg } => {
165                             let _ = self.resolve_pending(matcher);
166                             return Err(ClapError::no_equals(
167                                 self.cmd,
168                                 arg,
169                                 Usage::new(self.cmd).create_usage_with_title(&[]),
170                             ));
171                         }
172                         ParseResult::NoMatchingArg { arg } => {
173                             let _ = self.resolve_pending(matcher);
174                             let remaining_args: Vec<_> =
175                                 raw_args.remaining(&mut args_cursor).collect();
176                             return Err(self.did_you_mean_error(
177                                 &arg,
178                                 matcher,
179                                 &remaining_args,
180                                 trailing_values,
181                             ));
182                         }
183                         ParseResult::UnneededAttachedValue { rest, used, arg } => {
184                             let _ = self.resolve_pending(matcher);
185                             return Err(ClapError::too_many_values(
186                                 self.cmd,
187                                 rest,
188                                 arg,
189                                 Usage::new(self.cmd).create_usage_with_title(&used),
190                             ));
191                         }
192                         ParseResult::MaybeHyphenValue => {
193                             // Maybe a hyphen value, do nothing.
194                         }
195                         ParseResult::AttachedValueNotConsumed => {
196                             unreachable!()
197                         }
198                     }
199                 } else if let Some(short_arg) = arg_os.to_short() {
200                     // Arg looks like a short flag, and not a possible number
201 
202                     // Try to parse short args like normal, if allow_hyphen_values or
203                     // AllowNegativeNumbers is set, parse_short_arg will *not* throw
204                     // an error, and instead return Ok(None)
205                     let parse_result = ok!(self.parse_short_arg(
206                         matcher,
207                         short_arg,
208                         &parse_state,
209                         pos_counter,
210                         &mut valid_arg_found,
211                     ));
212                     // If it's None, we then check if one of those two AppSettings was set
213                     debug!(
214                         "Parser::get_matches_with: After parse_short_arg {:?}",
215                         parse_result
216                     );
217                     match parse_result {
218                         ParseResult::NoArg => {
219                             // Is a single dash `-`, try positional.
220                         }
221                         ParseResult::ValuesDone => {
222                             parse_state = ParseState::ValuesDone;
223                             continue;
224                         }
225                         ParseResult::Opt(id) => {
226                             parse_state = ParseState::Opt(id);
227                             continue;
228                         }
229                         ParseResult::FlagSubCommand(name) => {
230                             // If there are more short flags to be processed, we should keep the state, and later
231                             // revisit the current group of short flags skipping the subcommand.
232                             keep_state = self
233                                 .flag_subcmd_at
234                                 .map(|at| {
235                                     raw_args
236                                         .seek(&mut args_cursor, clap_lex::SeekFrom::Current(-1));
237                                     // Since we are now saving the current state, the number of flags to skip during state recovery should
238                                     // be the current index (`cur_idx`) minus ONE UNIT TO THE LEFT of the starting position.
239                                     self.flag_subcmd_skip = self.cur_idx.get() - at + 1;
240                                 })
241                                 .is_some();
242 
243                             debug!(
244                                 "Parser::get_matches_with:FlagSubCommandShort: subcmd_name={}, keep_state={}, flag_subcmd_skip={}",
245                                 name,
246                                 keep_state,
247                                 self.flag_subcmd_skip
248                             );
249 
250                             subcmd_name = Some(name);
251                             break;
252                         }
253                         ParseResult::EqualsNotProvided { arg } => {
254                             let _ = self.resolve_pending(matcher);
255                             return Err(ClapError::no_equals(
256                                 self.cmd,
257                                 arg,
258                                 Usage::new(self.cmd).create_usage_with_title(&[]),
259                             ));
260                         }
261                         ParseResult::NoMatchingArg { arg } => {
262                             let _ = self.resolve_pending(matcher);
263                             // We already know it looks like a flag
264                             let suggested_trailing_arg =
265                                 !trailing_values && self.cmd.has_positionals();
266                             return Err(ClapError::unknown_argument(
267                                 self.cmd,
268                                 arg,
269                                 None,
270                                 suggested_trailing_arg,
271                                 Usage::new(self.cmd).create_usage_with_title(&[]),
272                             ));
273                         }
274                         ParseResult::MaybeHyphenValue => {
275                             // Maybe a hyphen value, do nothing.
276                         }
277                         ParseResult::UnneededAttachedValue { .. }
278                         | ParseResult::AttachedValueNotConsumed => unreachable!(),
279                     }
280                 }
281 
282                 if let ParseState::Opt(id) = &parse_state {
283                     // Assume this is a value of a previous arg.
284 
285                     // get the option so we can check the settings
286                     let arg = &self.cmd[id];
287                     let parse_result = if let Some(parse_result) =
288                         self.check_terminator(arg, arg_os.to_value_os())
289                     {
290                         parse_result
291                     } else {
292                         let trailing_values = false;
293                         let arg_values = matcher.pending_values_mut(id, None, trailing_values);
294                         arg_values.push(arg_os.to_value_os().to_os_str().into_owned());
295                         if matcher.needs_more_vals(arg) {
296                             ParseResult::Opt(arg.get_id().clone())
297                         } else {
298                             ParseResult::ValuesDone
299                         }
300                     };
301                     parse_state = match parse_result {
302                         ParseResult::Opt(id) => ParseState::Opt(id),
303                         ParseResult::ValuesDone => ParseState::ValuesDone,
304                         _ => unreachable!(),
305                     };
306                     // get the next value from the iterator
307                     continue;
308                 }
309             }
310 
311             // Correct pos_counter.
312             pos_counter = {
313                 let is_second_to_last = pos_counter + 1 == positional_count;
314 
315                 // The last positional argument, or second to last positional
316                 // argument may be set to .multiple_values(true) or `.multiple_occurrences(true)`
317                 let low_index_mults = is_second_to_last
318                     && self.cmd.get_positionals().any(|a| {
319                         a.is_multiple() && (positional_count != a.get_index().unwrap_or(0))
320                     })
321                     && self
322                         .cmd
323                         .get_positionals()
324                         .last()
325                         .map_or(false, |p_name| !p_name.is_last_set());
326 
327                 let missing_pos = self.cmd.is_allow_missing_positional_set()
328                     && is_second_to_last
329                     && !trailing_values;
330 
331                 debug!(
332                     "Parser::get_matches_with: Positional counter...{}",
333                     pos_counter
334                 );
335                 debug!(
336                     "Parser::get_matches_with: Low index multiples...{:?}",
337                     low_index_mults
338                 );
339 
340                 if low_index_mults || missing_pos {
341                     let skip_current = if let Some(n) = raw_args.peek(&args_cursor) {
342                         if let Some(arg) = self
343                             .cmd
344                             .get_positionals()
345                             .find(|a| a.get_index() == Some(pos_counter))
346                         {
347                             // If next value looks like a new_arg or it's a
348                             // subcommand, skip positional argument under current
349                             // pos_counter(which means current value cannot be a
350                             // positional argument with a value next to it), assume
351                             // current value matches the next arg.
352                             self.is_new_arg(&n, arg)
353                                 || self
354                                     .possible_subcommand(n.to_value(), valid_arg_found)
355                                     .is_some()
356                         } else {
357                             true
358                         }
359                     } else {
360                         true
361                     };
362 
363                     if skip_current {
364                         debug!("Parser::get_matches_with: Bumping the positional counter...");
365                         pos_counter + 1
366                     } else {
367                         pos_counter
368                     }
369                 } else if trailing_values
370                     && (self.cmd.is_allow_missing_positional_set() || contains_last)
371                 {
372                     // Came to -- and one positional has .last(true) set, so we go immediately
373                     // to the last (highest index) positional
374                     debug!("Parser::get_matches_with: .last(true) and --, setting last pos");
375                     positional_count
376                 } else {
377                     pos_counter
378                 }
379             };
380 
381             if let Some(arg) = self.cmd.get_keymap().get(&pos_counter) {
382                 if arg.is_last_set() && !trailing_values {
383                     let _ = self.resolve_pending(matcher);
384                     // Its already considered a positional, we don't need to suggest turning it
385                     // into one
386                     let suggested_trailing_arg = false;
387                     return Err(ClapError::unknown_argument(
388                         self.cmd,
389                         arg_os.display().to_string(),
390                         None,
391                         suggested_trailing_arg,
392                         Usage::new(self.cmd).create_usage_with_title(&[]),
393                     ));
394                 }
395 
396                 if arg.is_trailing_var_arg_set() {
397                     trailing_values = true;
398                 }
399 
400                 if matcher.pending_arg_id() != Some(arg.get_id()) || !arg.is_multiple_values_set() {
401                     ok!(self.resolve_pending(matcher));
402                 }
403                 if let Some(_parse_result) = self.check_terminator(arg, arg_os.to_value_os()) {
404                     debug!(
405                         "Parser::get_matches_with: ignoring terminator result {:?}",
406                         _parse_result
407                     );
408                 } else {
409                     let arg_values = matcher.pending_values_mut(
410                         arg.get_id(),
411                         Some(Identifier::Index),
412                         trailing_values,
413                     );
414                     arg_values.push(arg_os.to_value_os().to_os_str().into_owned());
415                 }
416 
417                 // Only increment the positional counter if it doesn't allow multiples
418                 if !arg.is_multiple() {
419                     pos_counter += 1;
420                     parse_state = ParseState::ValuesDone;
421                 } else {
422                     parse_state = ParseState::Pos(arg.get_id().clone());
423                 }
424                 valid_arg_found = true;
425             } else if let Some(external_parser) =
426                 self.cmd.get_external_subcommand_value_parser().cloned()
427             {
428                 // Get external subcommand name
429                 let sc_name = match arg_os.to_value() {
430                     Ok(s) => s.to_owned(),
431                     Err(_) => {
432                         let _ = self.resolve_pending(matcher);
433                         return Err(ClapError::invalid_utf8(
434                             self.cmd,
435                             Usage::new(self.cmd).create_usage_with_title(&[]),
436                         ));
437                     }
438                 };
439 
440                 // Collect the external subcommand args
441                 let mut sc_m = ArgMatcher::new(self.cmd);
442                 sc_m.start_occurrence_of_external(self.cmd);
443 
444                 for raw_val in raw_args.remaining(&mut args_cursor) {
445                     let val = ok!(external_parser.parse_ref(self.cmd, None, raw_val));
446                     let external_id = Id::from_static_ref(Id::EXTERNAL);
447                     sc_m.add_val_to(&external_id, val, raw_val.to_os_string());
448                 }
449 
450                 matcher.subcommand(SubCommand {
451                     name: sc_name,
452                     matches: sc_m.into_inner(),
453                 });
454 
455                 ok!(self.resolve_pending(matcher));
456                 #[cfg(feature = "env")]
457                 ok!(self.add_env(matcher));
458                 ok!(self.add_defaults(matcher));
459                 return Validator::new(self.cmd).validate(parse_state, matcher);
460             } else {
461                 // Start error processing
462                 let _ = self.resolve_pending(matcher);
463                 return Err(self.match_arg_error(&arg_os, valid_arg_found, trailing_values));
464             }
465         }
466 
467         if let Some(ref pos_sc_name) = subcmd_name {
468             let sc_name = self
469                 .cmd
470                 .find_subcommand(pos_sc_name)
471                 .expect(INTERNAL_ERROR_MSG)
472                 .get_name()
473                 .to_owned();
474             ok!(self.parse_subcommand(&sc_name, matcher, raw_args, args_cursor, keep_state));
475         }
476 
477         ok!(self.resolve_pending(matcher));
478         #[cfg(feature = "env")]
479         ok!(self.add_env(matcher));
480         ok!(self.add_defaults(matcher));
481         Validator::new(self.cmd).validate(parse_state, matcher)
482     }
483 
match_arg_error( &self, arg_os: &clap_lex::ParsedArg<'_>, valid_arg_found: bool, trailing_values: bool, ) -> ClapError484     fn match_arg_error(
485         &self,
486         arg_os: &clap_lex::ParsedArg<'_>,
487         valid_arg_found: bool,
488         trailing_values: bool,
489     ) -> ClapError {
490         // If argument follows a `--`
491         if trailing_values {
492             // If the arg matches a subcommand name, or any of its aliases (if defined)
493             if self
494                 .possible_subcommand(arg_os.to_value(), valid_arg_found)
495                 .is_some()
496             {
497                 return ClapError::unnecessary_double_dash(
498                     self.cmd,
499                     arg_os.display().to_string(),
500                     Usage::new(self.cmd).create_usage_with_title(&[]),
501                 );
502             }
503         }
504 
505         if !(self.cmd.is_args_conflicts_with_subcommands_set() && valid_arg_found) {
506             let candidates = suggestions::did_you_mean(
507                 &arg_os.display().to_string(),
508                 self.cmd.all_subcommand_names(),
509             );
510             // If the argument looks like a subcommand.
511             if !candidates.is_empty() {
512                 return ClapError::invalid_subcommand(
513                     self.cmd,
514                     arg_os.display().to_string(),
515                     candidates,
516                     self.cmd
517                         .get_bin_name()
518                         .unwrap_or_else(|| self.cmd.get_name())
519                         .to_owned(),
520                     Usage::new(self.cmd).create_usage_with_title(&[]),
521                 );
522             }
523 
524             // If the argument must be a subcommand.
525             if self.cmd.has_subcommands()
526                 && (!self.cmd.has_positionals() || self.cmd.is_infer_subcommands_set())
527             {
528                 return ClapError::unrecognized_subcommand(
529                     self.cmd,
530                     arg_os.display().to_string(),
531                     Usage::new(self.cmd).create_usage_with_title(&[]),
532                 );
533             }
534         }
535 
536         let suggested_trailing_arg = !trailing_values
537             && self.cmd.has_positionals()
538             && (arg_os.is_long() || arg_os.is_short());
539         ClapError::unknown_argument(
540             self.cmd,
541             arg_os.display().to_string(),
542             None,
543             suggested_trailing_arg,
544             Usage::new(self.cmd).create_usage_with_title(&[]),
545         )
546     }
547 
548     // Checks if the arg matches a subcommand name, or any of its aliases (if defined)
possible_subcommand( &self, arg: Result<&str, &RawOsStr>, valid_arg_found: bool, ) -> Option<&str>549     fn possible_subcommand(
550         &self,
551         arg: Result<&str, &RawOsStr>,
552         valid_arg_found: bool,
553     ) -> Option<&str> {
554         debug!("Parser::possible_subcommand: arg={:?}", arg);
555         let arg = some!(arg.ok());
556 
557         if !(self.cmd.is_args_conflicts_with_subcommands_set() && valid_arg_found) {
558             if self.cmd.is_infer_subcommands_set() {
559                 // For subcommand `test`, we accepts it's prefix: `t`, `te`,
560                 // `tes` and `test`.
561                 let v = self
562                     .cmd
563                     .all_subcommand_names()
564                     .filter(|s| s.starts_with(arg))
565                     .collect::<Vec<_>>();
566 
567                 if v.len() == 1 {
568                     return Some(v[0]);
569                 }
570 
571                 // If there is any ambiguity, fallback to non-infer subcommand
572                 // search.
573             }
574             if let Some(sc) = self.cmd.find_subcommand(arg) {
575                 return Some(sc.get_name());
576             }
577         }
578         None
579     }
580 
581     // Checks if the arg matches a long flag subcommand name, or any of its aliases (if defined)
possible_long_flag_subcommand(&self, arg: &str) -> Option<&str>582     fn possible_long_flag_subcommand(&self, arg: &str) -> Option<&str> {
583         debug!("Parser::possible_long_flag_subcommand: arg={:?}", arg);
584         if self.cmd.is_infer_subcommands_set() {
585             let options = self
586                 .cmd
587                 .get_subcommands()
588                 .fold(Vec::new(), |mut options, sc| {
589                     if let Some(long) = sc.get_long_flag() {
590                         if long.starts_with(arg) {
591                             options.push(long);
592                         }
593                         options.extend(sc.get_all_aliases().filter(|alias| alias.starts_with(arg)))
594                     }
595                     options
596                 });
597             if options.len() == 1 {
598                 return Some(options[0]);
599             }
600 
601             for sc in options {
602                 if sc == arg {
603                     return Some(sc);
604                 }
605             }
606         } else if let Some(sc_name) = self.cmd.find_long_subcmd(arg) {
607             return Some(sc_name);
608         }
609         None
610     }
611 
parse_help_subcommand( &self, cmds: impl Iterator<Item = &'cmd OsStr>, ) -> ClapResult<std::convert::Infallible>612     fn parse_help_subcommand(
613         &self,
614         cmds: impl Iterator<Item = &'cmd OsStr>,
615     ) -> ClapResult<std::convert::Infallible> {
616         debug!("Parser::parse_help_subcommand");
617 
618         let mut cmd = self.cmd.clone();
619         let sc = {
620             let mut sc = &mut cmd;
621 
622             for cmd in cmds {
623                 sc = if let Some(sc_name) =
624                     sc.find_subcommand(cmd).map(|sc| sc.get_name().to_owned())
625                 {
626                     sc._build_subcommand(&sc_name).unwrap()
627                 } else {
628                     return Err(ClapError::unrecognized_subcommand(
629                         sc,
630                         cmd.to_string_lossy().into_owned(),
631                         Usage::new(sc).create_usage_with_title(&[]),
632                     ));
633                 };
634             }
635 
636             sc
637         };
638         let parser = Parser::new(sc);
639 
640         Err(parser.help_err(true))
641     }
642 
is_new_arg(&self, next: &clap_lex::ParsedArg<'_>, current_positional: &Arg) -> bool643     fn is_new_arg(&self, next: &clap_lex::ParsedArg<'_>, current_positional: &Arg) -> bool {
644         #![allow(clippy::needless_bool)] // Prefer consistent if/else-if ladder
645 
646         debug!(
647             "Parser::is_new_arg: {:?}:{}",
648             next.to_value_os(),
649             current_positional.get_id()
650         );
651 
652         if self.cmd[current_positional.get_id()].is_allow_hyphen_values_set()
653             || (self.cmd[current_positional.get_id()].is_allow_negative_numbers_set()
654                 && next.is_number())
655         {
656             // If allow hyphen, this isn't a new arg.
657             debug!("Parser::is_new_arg: Allow hyphen");
658             false
659         } else if next.is_long() {
660             // If this is a long flag, this is a new arg.
661             debug!("Parser::is_new_arg: --<something> found");
662             true
663         } else if next.is_short() {
664             // If this is a short flag, this is a new arg. But a singe '-' by
665             // itself is a value and typically means "stdin" on unix systems.
666             debug!("Parser::is_new_arg: -<something> found");
667             true
668         } else {
669             // Nothing special, this is a value.
670             debug!("Parser::is_new_arg: value");
671             false
672         }
673     }
674 
parse_subcommand( &mut self, sc_name: &str, matcher: &mut ArgMatcher, raw_args: &mut clap_lex::RawArgs, args_cursor: clap_lex::ArgCursor, keep_state: bool, ) -> ClapResult<()>675     fn parse_subcommand(
676         &mut self,
677         sc_name: &str,
678         matcher: &mut ArgMatcher,
679         raw_args: &mut clap_lex::RawArgs,
680         args_cursor: clap_lex::ArgCursor,
681         keep_state: bool,
682     ) -> ClapResult<()> {
683         debug!("Parser::parse_subcommand");
684 
685         let partial_parsing_enabled = self.cmd.is_ignore_errors_set();
686 
687         if let Some(sc) = self.cmd._build_subcommand(sc_name) {
688             let mut sc_matcher = ArgMatcher::new(sc);
689 
690             debug!(
691                 "Parser::parse_subcommand: About to parse sc={}",
692                 sc.get_name()
693             );
694 
695             {
696                 let mut p = Parser::new(sc);
697                 // HACK: maintain indexes between parsers
698                 // FlagSubCommand short arg needs to revisit the current short args, but skip the subcommand itself
699                 if keep_state {
700                     p.cur_idx.set(self.cur_idx.get());
701                     p.flag_subcmd_at = self.flag_subcmd_at;
702                     p.flag_subcmd_skip = self.flag_subcmd_skip;
703                 }
704                 if let Err(error) = p.get_matches_with(&mut sc_matcher, raw_args, args_cursor) {
705                     if partial_parsing_enabled {
706                         debug!(
707                             "Parser::parse_subcommand: ignored error in subcommand {}: {:?}",
708                             sc_name, error
709                         );
710                     } else {
711                         return Err(error);
712                     }
713                 }
714             }
715             matcher.subcommand(SubCommand {
716                 name: sc.get_name().to_owned(),
717                 matches: sc_matcher.into_inner(),
718             });
719         }
720         Ok(())
721     }
722 
parse_long_arg( &mut self, matcher: &mut ArgMatcher, long_arg: Result<&str, &RawOsStr>, long_value: Option<&RawOsStr>, parse_state: &ParseState, pos_counter: usize, valid_arg_found: &mut bool, ) -> ClapResult<ParseResult>723     fn parse_long_arg(
724         &mut self,
725         matcher: &mut ArgMatcher,
726         long_arg: Result<&str, &RawOsStr>,
727         long_value: Option<&RawOsStr>,
728         parse_state: &ParseState,
729         pos_counter: usize,
730         valid_arg_found: &mut bool,
731     ) -> ClapResult<ParseResult> {
732         // maybe here lifetime should be 'a
733         debug!("Parser::parse_long_arg");
734 
735         #[allow(clippy::blocks_in_if_conditions)]
736         if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if
737             self.cmd[opt].is_allow_hyphen_values_set())
738         {
739             debug!("Parser::parse_long_arg: prior arg accepts hyphenated values",);
740             return Ok(ParseResult::MaybeHyphenValue);
741         }
742 
743         debug!("Parser::parse_long_arg: Does it contain '='...");
744         let long_arg = match long_arg {
745             Ok(long_arg) => long_arg,
746             Err(long_arg) => {
747                 return Ok(ParseResult::NoMatchingArg {
748                     arg: long_arg.to_str_lossy().into_owned(),
749                 });
750             }
751         };
752         if long_arg.is_empty() {
753             debug_assert!(
754                 long_value.is_some(),
755                 "`--` should be filtered out before this point"
756             );
757         }
758 
759         let arg = if let Some(arg) = self.cmd.get_keymap().get(long_arg) {
760             debug!("Parser::parse_long_arg: Found valid arg or flag '{}'", arg);
761             Some((long_arg, arg))
762         } else if self.cmd.is_infer_long_args_set() {
763             self.cmd.get_arguments().find_map(|a| {
764                 if let Some(long) = a.get_long() {
765                     if long.starts_with(long_arg) {
766                         return Some((long, a));
767                     }
768                 }
769                 a.aliases
770                     .iter()
771                     .find_map(|(alias, _)| alias.starts_with(long_arg).then(|| (alias.as_str(), a)))
772             })
773         } else {
774             None
775         };
776 
777         if let Some((_long_arg, arg)) = arg {
778             let ident = Identifier::Long;
779             *valid_arg_found = true;
780             if arg.is_takes_value_set() {
781                 debug!(
782                     "Parser::parse_long_arg({:?}): Found an arg with value '{:?}'",
783                     long_arg, &long_value
784                 );
785                 let has_eq = long_value.is_some();
786                 self.parse_opt_value(ident, long_value, arg, matcher, has_eq)
787             } else if let Some(rest) = long_value {
788                 let required = self.cmd.required_graph();
789                 debug!(
790                     "Parser::parse_long_arg({:?}): Got invalid literal `{:?}`",
791                     long_arg, rest
792                 );
793                 let mut used: Vec<Id> = matcher
794                     .arg_ids()
795                     .filter(|arg_id| {
796                         matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent)
797                     })
798                     .filter(|&n| {
799                         self.cmd.find(n).map_or(true, |a| {
800                             !(a.is_hide_set() || required.contains(a.get_id()))
801                         })
802                     })
803                     .cloned()
804                     .collect();
805                 used.push(arg.get_id().clone());
806 
807                 Ok(ParseResult::UnneededAttachedValue {
808                     rest: rest.to_str_lossy().into_owned(),
809                     used,
810                     arg: arg.to_string(),
811                 })
812             } else {
813                 debug!("Parser::parse_long_arg({:?}): Presence validated", long_arg);
814                 let trailing_idx = None;
815                 self.react(
816                     Some(ident),
817                     ValueSource::CommandLine,
818                     arg,
819                     vec![],
820                     trailing_idx,
821                     matcher,
822                 )
823             }
824         } else if let Some(sc_name) = self.possible_long_flag_subcommand(long_arg) {
825             Ok(ParseResult::FlagSubCommand(sc_name.to_string()))
826         } else if self
827             .cmd
828             .get_keymap()
829             .get(&pos_counter)
830             .map_or(false, |arg| {
831                 arg.is_allow_hyphen_values_set() && !arg.is_last_set()
832             })
833         {
834             debug!(
835                 "Parser::parse_long_args: positional at {} allows hyphens",
836                 pos_counter
837             );
838             Ok(ParseResult::MaybeHyphenValue)
839         } else {
840             Ok(ParseResult::NoMatchingArg {
841                 arg: long_arg.to_owned(),
842             })
843         }
844     }
845 
parse_short_arg( &mut self, matcher: &mut ArgMatcher, mut short_arg: clap_lex::ShortFlags<'_>, parse_state: &ParseState, pos_counter: usize, valid_arg_found: &mut bool, ) -> ClapResult<ParseResult>846     fn parse_short_arg(
847         &mut self,
848         matcher: &mut ArgMatcher,
849         mut short_arg: clap_lex::ShortFlags<'_>,
850         parse_state: &ParseState,
851         // change this to possible pos_arg when removing the usage of &mut Parser.
852         pos_counter: usize,
853         valid_arg_found: &mut bool,
854     ) -> ClapResult<ParseResult> {
855         debug!("Parser::parse_short_arg: short_arg={:?}", short_arg);
856 
857         #[allow(clippy::blocks_in_if_conditions)]
858         if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt)
859                 if self.cmd[opt].is_allow_hyphen_values_set() || (self.cmd[opt].is_allow_negative_numbers_set() && short_arg.is_number()))
860         {
861             debug!("Parser::parse_short_args: prior arg accepts hyphenated values",);
862             return Ok(ParseResult::MaybeHyphenValue);
863         } else if self
864             .cmd
865             .get_keymap()
866             .get(&pos_counter)
867             .map_or(false, |arg| arg.is_allow_negative_numbers_set())
868             && short_arg.is_number()
869         {
870             debug!("Parser::parse_short_arg: negative number");
871             return Ok(ParseResult::MaybeHyphenValue);
872         } else if self
873             .cmd
874             .get_keymap()
875             .get(&pos_counter)
876             .map_or(false, |arg| {
877                 arg.is_allow_hyphen_values_set() && !arg.is_last_set()
878             })
879             && short_arg
880                 .clone()
881                 .any(|c| !c.map(|c| self.cmd.contains_short(c)).unwrap_or_default())
882         {
883             debug!(
884                 "Parser::parse_short_args: positional at {} allows hyphens",
885                 pos_counter
886             );
887             return Ok(ParseResult::MaybeHyphenValue);
888         }
889 
890         let mut ret = ParseResult::NoArg;
891 
892         let skip = self.flag_subcmd_skip;
893         self.flag_subcmd_skip = 0;
894         let res = short_arg.advance_by(skip);
895         debug_assert_eq!(
896             res,
897             Ok(()),
898             "tracking of `flag_subcmd_skip` is off for `{:?}`",
899             short_arg
900         );
901         while let Some(c) = short_arg.next_flag() {
902             let c = match c {
903                 Ok(c) => c,
904                 Err(rest) => {
905                     return Ok(ParseResult::NoMatchingArg {
906                         arg: format!("-{}", rest.to_str_lossy()),
907                     });
908                 }
909             };
910             debug!("Parser::parse_short_arg:iter:{}", c);
911 
912             // Check for matching short options, and return the name if there is no trailing
913             // concatenated value: -oval
914             // Option: -o
915             // Value: val
916             if let Some(arg) = self.cmd.get_keymap().get(&c) {
917                 let ident = Identifier::Short;
918                 debug!(
919                     "Parser::parse_short_arg:iter:{}: Found valid opt or flag",
920                     c
921                 );
922                 *valid_arg_found = true;
923                 if !arg.is_takes_value_set() {
924                     let arg_values = Vec::new();
925                     let trailing_idx = None;
926                     ret = ok!(self.react(
927                         Some(ident),
928                         ValueSource::CommandLine,
929                         arg,
930                         arg_values,
931                         trailing_idx,
932                         matcher,
933                     ));
934                     continue;
935                 }
936 
937                 // Check for trailing concatenated value
938                 //
939                 // Cloning the iterator, so we rollback if it isn't there.
940                 let val = short_arg.clone().next_value_os().unwrap_or_default();
941                 debug!(
942                     "Parser::parse_short_arg:iter:{}: val={:?} (bytes), val={:?} (ascii), short_arg={:?}",
943                     c, val, val.as_raw_bytes(), short_arg
944                 );
945                 let val = Some(val).filter(|v| !v.is_empty());
946 
947                 // Default to "we're expecting a value later".
948                 //
949                 // If attached value is not consumed, we may have more short
950                 // flags to parse, continue.
951                 //
952                 // e.g. `-xvf`, when require_equals && x.min_vals == 0, we don't
953                 // consume the `vf`, even if it's provided as value.
954                 let (val, has_eq) = if let Some(val) = val.and_then(|v| v.strip_prefix('=')) {
955                     (Some(val), true)
956                 } else {
957                     (val, false)
958                 };
959                 match ok!(self.parse_opt_value(ident, val, arg, matcher, has_eq)) {
960                     ParseResult::AttachedValueNotConsumed => continue,
961                     x => return Ok(x),
962                 }
963             }
964 
965             return if let Some(sc_name) = self.cmd.find_short_subcmd(c) {
966                 debug!("Parser::parse_short_arg:iter:{}: subcommand={}", c, sc_name);
967                 // Make sure indices get updated before reading `self.cur_idx`
968                 ok!(self.resolve_pending(matcher));
969                 self.cur_idx.set(self.cur_idx.get() + 1);
970                 debug!("Parser::parse_short_arg: cur_idx:={}", self.cur_idx.get());
971 
972                 let name = sc_name.to_string();
973                 // Get the index of the previously saved flag subcommand in the group of flags (if exists).
974                 // If it is a new flag subcommand, then the formentioned index should be the current one
975                 // (ie. `cur_idx`), and should be registered.
976                 let cur_idx = self.cur_idx.get();
977                 self.flag_subcmd_at.get_or_insert(cur_idx);
978                 let done_short_args = short_arg.is_empty();
979                 if done_short_args {
980                     self.flag_subcmd_at = None;
981                 }
982                 Ok(ParseResult::FlagSubCommand(name))
983             } else {
984                 Ok(ParseResult::NoMatchingArg {
985                     arg: format!("-{}", c),
986                 })
987             };
988         }
989         Ok(ret)
990     }
991 
parse_opt_value( &self, ident: Identifier, attached_value: Option<&RawOsStr>, arg: &Arg, matcher: &mut ArgMatcher, has_eq: bool, ) -> ClapResult<ParseResult>992     fn parse_opt_value(
993         &self,
994         ident: Identifier,
995         attached_value: Option<&RawOsStr>,
996         arg: &Arg,
997         matcher: &mut ArgMatcher,
998         has_eq: bool,
999     ) -> ClapResult<ParseResult> {
1000         debug!(
1001             "Parser::parse_opt_value; arg={}, val={:?}, has_eq={:?}",
1002             arg.get_id(),
1003             attached_value,
1004             has_eq
1005         );
1006         debug!("Parser::parse_opt_value; arg.settings={:?}", arg.settings);
1007 
1008         debug!("Parser::parse_opt_value; Checking for val...");
1009         // require_equals is set, but no '=' is provided, try throwing error.
1010         if arg.is_require_equals_set() && !has_eq {
1011             if arg.get_min_vals() == 0 {
1012                 debug!("Requires equals, but min_vals == 0");
1013                 let arg_values = Vec::new();
1014                 let trailing_idx = None;
1015                 let react_result = ok!(self.react(
1016                     Some(ident),
1017                     ValueSource::CommandLine,
1018                     arg,
1019                     arg_values,
1020                     trailing_idx,
1021                     matcher,
1022                 ));
1023                 debug_assert_eq!(react_result, ParseResult::ValuesDone);
1024                 if attached_value.is_some() {
1025                     Ok(ParseResult::AttachedValueNotConsumed)
1026                 } else {
1027                     Ok(ParseResult::ValuesDone)
1028                 }
1029             } else {
1030                 debug!("Requires equals but not provided. Error.");
1031                 Ok(ParseResult::EqualsNotProvided {
1032                     arg: arg.to_string(),
1033                 })
1034             }
1035         } else if let Some(v) = attached_value {
1036             let arg_values = vec![v.to_os_str().into_owned()];
1037             let trailing_idx = None;
1038             let react_result = ok!(self.react(
1039                 Some(ident),
1040                 ValueSource::CommandLine,
1041                 arg,
1042                 arg_values,
1043                 trailing_idx,
1044                 matcher,
1045             ));
1046             debug_assert_eq!(react_result, ParseResult::ValuesDone);
1047             // Attached are always done
1048             Ok(ParseResult::ValuesDone)
1049         } else {
1050             debug!("Parser::parse_opt_value: More arg vals required...");
1051             ok!(self.resolve_pending(matcher));
1052             let trailing_values = false;
1053             matcher.pending_values_mut(arg.get_id(), Some(ident), trailing_values);
1054             Ok(ParseResult::Opt(arg.get_id().clone()))
1055         }
1056     }
1057 
check_terminator(&self, arg: &Arg, val: &RawOsStr) -> Option<ParseResult>1058     fn check_terminator(&self, arg: &Arg, val: &RawOsStr) -> Option<ParseResult> {
1059         if Some(val)
1060             == arg
1061                 .terminator
1062                 .as_ref()
1063                 .map(|s| RawOsStr::from_str(s.as_str()))
1064         {
1065             debug!("Parser::check_terminator: terminator={:?}", arg.terminator);
1066             Some(ParseResult::ValuesDone)
1067         } else {
1068             None
1069         }
1070     }
1071 
push_arg_values( &self, arg: &Arg, raw_vals: Vec<OsString>, matcher: &mut ArgMatcher, ) -> ClapResult<()>1072     fn push_arg_values(
1073         &self,
1074         arg: &Arg,
1075         raw_vals: Vec<OsString>,
1076         matcher: &mut ArgMatcher,
1077     ) -> ClapResult<()> {
1078         debug!("Parser::push_arg_values: {:?}", raw_vals);
1079 
1080         for raw_val in raw_vals {
1081             // update the current index because each value is a distinct index to clap
1082             self.cur_idx.set(self.cur_idx.get() + 1);
1083             debug!(
1084                 "Parser::add_single_val_to_arg: cur_idx:={}",
1085                 self.cur_idx.get()
1086             );
1087             let value_parser = arg.get_value_parser();
1088             let val = ok!(value_parser.parse_ref(self.cmd, Some(arg), &raw_val));
1089 
1090             matcher.add_val_to(arg.get_id(), val, raw_val);
1091             matcher.add_index_to(arg.get_id(), self.cur_idx.get());
1092         }
1093 
1094         Ok(())
1095     }
1096 
resolve_pending(&self, matcher: &mut ArgMatcher) -> ClapResult<()>1097     fn resolve_pending(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1098         let pending = match matcher.take_pending() {
1099             Some(pending) => pending,
1100             None => {
1101                 return Ok(());
1102             }
1103         };
1104 
1105         debug!("Parser::resolve_pending: id={:?}", pending.id);
1106         let arg = self.cmd.find(&pending.id).expect(INTERNAL_ERROR_MSG);
1107         let _ = ok!(self.react(
1108             pending.ident,
1109             ValueSource::CommandLine,
1110             arg,
1111             pending.raw_vals,
1112             pending.trailing_idx,
1113             matcher,
1114         ));
1115 
1116         Ok(())
1117     }
1118 
react( &self, ident: Option<Identifier>, source: ValueSource, arg: &Arg, mut raw_vals: Vec<OsString>, mut trailing_idx: Option<usize>, matcher: &mut ArgMatcher, ) -> ClapResult<ParseResult>1119     fn react(
1120         &self,
1121         ident: Option<Identifier>,
1122         source: ValueSource,
1123         arg: &Arg,
1124         mut raw_vals: Vec<OsString>,
1125         mut trailing_idx: Option<usize>,
1126         matcher: &mut ArgMatcher,
1127     ) -> ClapResult<ParseResult> {
1128         ok!(self.resolve_pending(matcher));
1129 
1130         debug!(
1131             "Parser::react action={:?}, identifier={:?}, source={:?}",
1132             arg.get_action(),
1133             ident,
1134             source
1135         );
1136 
1137         // Process before `default_missing_values` to avoid it counting as values from the command
1138         // line
1139         if source == ValueSource::CommandLine {
1140             ok!(self.verify_num_args(arg, &raw_vals));
1141         }
1142 
1143         if raw_vals.is_empty() {
1144             // We assume this case is valid: require equals, but min_vals == 0.
1145             if !arg.default_missing_vals.is_empty() {
1146                 debug!("Parser::react: has default_missing_vals");
1147                 trailing_idx = None;
1148                 raw_vals.extend(
1149                     arg.default_missing_vals
1150                         .iter()
1151                         .map(|s| s.as_os_str().to_owned()),
1152                 );
1153             }
1154         }
1155 
1156         if let Some(val_delim) = arg.get_value_delimiter() {
1157             if self.cmd.is_dont_delimit_trailing_values_set() && trailing_idx == Some(0) {
1158                 // Nothing to do
1159             } else {
1160                 let mut split_raw_vals = Vec::with_capacity(raw_vals.len());
1161                 for (i, raw_val) in raw_vals.into_iter().enumerate() {
1162                     let raw_val = RawOsString::new(raw_val);
1163                     if !raw_val.contains(val_delim)
1164                         || (self.cmd.is_dont_delimit_trailing_values_set()
1165                             && trailing_idx == Some(i))
1166                     {
1167                         split_raw_vals.push(raw_val.into_os_string());
1168                     } else {
1169                         split_raw_vals
1170                             .extend(raw_val.split(val_delim).map(|x| x.to_os_str().into_owned()));
1171                     }
1172                 }
1173                 raw_vals = split_raw_vals
1174             }
1175         }
1176 
1177         match arg.get_action() {
1178             ArgAction::Set => {
1179                 if source == ValueSource::CommandLine
1180                     && matches!(ident, Some(Identifier::Short) | Some(Identifier::Long))
1181                 {
1182                     // Record flag's index
1183                     self.cur_idx.set(self.cur_idx.get() + 1);
1184                     debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
1185                 }
1186                 if matcher.remove(arg.get_id())
1187                     && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1188                 {
1189                     return Err(ClapError::argument_conflict(
1190                         self.cmd,
1191                         arg.to_string(),
1192                         vec![arg.to_string()],
1193                         Usage::new(self.cmd).create_usage_with_title(&[]),
1194                     ));
1195                 }
1196                 self.start_custom_arg(matcher, arg, source);
1197                 ok!(self.push_arg_values(arg, raw_vals, matcher));
1198                 if cfg!(debug_assertions) && matcher.needs_more_vals(arg) {
1199                     debug!(
1200                         "Parser::react not enough values passed in, leaving it to the validator to complain",
1201                     );
1202                 }
1203                 Ok(ParseResult::ValuesDone)
1204             }
1205             ArgAction::Append => {
1206                 if source == ValueSource::CommandLine
1207                     && matches!(ident, Some(Identifier::Short) | Some(Identifier::Long))
1208                 {
1209                     // Record flag's index
1210                     self.cur_idx.set(self.cur_idx.get() + 1);
1211                     debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
1212                 }
1213                 self.start_custom_arg(matcher, arg, source);
1214                 ok!(self.push_arg_values(arg, raw_vals, matcher));
1215                 if cfg!(debug_assertions) && matcher.needs_more_vals(arg) {
1216                     debug!(
1217                         "Parser::react not enough values passed in, leaving it to the validator to complain",
1218                     );
1219                 }
1220                 Ok(ParseResult::ValuesDone)
1221             }
1222             ArgAction::SetTrue => {
1223                 let raw_vals = if raw_vals.is_empty() {
1224                     vec![OsString::from("true")]
1225                 } else {
1226                     raw_vals
1227                 };
1228 
1229                 if matcher.remove(arg.get_id())
1230                     && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1231                 {
1232                     return Err(ClapError::argument_conflict(
1233                         self.cmd,
1234                         arg.to_string(),
1235                         vec![arg.to_string()],
1236                         Usage::new(self.cmd).create_usage_with_title(&[]),
1237                     ));
1238                 }
1239                 self.start_custom_arg(matcher, arg, source);
1240                 ok!(self.push_arg_values(arg, raw_vals, matcher));
1241                 Ok(ParseResult::ValuesDone)
1242             }
1243             ArgAction::SetFalse => {
1244                 let raw_vals = if raw_vals.is_empty() {
1245                     vec![OsString::from("false")]
1246                 } else {
1247                     raw_vals
1248                 };
1249 
1250                 if matcher.remove(arg.get_id())
1251                     && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1252                 {
1253                     return Err(ClapError::argument_conflict(
1254                         self.cmd,
1255                         arg.to_string(),
1256                         vec![arg.to_string()],
1257                         Usage::new(self.cmd).create_usage_with_title(&[]),
1258                     ));
1259                 }
1260                 self.start_custom_arg(matcher, arg, source);
1261                 ok!(self.push_arg_values(arg, raw_vals, matcher));
1262                 Ok(ParseResult::ValuesDone)
1263             }
1264             ArgAction::Count => {
1265                 let raw_vals = if raw_vals.is_empty() {
1266                     let existing_value = *matcher
1267                         .get_one::<crate::builder::CountType>(arg.get_id().as_str())
1268                         .unwrap_or(&0);
1269                     let next_value = existing_value.saturating_add(1);
1270                     vec![OsString::from(next_value.to_string())]
1271                 } else {
1272                     raw_vals
1273                 };
1274 
1275                 matcher.remove(arg.get_id());
1276                 self.start_custom_arg(matcher, arg, source);
1277                 ok!(self.push_arg_values(arg, raw_vals, matcher));
1278                 Ok(ParseResult::ValuesDone)
1279             }
1280             ArgAction::Help => {
1281                 let use_long = match ident {
1282                     Some(Identifier::Long) => true,
1283                     Some(Identifier::Short) => false,
1284                     Some(Identifier::Index) => true,
1285                     None => true,
1286                 };
1287                 debug!("Help: use_long={}", use_long);
1288                 Err(self.help_err(use_long))
1289             }
1290             ArgAction::Version => {
1291                 let use_long = match ident {
1292                     Some(Identifier::Long) => true,
1293                     Some(Identifier::Short) => false,
1294                     Some(Identifier::Index) => true,
1295                     None => true,
1296                 };
1297                 debug!("Version: use_long={}", use_long);
1298                 Err(self.version_err(use_long))
1299             }
1300         }
1301     }
1302 
verify_num_args(&self, arg: &Arg, raw_vals: &[OsString]) -> ClapResult<()>1303     fn verify_num_args(&self, arg: &Arg, raw_vals: &[OsString]) -> ClapResult<()> {
1304         if self.cmd.is_ignore_errors_set() {
1305             return Ok(());
1306         }
1307 
1308         let actual = raw_vals.len();
1309         let expected = arg.get_num_args().expect(INTERNAL_ERROR_MSG);
1310 
1311         if 0 < expected.min_values() && actual == 0 {
1312             // Issue 665 (https://github.com/clap-rs/clap/issues/665)
1313             // Issue 1105 (https://github.com/clap-rs/clap/issues/1105)
1314             return Err(ClapError::empty_value(
1315                 self.cmd,
1316                 &super::get_possible_values_cli(arg)
1317                     .iter()
1318                     .filter(|pv| !pv.is_hide_set())
1319                     .map(|n| n.get_name().to_owned())
1320                     .collect::<Vec<_>>(),
1321                 arg.to_string(),
1322             ));
1323         } else if let Some(expected) = expected.num_values() {
1324             if expected != actual {
1325                 debug!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues");
1326                 return Err(ClapError::wrong_number_of_values(
1327                     self.cmd,
1328                     arg.to_string(),
1329                     expected,
1330                     actual,
1331                     Usage::new(self.cmd).create_usage_with_title(&[]),
1332                 ));
1333             }
1334         } else if actual < expected.min_values() {
1335             return Err(ClapError::too_few_values(
1336                 self.cmd,
1337                 arg.to_string(),
1338                 expected.min_values(),
1339                 actual,
1340                 Usage::new(self.cmd).create_usage_with_title(&[]),
1341             ));
1342         } else if expected.max_values() < actual {
1343             debug!("Validator::validate_arg_num_vals: Sending error TooManyValues");
1344             return Err(ClapError::too_many_values(
1345                 self.cmd,
1346                 raw_vals
1347                     .last()
1348                     .expect(INTERNAL_ERROR_MSG)
1349                     .to_string_lossy()
1350                     .into_owned(),
1351                 arg.to_string(),
1352                 Usage::new(self.cmd).create_usage_with_title(&[]),
1353             ));
1354         }
1355 
1356         Ok(())
1357     }
1358 
remove_overrides(&self, arg: &Arg, matcher: &mut ArgMatcher)1359     fn remove_overrides(&self, arg: &Arg, matcher: &mut ArgMatcher) {
1360         debug!("Parser::remove_overrides: id={:?}", arg.id);
1361         for override_id in &arg.overrides {
1362             debug!("Parser::remove_overrides:iter:{:?}: removing", override_id);
1363             matcher.remove(override_id);
1364         }
1365 
1366         // Override anything that can override us
1367         let mut transitive = Vec::new();
1368         for arg_id in matcher.arg_ids() {
1369             if let Some(overrider) = self.cmd.find(arg_id) {
1370                 if overrider.overrides.contains(arg.get_id()) {
1371                     transitive.push(overrider.get_id());
1372                 }
1373             }
1374         }
1375         for overrider_id in transitive {
1376             debug!("Parser::remove_overrides:iter:{:?}: removing", overrider_id);
1377             matcher.remove(overrider_id);
1378         }
1379     }
1380 
1381     #[cfg(feature = "env")]
add_env(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()>1382     fn add_env(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1383         debug!("Parser::add_env");
1384 
1385         for arg in self.cmd.get_arguments() {
1386             // Use env only if the arg was absent among command line args,
1387             // early return if this is not the case.
1388             if matcher.contains(&arg.id) {
1389                 debug!("Parser::add_env: Skipping existing arg `{}`", arg);
1390                 continue;
1391             }
1392 
1393             debug!("Parser::add_env: Checking arg `{}`", arg);
1394             if let Some((_, Some(ref val))) = arg.env {
1395                 debug!("Parser::add_env: Found an opt with value={:?}", val);
1396                 let arg_values = vec![val.to_owned()];
1397                 let trailing_idx = None;
1398                 let _ = ok!(self.react(
1399                     None,
1400                     ValueSource::EnvVariable,
1401                     arg,
1402                     arg_values,
1403                     trailing_idx,
1404                     matcher,
1405                 ));
1406             }
1407         }
1408 
1409         Ok(())
1410     }
1411 
add_defaults(&self, matcher: &mut ArgMatcher) -> ClapResult<()>1412     fn add_defaults(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1413         debug!("Parser::add_defaults");
1414 
1415         for arg in self.cmd.get_arguments() {
1416             debug!("Parser::add_defaults:iter:{}:", arg.get_id());
1417             ok!(self.add_default_value(arg, matcher));
1418         }
1419 
1420         Ok(())
1421     }
1422 
add_default_value(&self, arg: &Arg, matcher: &mut ArgMatcher) -> ClapResult<()>1423     fn add_default_value(&self, arg: &Arg, matcher: &mut ArgMatcher) -> ClapResult<()> {
1424         if !arg.default_vals_ifs.is_empty() {
1425             debug!("Parser::add_default_value: has conditional defaults");
1426             if !matcher.contains(arg.get_id()) {
1427                 for (id, val, default) in arg.default_vals_ifs.iter() {
1428                     let add = if let Some(a) = matcher.get(id) {
1429                         match val {
1430                             crate::builder::ArgPredicate::Equals(v) => {
1431                                 a.raw_vals_flatten().any(|value| v == value)
1432                             }
1433                             crate::builder::ArgPredicate::IsPresent => true,
1434                         }
1435                     } else {
1436                         false
1437                     };
1438 
1439                     if add {
1440                         if let Some(default) = default {
1441                             let arg_values = vec![default.to_os_string()];
1442                             let trailing_idx = None;
1443                             let _ = ok!(self.react(
1444                                 None,
1445                                 ValueSource::DefaultValue,
1446                                 arg,
1447                                 arg_values,
1448                                 trailing_idx,
1449                                 matcher,
1450                             ));
1451                         }
1452                         return Ok(());
1453                     }
1454                 }
1455             }
1456         } else {
1457             debug!("Parser::add_default_value: doesn't have conditional defaults");
1458         }
1459 
1460         if !arg.default_vals.is_empty() {
1461             debug!(
1462                 "Parser::add_default_value:iter:{}: has default vals",
1463                 arg.get_id()
1464             );
1465             if matcher.contains(arg.get_id()) {
1466                 debug!("Parser::add_default_value:iter:{}: was used", arg.get_id());
1467             // do nothing
1468             } else {
1469                 debug!(
1470                     "Parser::add_default_value:iter:{}: wasn't used",
1471                     arg.get_id()
1472                 );
1473                 let arg_values: Vec<_> = arg
1474                     .default_vals
1475                     .iter()
1476                     .map(crate::builder::OsStr::to_os_string)
1477                     .collect();
1478                 let trailing_idx = None;
1479                 let _ = ok!(self.react(
1480                     None,
1481                     ValueSource::DefaultValue,
1482                     arg,
1483                     arg_values,
1484                     trailing_idx,
1485                     matcher,
1486                 ));
1487             }
1488         } else {
1489             debug!(
1490                 "Parser::add_default_value:iter:{}: doesn't have default vals",
1491                 arg.get_id()
1492             );
1493 
1494             // do nothing
1495         }
1496 
1497         Ok(())
1498     }
1499 
start_custom_arg(&self, matcher: &mut ArgMatcher, arg: &Arg, source: ValueSource)1500     fn start_custom_arg(&self, matcher: &mut ArgMatcher, arg: &Arg, source: ValueSource) {
1501         if source == ValueSource::CommandLine {
1502             // With each new occurrence, remove overrides from prior occurrences
1503             self.remove_overrides(arg, matcher);
1504         }
1505         matcher.start_custom_arg(arg, source);
1506         if source.is_explicit() {
1507             for group in self.cmd.groups_for_arg(arg.get_id()) {
1508                 matcher.start_custom_group(group.clone(), source);
1509                 matcher.add_val_to(
1510                     &group,
1511                     AnyValue::new(arg.get_id().clone()),
1512                     OsString::from(arg.get_id().as_str()),
1513                 );
1514             }
1515         }
1516     }
1517 }
1518 
1519 // Error, Help, and Version Methods
1520 impl<'cmd> Parser<'cmd> {
1521     /// Is only used for the long flag(which is the only one needs fuzzy searching)
did_you_mean_error( &mut self, arg: &str, matcher: &mut ArgMatcher, remaining_args: &[&OsStr], trailing_values: bool, ) -> ClapError1522     fn did_you_mean_error(
1523         &mut self,
1524         arg: &str,
1525         matcher: &mut ArgMatcher,
1526         remaining_args: &[&OsStr],
1527         trailing_values: bool,
1528     ) -> ClapError {
1529         debug!("Parser::did_you_mean_error: arg={}", arg);
1530         // Didn't match a flag or option
1531         let longs = self
1532             .cmd
1533             .get_keymap()
1534             .keys()
1535             .filter_map(|x| match x {
1536                 KeyType::Long(l) => Some(l.to_string_lossy().into_owned()),
1537                 _ => None,
1538             })
1539             .collect::<Vec<_>>();
1540         debug!("Parser::did_you_mean_error: longs={:?}", longs);
1541 
1542         let did_you_mean = suggestions::did_you_mean_flag(
1543             arg,
1544             remaining_args,
1545             longs.iter().map(|x| &x[..]),
1546             self.cmd.get_subcommands_mut(),
1547         );
1548 
1549         // Add the arg to the matches to build a proper usage string
1550         if let Some((name, _)) = did_you_mean.as_ref() {
1551             if let Some(arg) = self.cmd.get_keymap().get(&name.as_ref()) {
1552                 self.start_custom_arg(matcher, arg, ValueSource::CommandLine);
1553             }
1554         }
1555 
1556         let required = self.cmd.required_graph();
1557         let used: Vec<Id> = matcher
1558             .arg_ids()
1559             .filter(|arg_id| {
1560                 matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent)
1561             })
1562             .filter(|n| self.cmd.find(n).map_or(true, |a| !a.is_hide_set()))
1563             .cloned()
1564             .collect();
1565 
1566         // `did_you_mean` is a lot more likely and should cause us to skip the `--` suggestion
1567         //
1568         // In theory, this is only called for `--long`s, so we don't need to check
1569         let suggested_trailing_arg =
1570             did_you_mean.is_none() && !trailing_values && self.cmd.has_positionals();
1571         ClapError::unknown_argument(
1572             self.cmd,
1573             format!("--{}", arg),
1574             did_you_mean,
1575             suggested_trailing_arg,
1576             Usage::new(self.cmd)
1577                 .required(&required)
1578                 .create_usage_with_title(&used),
1579         )
1580     }
1581 
help_err(&self, use_long: bool) -> ClapError1582     fn help_err(&self, use_long: bool) -> ClapError {
1583         let styled = self.cmd.write_help_err(use_long);
1584         ClapError::display_help(self.cmd, styled)
1585     }
1586 
version_err(&self, use_long: bool) -> ClapError1587     fn version_err(&self, use_long: bool) -> ClapError {
1588         let styled = self.cmd.write_version_err(use_long);
1589         ClapError::display_version(self.cmd, styled)
1590     }
1591 }
1592 
1593 #[derive(Debug, PartialEq, Eq)]
1594 pub(crate) enum ParseState {
1595     ValuesDone,
1596     Opt(Id),
1597     Pos(Id),
1598 }
1599 
1600 /// Recoverable Parsing results.
1601 #[derive(Debug, PartialEq, Clone)]
1602 #[must_use]
1603 enum ParseResult {
1604     FlagSubCommand(String),
1605     Opt(Id),
1606     ValuesDone,
1607     /// Value attached to the short flag is not consumed(e.g. 'u' for `-cu` is
1608     /// not consumed).
1609     AttachedValueNotConsumed,
1610     /// This long flag doesn't need a value but is provided one.
1611     UnneededAttachedValue {
1612         rest: String,
1613         used: Vec<Id>,
1614         arg: String,
1615     },
1616     /// This flag might be an hyphen Value.
1617     MaybeHyphenValue,
1618     /// Equals required but not provided.
1619     EqualsNotProvided {
1620         arg: String,
1621     },
1622     /// Failed to match a Arg.
1623     NoMatchingArg {
1624         arg: String,
1625     },
1626     /// No argument found e.g. parser is given `-` when parsing a flag.
1627     NoArg,
1628 }
1629 
1630 #[derive(Clone, Debug, PartialEq, Eq)]
1631 pub(crate) struct PendingArg {
1632     pub(crate) id: Id,
1633     pub(crate) ident: Option<Identifier>,
1634     pub(crate) raw_vals: Vec<OsString>,
1635     pub(crate) trailing_idx: Option<usize>,
1636 }
1637 
1638 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1639 pub(crate) enum Identifier {
1640     Short,
1641     Long,
1642     Index,
1643 }
1644