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