Skip to main content

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