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