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