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