clap_builder/parser/
parser.rs

1// Std
2use std::{
3    cell::Cell,
4    ffi::{OsStr, OsString},
5};
6
7use clap_lex::OsStrExt as _;
8
9// Internal
10use crate::builder::{Arg, Command};
11use crate::error::Error as ClapError;
12use crate::error::Result as ClapResult;
13use crate::mkeymap::KeyType;
14use crate::output::Usage;
15use crate::parser::features::suggestions;
16use crate::parser::{ArgMatcher, SubCommand};
17use crate::parser::{Validator, ValueSource};
18use crate::util::AnyValue;
19use crate::util::Id;
20use crate::ArgAction;
21use crate::INTERNAL_ERROR_MSG;
22
23pub(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
34impl<'cmd> Parser<'cmd> {
35    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
46impl<'cmd> Parser<'cmd> {
47    // The actual parsing function
48    #[allow(clippy::cognitive_complexity)]
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
484    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)
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)
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
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
659    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 single '-' 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
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
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_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
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_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
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
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
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
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
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
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
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")]
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
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
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
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
1525impl<'cmd> Parser<'cmd> {
1526    /// Is only used for the long flag(which is the only one needs fuzzy searching)
1527    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        // with the one exception being that the CLI is trying to capture arguments
1574        //
1575        // In theory, this is only called for `--long`s, so we don't need to check
1576        let suggested_trailing_arg = (did_you_mean.is_none()
1577            || self
1578                .cmd
1579                .get_positionals()
1580                .any(|arg| arg.is_last_set() || arg.is_trailing_var_arg_set()))
1581            && !trailing_values
1582            && self.cmd.has_positionals();
1583        ClapError::unknown_argument(
1584            self.cmd,
1585            format!("--{arg}"),
1586            did_you_mean,
1587            suggested_trailing_arg,
1588            Usage::new(self.cmd)
1589                .required(&required)
1590                .create_usage_with_title(&used),
1591        )
1592    }
1593
1594    fn help_err(&self, use_long: bool) -> ClapError {
1595        let styled = self.cmd.write_help_err(use_long);
1596        ClapError::display_help(self.cmd, styled)
1597    }
1598
1599    fn version_err(&self, use_long: bool) -> ClapError {
1600        let styled = self.cmd.write_version_err(use_long);
1601        ClapError::display_version(self.cmd, styled)
1602    }
1603}
1604
1605#[derive(Debug, PartialEq, Eq)]
1606pub(crate) enum ParseState {
1607    ValuesDone,
1608    Opt(Id),
1609    Pos(Id),
1610}
1611
1612/// Recoverable Parsing results.
1613#[derive(Debug, PartialEq, Clone)]
1614#[must_use]
1615enum ParseResult {
1616    FlagSubCommand(String),
1617    Opt(Id),
1618    ValuesDone,
1619    /// Value attached to the short flag is not consumed(e.g. 'u' for `-cu` is
1620    /// not consumed).
1621    AttachedValueNotConsumed,
1622    /// This long flag doesn't need a value but is provided one.
1623    UnneededAttachedValue {
1624        rest: String,
1625        used: Vec<Id>,
1626        arg: String,
1627    },
1628    /// This flag might be an hyphen Value.
1629    MaybeHyphenValue,
1630    /// Equals required but not provided.
1631    EqualsNotProvided {
1632        arg: String,
1633    },
1634    /// Failed to match a Arg.
1635    NoMatchingArg {
1636        arg: String,
1637    },
1638    /// No argument found e.g. parser is given `-` when parsing a flag.
1639    NoArg,
1640}
1641
1642#[derive(Clone, Debug, PartialEq, Eq)]
1643pub(crate) struct PendingArg {
1644    pub(crate) id: Id,
1645    pub(crate) ident: Option<Identifier>,
1646    pub(crate) raw_vals: Vec<OsString>,
1647    pub(crate) trailing_idx: Option<usize>,
1648}
1649
1650#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1651pub(crate) enum Identifier {
1652    Short,
1653    Long,
1654    Index,
1655}