• 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 `{short_arg:?}`"
899         );
900         while let Some(c) = short_arg.next_flag() {
901             let c = match c {
902                 Ok(c) => c,
903                 Err(rest) => {
904                     return Ok(ParseResult::NoMatchingArg {
905                         arg: format!("-{}", rest.to_str_lossy()),
906                     });
907                 }
908             };
909             debug!("Parser::parse_short_arg:iter:{}", c);
910 
911             // Check for matching short options, and return the name if there is no trailing
912             // concatenated value: -oval
913             // Option: -o
914             // Value: val
915             if let Some(arg) = self.cmd.get_keymap().get(&c) {
916                 let ident = Identifier::Short;
917                 debug!(
918                     "Parser::parse_short_arg:iter:{}: Found valid opt or flag",
919                     c
920                 );
921                 *valid_arg_found = true;
922                 if !arg.is_takes_value_set() {
923                     let arg_values = Vec::new();
924                     let trailing_idx = None;
925                     ret = ok!(self.react(
926                         Some(ident),
927                         ValueSource::CommandLine,
928                         arg,
929                         arg_values,
930                         trailing_idx,
931                         matcher,
932                     ));
933                     continue;
934                 }
935 
936                 // Check for trailing concatenated value
937                 //
938                 // Cloning the iterator, so we rollback if it isn't there.
939                 let val = short_arg.clone().next_value_os().unwrap_or_default();
940                 debug!(
941                     "Parser::parse_short_arg:iter:{}: val={:?} (bytes), val={:?} (ascii), short_arg={:?}",
942                     c, val, val.as_raw_bytes(), short_arg
943                 );
944                 let val = Some(val).filter(|v| !v.is_empty());
945 
946                 // Default to "we're expecting a value later".
947                 //
948                 // If attached value is not consumed, we may have more short
949                 // flags to parse, continue.
950                 //
951                 // e.g. `-xvf`, when require_equals && x.min_vals == 0, we don't
952                 // consume the `vf`, even if it's provided as value.
953                 let (val, has_eq) = if let Some(val) = val.and_then(|v| v.strip_prefix('=')) {
954                     (Some(val), true)
955                 } else {
956                     (val, false)
957                 };
958                 match ok!(self.parse_opt_value(ident, val, arg, matcher, has_eq)) {
959                     ParseResult::AttachedValueNotConsumed => continue,
960                     x => return Ok(x),
961                 }
962             }
963 
964             return if let Some(sc_name) = self.cmd.find_short_subcmd(c) {
965                 debug!("Parser::parse_short_arg:iter:{}: subcommand={}", c, sc_name);
966                 // Make sure indices get updated before reading `self.cur_idx`
967                 ok!(self.resolve_pending(matcher));
968                 self.cur_idx.set(self.cur_idx.get() + 1);
969                 debug!("Parser::parse_short_arg: cur_idx:={}", self.cur_idx.get());
970 
971                 let name = sc_name.to_string();
972                 // Get the index of the previously saved flag subcommand in the group of flags (if exists).
973                 // If it is a new flag subcommand, then the formentioned index should be the current one
974                 // (ie. `cur_idx`), and should be registered.
975                 let cur_idx = self.cur_idx.get();
976                 self.flag_subcmd_at.get_or_insert(cur_idx);
977                 let done_short_args = short_arg.is_empty();
978                 if done_short_args {
979                     self.flag_subcmd_at = None;
980                 }
981                 Ok(ParseResult::FlagSubCommand(name))
982             } else {
983                 Ok(ParseResult::NoMatchingArg {
984                     arg: format!("-{c}"),
985                 })
986             };
987         }
988         Ok(ret)
989     }
990 
parse_opt_value( &self, ident: Identifier, attached_value: Option<&RawOsStr>, arg: &Arg, matcher: &mut ArgMatcher, has_eq: bool, ) -> ClapResult<ParseResult>991     fn parse_opt_value(
992         &self,
993         ident: Identifier,
994         attached_value: Option<&RawOsStr>,
995         arg: &Arg,
996         matcher: &mut ArgMatcher,
997         has_eq: bool,
998     ) -> ClapResult<ParseResult> {
999         debug!(
1000             "Parser::parse_opt_value; arg={}, val={:?}, has_eq={:?}",
1001             arg.get_id(),
1002             attached_value,
1003             has_eq
1004         );
1005         debug!("Parser::parse_opt_value; arg.settings={:?}", arg.settings);
1006 
1007         debug!("Parser::parse_opt_value; Checking for val...");
1008         // require_equals is set, but no '=' is provided, try throwing error.
1009         if arg.is_require_equals_set() && !has_eq {
1010             if arg.get_min_vals() == 0 {
1011                 debug!("Requires equals, but min_vals == 0");
1012                 let arg_values = Vec::new();
1013                 let trailing_idx = None;
1014                 let react_result = ok!(self.react(
1015                     Some(ident),
1016                     ValueSource::CommandLine,
1017                     arg,
1018                     arg_values,
1019                     trailing_idx,
1020                     matcher,
1021                 ));
1022                 debug_assert_eq!(react_result, ParseResult::ValuesDone);
1023                 if attached_value.is_some() {
1024                     Ok(ParseResult::AttachedValueNotConsumed)
1025                 } else {
1026                     Ok(ParseResult::ValuesDone)
1027                 }
1028             } else {
1029                 debug!("Requires equals but not provided. Error.");
1030                 Ok(ParseResult::EqualsNotProvided {
1031                     arg: arg.to_string(),
1032                 })
1033             }
1034         } else if let Some(v) = attached_value {
1035             let arg_values = vec![v.to_os_str().into_owned()];
1036             let trailing_idx = None;
1037             let react_result = ok!(self.react(
1038                 Some(ident),
1039                 ValueSource::CommandLine,
1040                 arg,
1041                 arg_values,
1042                 trailing_idx,
1043                 matcher,
1044             ));
1045             debug_assert_eq!(react_result, ParseResult::ValuesDone);
1046             // Attached are always done
1047             Ok(ParseResult::ValuesDone)
1048         } else {
1049             debug!("Parser::parse_opt_value: More arg vals required...");
1050             ok!(self.resolve_pending(matcher));
1051             let trailing_values = false;
1052             matcher.pending_values_mut(arg.get_id(), Some(ident), trailing_values);
1053             Ok(ParseResult::Opt(arg.get_id().clone()))
1054         }
1055     }
1056 
check_terminator(&self, arg: &Arg, val: &RawOsStr) -> Option<ParseResult>1057     fn check_terminator(&self, arg: &Arg, val: &RawOsStr) -> Option<ParseResult> {
1058         if Some(val)
1059             == arg
1060                 .terminator
1061                 .as_ref()
1062                 .map(|s| RawOsStr::from_str(s.as_str()))
1063         {
1064             debug!("Parser::check_terminator: terminator={:?}", arg.terminator);
1065             Some(ParseResult::ValuesDone)
1066         } else {
1067             None
1068         }
1069     }
1070 
push_arg_values( &self, arg: &Arg, raw_vals: Vec<OsString>, matcher: &mut ArgMatcher, ) -> ClapResult<()>1071     fn push_arg_values(
1072         &self,
1073         arg: &Arg,
1074         raw_vals: Vec<OsString>,
1075         matcher: &mut ArgMatcher,
1076     ) -> ClapResult<()> {
1077         debug!("Parser::push_arg_values: {:?}", raw_vals);
1078 
1079         for raw_val in raw_vals {
1080             // update the current index because each value is a distinct index to clap
1081             self.cur_idx.set(self.cur_idx.get() + 1);
1082             debug!(
1083                 "Parser::add_single_val_to_arg: cur_idx:={}",
1084                 self.cur_idx.get()
1085             );
1086             let value_parser = arg.get_value_parser();
1087             let val = ok!(value_parser.parse_ref(self.cmd, Some(arg), &raw_val));
1088 
1089             matcher.add_val_to(arg.get_id(), val, raw_val);
1090             matcher.add_index_to(arg.get_id(), self.cur_idx.get());
1091         }
1092 
1093         Ok(())
1094     }
1095 
resolve_pending(&self, matcher: &mut ArgMatcher) -> ClapResult<()>1096     fn resolve_pending(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1097         let pending = match matcher.take_pending() {
1098             Some(pending) => pending,
1099             None => {
1100                 return Ok(());
1101             }
1102         };
1103 
1104         debug!("Parser::resolve_pending: id={:?}", pending.id);
1105         let arg = self.cmd.find(&pending.id).expect(INTERNAL_ERROR_MSG);
1106         let _ = ok!(self.react(
1107             pending.ident,
1108             ValueSource::CommandLine,
1109             arg,
1110             pending.raw_vals,
1111             pending.trailing_idx,
1112             matcher,
1113         ));
1114 
1115         Ok(())
1116     }
1117 
react( &self, ident: Option<Identifier>, source: ValueSource, arg: &Arg, mut raw_vals: Vec<OsString>, mut trailing_idx: Option<usize>, matcher: &mut ArgMatcher, ) -> ClapResult<ParseResult>1118     fn react(
1119         &self,
1120         ident: Option<Identifier>,
1121         source: ValueSource,
1122         arg: &Arg,
1123         mut raw_vals: Vec<OsString>,
1124         mut trailing_idx: Option<usize>,
1125         matcher: &mut ArgMatcher,
1126     ) -> ClapResult<ParseResult> {
1127         ok!(self.resolve_pending(matcher));
1128 
1129         debug!(
1130             "Parser::react action={:?}, identifier={:?}, source={:?}",
1131             arg.get_action(),
1132             ident,
1133             source
1134         );
1135 
1136         // Process before `default_missing_values` to avoid it counting as values from the command
1137         // line
1138         if source == ValueSource::CommandLine {
1139             ok!(self.verify_num_args(arg, &raw_vals));
1140         }
1141 
1142         if raw_vals.is_empty() {
1143             // We assume this case is valid: require equals, but min_vals == 0.
1144             if !arg.default_missing_vals.is_empty() {
1145                 debug!("Parser::react: has default_missing_vals");
1146                 trailing_idx = None;
1147                 raw_vals.extend(
1148                     arg.default_missing_vals
1149                         .iter()
1150                         .map(|s| s.as_os_str().to_owned()),
1151                 );
1152             }
1153         }
1154 
1155         if let Some(val_delim) = arg.get_value_delimiter() {
1156             if self.cmd.is_dont_delimit_trailing_values_set() && trailing_idx == Some(0) {
1157                 // Nothing to do
1158             } else {
1159                 let mut split_raw_vals = Vec::with_capacity(raw_vals.len());
1160                 for (i, raw_val) in raw_vals.into_iter().enumerate() {
1161                     let raw_val = RawOsString::new(raw_val);
1162                     if !raw_val.contains(val_delim)
1163                         || (self.cmd.is_dont_delimit_trailing_values_set()
1164                             && trailing_idx == Some(i))
1165                     {
1166                         split_raw_vals.push(raw_val.into_os_string());
1167                     } else {
1168                         split_raw_vals
1169                             .extend(raw_val.split(val_delim).map(|x| x.to_os_str().into_owned()));
1170                     }
1171                 }
1172                 raw_vals = split_raw_vals
1173             }
1174         }
1175 
1176         match arg.get_action() {
1177             ArgAction::Set => {
1178                 if source == ValueSource::CommandLine
1179                     && matches!(ident, Some(Identifier::Short) | Some(Identifier::Long))
1180                 {
1181                     // Record flag's index
1182                     self.cur_idx.set(self.cur_idx.get() + 1);
1183                     debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
1184                 }
1185                 if matcher.remove(arg.get_id())
1186                     && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1187                 {
1188                     return Err(ClapError::argument_conflict(
1189                         self.cmd,
1190                         arg.to_string(),
1191                         vec![arg.to_string()],
1192                         Usage::new(self.cmd).create_usage_with_title(&[]),
1193                     ));
1194                 }
1195                 self.start_custom_arg(matcher, arg, source);
1196                 ok!(self.push_arg_values(arg, raw_vals, matcher));
1197                 if cfg!(debug_assertions) && matcher.needs_more_vals(arg) {
1198                     debug!(
1199                         "Parser::react not enough values passed in, leaving it to the validator to complain",
1200                     );
1201                 }
1202                 Ok(ParseResult::ValuesDone)
1203             }
1204             ArgAction::Append => {
1205                 if source == ValueSource::CommandLine
1206                     && matches!(ident, Some(Identifier::Short) | Some(Identifier::Long))
1207                 {
1208                     // Record flag's index
1209                     self.cur_idx.set(self.cur_idx.get() + 1);
1210                     debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
1211                 }
1212                 self.start_custom_arg(matcher, arg, source);
1213                 ok!(self.push_arg_values(arg, raw_vals, matcher));
1214                 if cfg!(debug_assertions) && matcher.needs_more_vals(arg) {
1215                     debug!(
1216                         "Parser::react not enough values passed in, leaving it to the validator to complain",
1217                     );
1218                 }
1219                 Ok(ParseResult::ValuesDone)
1220             }
1221             ArgAction::SetTrue => {
1222                 let raw_vals = if raw_vals.is_empty() {
1223                     vec![OsString::from("true")]
1224                 } else {
1225                     raw_vals
1226                 };
1227 
1228                 if matcher.remove(arg.get_id())
1229                     && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1230                 {
1231                     return Err(ClapError::argument_conflict(
1232                         self.cmd,
1233                         arg.to_string(),
1234                         vec![arg.to_string()],
1235                         Usage::new(self.cmd).create_usage_with_title(&[]),
1236                     ));
1237                 }
1238                 self.start_custom_arg(matcher, arg, source);
1239                 ok!(self.push_arg_values(arg, raw_vals, matcher));
1240                 Ok(ParseResult::ValuesDone)
1241             }
1242             ArgAction::SetFalse => {
1243                 let raw_vals = if raw_vals.is_empty() {
1244                     vec![OsString::from("false")]
1245                 } else {
1246                     raw_vals
1247                 };
1248 
1249                 if matcher.remove(arg.get_id())
1250                     && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1251                 {
1252                     return Err(ClapError::argument_conflict(
1253                         self.cmd,
1254                         arg.to_string(),
1255                         vec![arg.to_string()],
1256                         Usage::new(self.cmd).create_usage_with_title(&[]),
1257                     ));
1258                 }
1259                 self.start_custom_arg(matcher, arg, source);
1260                 ok!(self.push_arg_values(arg, raw_vals, matcher));
1261                 Ok(ParseResult::ValuesDone)
1262             }
1263             ArgAction::Count => {
1264                 let raw_vals = if raw_vals.is_empty() {
1265                     let existing_value = *matcher
1266                         .get_one::<crate::builder::CountType>(arg.get_id().as_str())
1267                         .unwrap_or(&0);
1268                     let next_value = existing_value.saturating_add(1);
1269                     vec![OsString::from(next_value.to_string())]
1270                 } else {
1271                     raw_vals
1272                 };
1273 
1274                 matcher.remove(arg.get_id());
1275                 self.start_custom_arg(matcher, arg, source);
1276                 ok!(self.push_arg_values(arg, raw_vals, matcher));
1277                 Ok(ParseResult::ValuesDone)
1278             }
1279             ArgAction::Help => {
1280                 let use_long = match ident {
1281                     Some(Identifier::Long) => true,
1282                     Some(Identifier::Short) => false,
1283                     Some(Identifier::Index) => true,
1284                     None => true,
1285                 };
1286                 debug!("Help: use_long={}", use_long);
1287                 Err(self.help_err(use_long))
1288             }
1289             ArgAction::Version => {
1290                 let use_long = match ident {
1291                     Some(Identifier::Long) => true,
1292                     Some(Identifier::Short) => false,
1293                     Some(Identifier::Index) => true,
1294                     None => true,
1295                 };
1296                 debug!("Version: use_long={}", use_long);
1297                 Err(self.version_err(use_long))
1298             }
1299         }
1300     }
1301 
verify_num_args(&self, arg: &Arg, raw_vals: &[OsString]) -> ClapResult<()>1302     fn verify_num_args(&self, arg: &Arg, raw_vals: &[OsString]) -> ClapResult<()> {
1303         if self.cmd.is_ignore_errors_set() {
1304             return Ok(());
1305         }
1306 
1307         let actual = raw_vals.len();
1308         let expected = arg.get_num_args().expect(INTERNAL_ERROR_MSG);
1309 
1310         if 0 < expected.min_values() && actual == 0 {
1311             // Issue 665 (https://github.com/clap-rs/clap/issues/665)
1312             // Issue 1105 (https://github.com/clap-rs/clap/issues/1105)
1313             return Err(ClapError::empty_value(
1314                 self.cmd,
1315                 &super::get_possible_values_cli(arg)
1316                     .iter()
1317                     .filter(|pv| !pv.is_hide_set())
1318                     .map(|n| n.get_name().to_owned())
1319                     .collect::<Vec<_>>(),
1320                 arg.to_string(),
1321             ));
1322         } else if let Some(expected) = expected.num_values() {
1323             if expected != actual {
1324                 debug!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues");
1325                 return Err(ClapError::wrong_number_of_values(
1326                     self.cmd,
1327                     arg.to_string(),
1328                     expected,
1329                     actual,
1330                     Usage::new(self.cmd).create_usage_with_title(&[]),
1331                 ));
1332             }
1333         } else if actual < expected.min_values() {
1334             return Err(ClapError::too_few_values(
1335                 self.cmd,
1336                 arg.to_string(),
1337                 expected.min_values(),
1338                 actual,
1339                 Usage::new(self.cmd).create_usage_with_title(&[]),
1340             ));
1341         } else if expected.max_values() < actual {
1342             debug!("Validator::validate_arg_num_vals: Sending error TooManyValues");
1343             return Err(ClapError::too_many_values(
1344                 self.cmd,
1345                 raw_vals
1346                     .last()
1347                     .expect(INTERNAL_ERROR_MSG)
1348                     .to_string_lossy()
1349                     .into_owned(),
1350                 arg.to_string(),
1351                 Usage::new(self.cmd).create_usage_with_title(&[]),
1352             ));
1353         }
1354 
1355         Ok(())
1356     }
1357 
remove_overrides(&self, arg: &Arg, matcher: &mut ArgMatcher)1358     fn remove_overrides(&self, arg: &Arg, matcher: &mut ArgMatcher) {
1359         debug!("Parser::remove_overrides: id={:?}", arg.id);
1360         for override_id in &arg.overrides {
1361             debug!("Parser::remove_overrides:iter:{:?}: removing", override_id);
1362             matcher.remove(override_id);
1363         }
1364 
1365         // Override anything that can override us
1366         let mut transitive = Vec::new();
1367         for arg_id in matcher.arg_ids() {
1368             if let Some(overrider) = self.cmd.find(arg_id) {
1369                 if overrider.overrides.contains(arg.get_id()) {
1370                     transitive.push(overrider.get_id());
1371                 }
1372             }
1373         }
1374         for overrider_id in transitive {
1375             debug!("Parser::remove_overrides:iter:{:?}: removing", overrider_id);
1376             matcher.remove(overrider_id);
1377         }
1378     }
1379 
1380     #[cfg(feature = "env")]
add_env(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()>1381     fn add_env(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1382         debug!("Parser::add_env");
1383 
1384         for arg in self.cmd.get_arguments() {
1385             // Use env only if the arg was absent among command line args,
1386             // early return if this is not the case.
1387             if matcher.contains(&arg.id) {
1388                 debug!("Parser::add_env: Skipping existing arg `{}`", arg);
1389                 continue;
1390             }
1391 
1392             debug!("Parser::add_env: Checking arg `{}`", arg);
1393             if let Some((_, Some(ref val))) = arg.env {
1394                 debug!("Parser::add_env: Found an opt with value={:?}", val);
1395                 let arg_values = vec![val.to_owned()];
1396                 let trailing_idx = None;
1397                 let _ = ok!(self.react(
1398                     None,
1399                     ValueSource::EnvVariable,
1400                     arg,
1401                     arg_values,
1402                     trailing_idx,
1403                     matcher,
1404                 ));
1405             }
1406         }
1407 
1408         Ok(())
1409     }
1410 
add_defaults(&self, matcher: &mut ArgMatcher) -> ClapResult<()>1411     fn add_defaults(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1412         debug!("Parser::add_defaults");
1413 
1414         for arg in self.cmd.get_arguments() {
1415             debug!("Parser::add_defaults:iter:{}:", arg.get_id());
1416             ok!(self.add_default_value(arg, matcher));
1417         }
1418 
1419         Ok(())
1420     }
1421 
add_default_value(&self, arg: &Arg, matcher: &mut ArgMatcher) -> ClapResult<()>1422     fn add_default_value(&self, arg: &Arg, matcher: &mut ArgMatcher) -> ClapResult<()> {
1423         if !arg.default_vals_ifs.is_empty() {
1424             debug!("Parser::add_default_value: has conditional defaults");
1425             if !matcher.contains(arg.get_id()) {
1426                 for (id, val, default) in arg.default_vals_ifs.iter() {
1427                     let add = if let Some(a) = matcher.get(id) {
1428                         match val {
1429                             crate::builder::ArgPredicate::Equals(v) => {
1430                                 a.raw_vals_flatten().any(|value| v == value)
1431                             }
1432                             crate::builder::ArgPredicate::IsPresent => true,
1433                         }
1434                     } else {
1435                         false
1436                     };
1437 
1438                     if add {
1439                         if let Some(default) = default {
1440                             let arg_values = vec![default.to_os_string()];
1441                             let trailing_idx = None;
1442                             let _ = ok!(self.react(
1443                                 None,
1444                                 ValueSource::DefaultValue,
1445                                 arg,
1446                                 arg_values,
1447                                 trailing_idx,
1448                                 matcher,
1449                             ));
1450                         }
1451                         return Ok(());
1452                     }
1453                 }
1454             }
1455         } else {
1456             debug!("Parser::add_default_value: doesn't have conditional defaults");
1457         }
1458 
1459         if !arg.default_vals.is_empty() {
1460             debug!(
1461                 "Parser::add_default_value:iter:{}: has default vals",
1462                 arg.get_id()
1463             );
1464             if matcher.contains(arg.get_id()) {
1465                 debug!("Parser::add_default_value:iter:{}: was used", arg.get_id());
1466             // do nothing
1467             } else {
1468                 debug!(
1469                     "Parser::add_default_value:iter:{}: wasn't used",
1470                     arg.get_id()
1471                 );
1472                 let arg_values: Vec<_> = arg
1473                     .default_vals
1474                     .iter()
1475                     .map(crate::builder::OsStr::to_os_string)
1476                     .collect();
1477                 let trailing_idx = None;
1478                 let _ = ok!(self.react(
1479                     None,
1480                     ValueSource::DefaultValue,
1481                     arg,
1482                     arg_values,
1483                     trailing_idx,
1484                     matcher,
1485                 ));
1486             }
1487         } else {
1488             debug!(
1489                 "Parser::add_default_value:iter:{}: doesn't have default vals",
1490                 arg.get_id()
1491             );
1492 
1493             // do nothing
1494         }
1495 
1496         Ok(())
1497     }
1498 
start_custom_arg(&self, matcher: &mut ArgMatcher, arg: &Arg, source: ValueSource)1499     fn start_custom_arg(&self, matcher: &mut ArgMatcher, arg: &Arg, source: ValueSource) {
1500         if source == ValueSource::CommandLine {
1501             // With each new occurrence, remove overrides from prior occurrences
1502             self.remove_overrides(arg, matcher);
1503         }
1504         matcher.start_custom_arg(arg, source);
1505         if source.is_explicit() {
1506             for group in self.cmd.groups_for_arg(arg.get_id()) {
1507                 matcher.start_custom_group(group.clone(), source);
1508                 matcher.add_val_to(
1509                     &group,
1510                     AnyValue::new(arg.get_id().clone()),
1511                     OsString::from(arg.get_id().as_str()),
1512                 );
1513             }
1514         }
1515     }
1516 }
1517 
1518 // Error, Help, and Version Methods
1519 impl<'cmd> Parser<'cmd> {
1520     /// 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, ) -> ClapError1521     fn did_you_mean_error(
1522         &mut self,
1523         arg: &str,
1524         matcher: &mut ArgMatcher,
1525         remaining_args: &[&OsStr],
1526         trailing_values: bool,
1527     ) -> ClapError {
1528         debug!("Parser::did_you_mean_error: arg={}", arg);
1529         // Didn't match a flag or option
1530         let longs = self
1531             .cmd
1532             .get_keymap()
1533             .keys()
1534             .filter_map(|x| match x {
1535                 KeyType::Long(l) => Some(l.to_string_lossy().into_owned()),
1536                 _ => None,
1537             })
1538             .collect::<Vec<_>>();
1539         debug!("Parser::did_you_mean_error: longs={:?}", longs);
1540 
1541         let did_you_mean = suggestions::did_you_mean_flag(
1542             arg,
1543             remaining_args,
1544             longs.iter().map(|x| &x[..]),
1545             self.cmd.get_subcommands_mut(),
1546         );
1547 
1548         // Add the arg to the matches to build a proper usage string
1549         if let Some((name, _)) = did_you_mean.as_ref() {
1550             if let Some(arg) = self.cmd.get_keymap().get(&name.as_ref()) {
1551                 self.start_custom_arg(matcher, arg, ValueSource::CommandLine);
1552             }
1553         }
1554 
1555         let required = self.cmd.required_graph();
1556         let used: Vec<Id> = matcher
1557             .arg_ids()
1558             .filter(|arg_id| {
1559                 matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent)
1560             })
1561             .filter(|n| self.cmd.find(n).map_or(true, |a| !a.is_hide_set()))
1562             .cloned()
1563             .collect();
1564 
1565         // `did_you_mean` is a lot more likely and should cause us to skip the `--` suggestion
1566         //
1567         // In theory, this is only called for `--long`s, so we don't need to check
1568         let suggested_trailing_arg =
1569             did_you_mean.is_none() && !trailing_values && self.cmd.has_positionals();
1570         ClapError::unknown_argument(
1571             self.cmd,
1572             format!("--{arg}"),
1573             did_you_mean,
1574             suggested_trailing_arg,
1575             Usage::new(self.cmd)
1576                 .required(&required)
1577                 .create_usage_with_title(&used),
1578         )
1579     }
1580 
help_err(&self, use_long: bool) -> ClapError1581     fn help_err(&self, use_long: bool) -> ClapError {
1582         let styled = self.cmd.write_help_err(use_long);
1583         ClapError::display_help(self.cmd, styled)
1584     }
1585 
version_err(&self, use_long: bool) -> ClapError1586     fn version_err(&self, use_long: bool) -> ClapError {
1587         let styled = self.cmd.write_version_err(use_long);
1588         ClapError::display_version(self.cmd, styled)
1589     }
1590 }
1591 
1592 #[derive(Debug, PartialEq, Eq)]
1593 pub(crate) enum ParseState {
1594     ValuesDone,
1595     Opt(Id),
1596     Pos(Id),
1597 }
1598 
1599 /// Recoverable Parsing results.
1600 #[derive(Debug, PartialEq, Clone)]
1601 #[must_use]
1602 enum ParseResult {
1603     FlagSubCommand(String),
1604     Opt(Id),
1605     ValuesDone,
1606     /// Value attached to the short flag is not consumed(e.g. 'u' for `-cu` is
1607     /// not consumed).
1608     AttachedValueNotConsumed,
1609     /// This long flag doesn't need a value but is provided one.
1610     UnneededAttachedValue {
1611         rest: String,
1612         used: Vec<Id>,
1613         arg: String,
1614     },
1615     /// This flag might be an hyphen Value.
1616     MaybeHyphenValue,
1617     /// Equals required but not provided.
1618     EqualsNotProvided {
1619         arg: String,
1620     },
1621     /// Failed to match a Arg.
1622     NoMatchingArg {
1623         arg: String,
1624     },
1625     /// No argument found e.g. parser is given `-` when parsing a flag.
1626     NoArg,
1627 }
1628 
1629 #[derive(Clone, Debug, PartialEq, Eq)]
1630 pub(crate) struct PendingArg {
1631     pub(crate) id: Id,
1632     pub(crate) ident: Option<Identifier>,
1633     pub(crate) raw_vals: Vec<OsString>,
1634     pub(crate) trailing_idx: Option<usize>,
1635 }
1636 
1637 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1638 pub(crate) enum Identifier {
1639     Short,
1640     Long,
1641     Index,
1642 }
1643