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