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