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