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