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 .filter_map(|id| self.cmd.find(id).map(|a| a.to_string()))
488 .collect(),
489 Usage::new(self.cmd).create_usage_with_title(&[]),
490 ));
491 }
492 let sc_name = self
493 .cmd
494 .find_subcommand(pos_sc_name)
495 .expect(INTERNAL_ERROR_MSG)
496 .get_name()
497 .to_owned();
498 ok!(self.parse_subcommand(&sc_name, matcher, raw_args, args_cursor, keep_state));
499 }
500
501 Ok(())
502 }
503
504 fn match_arg_error(
505 &self,
506 arg_os: &clap_lex::ParsedArg<'_>,
507 valid_arg_found: bool,
508 trailing_values: bool,
509 matcher: &ArgMatcher,
510 ) -> ClapError {
511 if trailing_values {
513 if self
515 .possible_subcommand(arg_os.to_value(), valid_arg_found)
516 .is_some()
517 {
518 return ClapError::unnecessary_double_dash(
519 self.cmd,
520 arg_os.display().to_string(),
521 Usage::new(self.cmd).create_usage_with_title(&[]),
522 );
523 }
524 }
525
526 let suggested_trailing_arg = !trailing_values
527 && self.cmd.has_positionals()
528 && (arg_os.is_long() || arg_os.is_short());
529
530 if self.cmd.has_subcommands() {
531 if self.cmd.is_args_conflicts_with_subcommands_set() && valid_arg_found {
532 return ClapError::subcommand_conflict(
533 self.cmd,
534 arg_os.display().to_string(),
535 matcher
536 .arg_ids()
537 .filter_map(|id| self.cmd.find(id).map(|a| a.to_string()))
538 .collect(),
539 Usage::new(self.cmd).create_usage_with_title(&[]),
540 );
541 }
542
543 let candidates = suggestions::did_you_mean(
544 &arg_os.display().to_string(),
545 self.cmd.all_subcommand_names(),
546 );
547 if !candidates.is_empty() {
549 return ClapError::invalid_subcommand(
550 self.cmd,
551 arg_os.display().to_string(),
552 candidates,
553 self.cmd.get_bin_name_fallback().to_owned(),
554 suggested_trailing_arg,
555 Usage::new(self.cmd).create_usage_with_title(&[]),
556 );
557 }
558
559 if !self.cmd.has_positionals() || self.cmd.is_infer_subcommands_set() {
561 return ClapError::unrecognized_subcommand(
562 self.cmd,
563 arg_os.display().to_string(),
564 Usage::new(self.cmd).create_usage_with_title(&[]),
565 );
566 }
567 }
568
569 ClapError::unknown_argument(
570 self.cmd,
571 arg_os.display().to_string(),
572 None,
573 suggested_trailing_arg,
574 Usage::new(self.cmd).create_usage_with_title(&[]),
575 )
576 }
577
578 fn possible_subcommand(
580 &self,
581 arg: Result<&str, &OsStr>,
582 valid_arg_found: bool,
583 ) -> Option<&str> {
584 debug!("Parser::possible_subcommand: arg={arg:?}");
585 let arg = some!(arg.ok());
586
587 if !(self.cmd.is_args_conflicts_with_subcommands_set() && valid_arg_found) {
588 if self.cmd.is_infer_subcommands_set() {
589 let mut iter = self.cmd.get_subcommands().filter_map(|s| {
592 if s.get_name().starts_with(arg) {
593 return Some(s.get_name());
594 }
595
596 s.get_all_aliases().find(|s| s.starts_with(arg))
599 });
600
601 if let name @ Some(_) = iter.next() {
602 if iter.next().is_none() {
603 return name;
604 }
605 }
606 }
607 if let Some(sc) = self.cmd.find_subcommand(arg) {
610 return Some(sc.get_name());
611 }
612 }
613 None
614 }
615
616 fn possible_long_flag_subcommand(&self, arg: &str) -> Option<&str> {
618 debug!("Parser::possible_long_flag_subcommand: arg={arg:?}");
619 if self.cmd.is_infer_subcommands_set() {
620 let mut iter = self.cmd.get_subcommands().filter_map(|sc| {
621 sc.get_long_flag().and_then(|long| {
622 if long.starts_with(arg) {
623 Some(sc.get_name())
624 } else {
625 sc.get_all_long_flag_aliases().find_map(|alias| {
626 if alias.starts_with(arg) {
627 Some(sc.get_name())
628 } else {
629 None
630 }
631 })
632 }
633 })
634 });
635
636 if let name @ Some(_) = iter.next() {
637 if iter.next().is_none() {
638 return name;
639 }
640 }
641 }
642 if let Some(sc_name) = self.cmd.find_long_subcmd(arg) {
643 return Some(sc_name);
644 }
645 None
646 }
647
648 fn parse_help_subcommand(
649 &self,
650 cmds: impl Iterator<Item = &'cmd OsStr>,
651 ) -> ClapResult<std::convert::Infallible> {
652 debug!("Parser::parse_help_subcommand");
653
654 let mut cmd = self.cmd.clone();
655 let sc = {
656 let mut sc = &mut cmd;
657
658 for cmd in cmds {
659 sc = if let Some(sc_name) =
660 sc.find_subcommand(cmd).map(|sc| sc.get_name().to_owned())
661 {
662 sc._build_subcommand(&sc_name).unwrap()
663 } else {
664 return Err(ClapError::unrecognized_subcommand(
665 sc,
666 cmd.to_string_lossy().into_owned(),
667 Usage::new(sc).create_usage_with_title(&[]),
668 ));
669 };
670 }
671
672 sc
673 };
674 let parser = Parser::new(sc);
675
676 Err(parser.help_err(true))
677 }
678
679 fn is_new_arg(&self, next: &clap_lex::ParsedArg<'_>, current_positional: &Arg) -> bool {
680 #![allow(clippy::needless_bool)] debug!(
683 "Parser::is_new_arg: {:?}:{}",
684 next.to_value_os(),
685 current_positional.get_id()
686 );
687
688 if self.cmd[current_positional.get_id()].is_allow_hyphen_values_set()
689 || (self.cmd[current_positional.get_id()].is_allow_negative_numbers_set()
690 && next.is_negative_number())
691 {
692 debug!("Parser::is_new_arg: Allow hyphen");
694 false
695 } else if next.is_long() {
696 debug!("Parser::is_new_arg: --<something> found");
698 true
699 } else if next.is_short() {
700 debug!("Parser::is_new_arg: -<something> found");
703 true
704 } else {
705 debug!("Parser::is_new_arg: value");
707 false
708 }
709 }
710
711 fn parse_subcommand(
712 &mut self,
713 sc_name: &str,
714 matcher: &mut ArgMatcher,
715 raw_args: &mut clap_lex::RawArgs,
716 args_cursor: clap_lex::ArgCursor,
717 keep_state: bool,
718 ) -> ClapResult<()> {
719 debug!("Parser::parse_subcommand");
720
721 let partial_parsing_enabled = self.cmd.is_ignore_errors_set();
722
723 if let Some(sc) = self.cmd._build_subcommand(sc_name) {
724 let mut sc_matcher = ArgMatcher::new(sc);
725
726 debug!(
727 "Parser::parse_subcommand: About to parse sc={}",
728 sc.get_name()
729 );
730
731 {
732 let mut p = Parser::new(sc);
733 if keep_state {
736 p.cur_idx.set(self.cur_idx.get());
737 p.flag_subcmd_at = self.flag_subcmd_at;
738 p.flag_subcmd_skip = self.flag_subcmd_skip;
739 }
740 if let Err(error) = p.get_matches_with(&mut sc_matcher, raw_args, args_cursor) {
741 if partial_parsing_enabled {
742 debug!("Parser::parse_subcommand: ignored error in subcommand {sc_name}: {error:?}");
743 } else {
744 return Err(error);
745 }
746 }
747 }
748 matcher.subcommand(SubCommand {
749 name: sc.get_name().to_owned(),
750 matches: sc_matcher.into_inner(),
751 });
752 }
753 Ok(())
754 }
755
756 fn parse_long_arg(
757 &mut self,
758 matcher: &mut ArgMatcher,
759 long_arg: Result<&str, &OsStr>,
760 long_value: Option<&OsStr>,
761 parse_state: &ParseState,
762 pos_counter: usize,
763 valid_arg_found: &mut bool,
764 ) -> ClapResult<ParseResult> {
765 debug!("Parser::parse_long_arg");
767
768 #[allow(clippy::blocks_in_conditions)]
769 if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if
770 self.cmd[opt].is_allow_hyphen_values_set())
771 {
772 debug!("Parser::parse_long_arg: prior arg accepts hyphenated values",);
773 return Ok(ParseResult::MaybeHyphenValue);
774 }
775
776 debug!("Parser::parse_long_arg: Does it contain '='...");
777 let long_arg = match long_arg {
778 Ok(long_arg) => long_arg,
779 Err(long_arg_os) => {
780 return Ok(ParseResult::NoMatchingArg {
781 arg: long_arg_os.to_string_lossy().into_owned(),
782 })
783 }
784 };
785 if long_arg.is_empty() {
786 debug_assert!(
787 long_value.is_some(),
788 "`--` should be filtered out before this point"
789 );
790 }
791
792 let arg = if let Some(arg) = self.cmd.get_keymap().get(long_arg) {
793 debug!("Parser::parse_long_arg: Found valid arg or flag '{arg}'");
794 Some((long_arg, arg))
795 } else if self.cmd.is_infer_long_args_set() {
796 let mut iter = self.cmd.get_arguments().filter_map(|a| {
797 if let Some(long) = a.get_long() {
798 if long.starts_with(long_arg) {
799 return Some((long, a));
800 }
801 }
802 a.aliases
803 .iter()
804 .find_map(|(alias, _)| alias.starts_with(long_arg).then(|| (alias.as_str(), a)))
805 });
806
807 iter.next().filter(|_| iter.next().is_none())
808 } else {
809 None
810 };
811
812 if let Some((_long_arg, arg)) = arg {
813 let ident = Identifier::Long;
814 *valid_arg_found = true;
815 if arg.is_takes_value_set() {
816 debug!(
817 "Parser::parse_long_arg({:?}): Found an arg with value '{:?}'",
818 long_arg, &long_value
819 );
820 let has_eq = long_value.is_some();
821 self.parse_opt_value(ident, long_value, arg, matcher, has_eq)
822 } else if let Some(rest) = long_value {
823 let required = self.cmd.required_graph();
824 debug!("Parser::parse_long_arg({long_arg:?}): Got invalid literal `{rest:?}`");
825 let mut used: Vec<Id> = matcher
826 .arg_ids()
827 .filter(|arg_id| {
828 matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent)
829 })
830 .filter(|&n| {
831 self.cmd
832 .find(n)
833 .map(|a| !(a.is_hide_set() || required.contains(a.get_id())))
834 .unwrap_or(true)
835 })
836 .cloned()
837 .collect();
838 used.push(arg.get_id().clone());
839
840 Ok(ParseResult::UnneededAttachedValue {
841 rest: rest.to_string_lossy().into_owned(),
842 used,
843 arg: arg.to_string(),
844 })
845 } else {
846 debug!("Parser::parse_long_arg({long_arg:?}): Presence validated");
847 let trailing_idx = None;
848 self.react(
849 Some(ident),
850 ValueSource::CommandLine,
851 arg,
852 vec![],
853 trailing_idx,
854 matcher,
855 )
856 }
857 } else if let Some(sc_name) = self.possible_long_flag_subcommand(long_arg) {
858 Ok(ParseResult::FlagSubCommand(sc_name.to_string()))
859 } else if self
860 .cmd
861 .get_keymap()
862 .get(&pos_counter)
863 .map(|arg| arg.is_allow_hyphen_values_set() && !arg.is_last_set())
864 .unwrap_or_default()
865 {
866 debug!("Parser::parse_long_args: positional at {pos_counter} allows hyphens");
867 Ok(ParseResult::MaybeHyphenValue)
868 } else {
869 Ok(ParseResult::NoMatchingArg {
870 arg: long_arg.to_owned(),
871 })
872 }
873 }
874
875 fn parse_short_arg(
876 &mut self,
877 matcher: &mut ArgMatcher,
878 mut short_arg: clap_lex::ShortFlags<'_>,
879 parse_state: &ParseState,
880 pos_counter: usize,
882 valid_arg_found: &mut bool,
883 ) -> ClapResult<ParseResult> {
884 debug!("Parser::parse_short_arg: short_arg={short_arg:?}");
885
886 #[allow(clippy::blocks_in_conditions)]
887 if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt)
888 if self.cmd[opt].is_allow_hyphen_values_set() || (self.cmd[opt].is_allow_negative_numbers_set() && short_arg.is_negative_number()))
889 {
890 debug!("Parser::parse_short_args: prior arg accepts hyphenated values",);
891 return Ok(ParseResult::MaybeHyphenValue);
892 } else if self
893 .cmd
894 .get_keymap()
895 .get(&pos_counter)
896 .map(|arg| arg.is_allow_negative_numbers_set())
897 .unwrap_or_default()
898 && short_arg.is_negative_number()
899 {
900 debug!("Parser::parse_short_arg: negative number");
901 return Ok(ParseResult::MaybeHyphenValue);
902 } else if self
903 .cmd
904 .get_keymap()
905 .get(&pos_counter)
906 .map(|arg| arg.is_allow_hyphen_values_set() && !arg.is_last_set())
907 .unwrap_or_default()
908 && short_arg
909 .clone()
910 .any(|c| !c.map(|c| self.cmd.contains_short(c)).unwrap_or_default())
911 {
912 debug!("Parser::parse_short_args: positional at {pos_counter} allows hyphens");
913 return Ok(ParseResult::MaybeHyphenValue);
914 }
915
916 let mut ret = ParseResult::NoArg;
917
918 let skip = self.flag_subcmd_skip;
919 self.flag_subcmd_skip = 0;
920 let res = short_arg.advance_by(skip);
921 debug_assert_eq!(
922 res,
923 Ok(()),
924 "tracking of `flag_subcmd_skip` is off for `{short_arg:?}`"
925 );
926 while let Some(c) = short_arg.next_flag() {
927 let c = match c {
928 Ok(c) => c,
929 Err(rest) => {
930 return Ok(ParseResult::NoMatchingArg {
931 arg: format!("-{}", rest.to_string_lossy()),
932 });
933 }
934 };
935 debug!("Parser::parse_short_arg:iter:{c}");
936
937 if let Some(arg) = self.cmd.get_keymap().get(&c) {
942 let ident = Identifier::Short;
943 debug!("Parser::parse_short_arg:iter:{c}: Found valid opt or flag");
944 *valid_arg_found = true;
945 if !arg.is_takes_value_set() {
946 let arg_values = Vec::new();
947 let trailing_idx = None;
948 ret = ok!(self.react(
949 Some(ident),
950 ValueSource::CommandLine,
951 arg,
952 arg_values,
953 trailing_idx,
954 matcher,
955 ));
956 continue;
957 }
958
959 let val = short_arg.clone().next_value_os().unwrap_or_default();
963 debug!("Parser::parse_short_arg:iter:{c}: val={val:?}, short_arg={short_arg:?}");
964 let val = Some(val).filter(|v| !v.is_empty());
965
966 let (val, has_eq) = if let Some(val) = val.and_then(|v| v.strip_prefix("=")) {
974 (Some(val), true)
975 } else {
976 (val, false)
977 };
978 match ok!(self.parse_opt_value(ident, val, arg, matcher, has_eq)) {
979 ParseResult::AttachedValueNotConsumed => continue,
980 x => return Ok(x),
981 }
982 }
983
984 return if let Some(sc_name) = self.cmd.find_short_subcmd(c) {
985 debug!("Parser::parse_short_arg:iter:{c}: subcommand={sc_name}");
986 ok!(self.resolve_pending(matcher));
988 self.cur_idx.set(self.cur_idx.get() + 1);
989 debug!("Parser::parse_short_arg: cur_idx:={}", self.cur_idx.get());
990
991 let name = sc_name.to_string();
992 let cur_idx = self.cur_idx.get();
996 self.flag_subcmd_at.get_or_insert(cur_idx);
997 let done_short_args = short_arg.is_empty();
998 if done_short_args {
999 self.flag_subcmd_at = None;
1000 }
1001 Ok(ParseResult::FlagSubCommand(name))
1002 } else {
1003 Ok(ParseResult::NoMatchingArg {
1004 arg: format!("-{c}"),
1005 })
1006 };
1007 }
1008 Ok(ret)
1009 }
1010
1011 fn parse_opt_value(
1012 &self,
1013 ident: Identifier,
1014 attached_value: Option<&OsStr>,
1015 arg: &Arg,
1016 matcher: &mut ArgMatcher,
1017 has_eq: bool,
1018 ) -> ClapResult<ParseResult> {
1019 debug!(
1020 "Parser::parse_opt_value; arg={}, val={:?}, has_eq={:?}",
1021 arg.get_id(),
1022 attached_value,
1023 has_eq
1024 );
1025 debug!("Parser::parse_opt_value; arg.settings={:?}", arg.settings);
1026
1027 debug!("Parser::parse_opt_value; Checking for val...");
1028 if arg.is_require_equals_set() && !has_eq {
1030 if arg.get_min_vals() == 0 {
1031 debug!("Requires equals, but min_vals == 0");
1032 let arg_values = Vec::new();
1033 let trailing_idx = None;
1034 let react_result = ok!(self.react(
1035 Some(ident),
1036 ValueSource::CommandLine,
1037 arg,
1038 arg_values,
1039 trailing_idx,
1040 matcher,
1041 ));
1042 debug_assert_eq!(react_result, ParseResult::ValuesDone);
1043 if attached_value.is_some() {
1044 Ok(ParseResult::AttachedValueNotConsumed)
1045 } else {
1046 Ok(ParseResult::ValuesDone)
1047 }
1048 } else {
1049 debug!("Requires equals but not provided. Error.");
1050 Ok(ParseResult::EqualsNotProvided {
1051 arg: arg.to_string(),
1052 })
1053 }
1054 } else if let Some(v) = attached_value {
1055 let arg_values = vec![v.to_owned()];
1056 let trailing_idx = None;
1057 let react_result = ok!(self.react(
1058 Some(ident),
1059 ValueSource::CommandLine,
1060 arg,
1061 arg_values,
1062 trailing_idx,
1063 matcher,
1064 ));
1065 debug_assert_eq!(react_result, ParseResult::ValuesDone);
1066 Ok(ParseResult::ValuesDone)
1068 } else {
1069 debug!("Parser::parse_opt_value: More arg vals required...");
1070 ok!(self.resolve_pending(matcher));
1071 let trailing_values = false;
1072 matcher.pending_values_mut(arg.get_id(), Some(ident), trailing_values);
1073 Ok(ParseResult::Opt(arg.get_id().clone()))
1074 }
1075 }
1076
1077 fn check_terminator(&self, arg: &Arg, val: &OsStr) -> Option<ParseResult> {
1078 if Some(val) == arg.terminator.as_ref().map(|s| OsStr::new(s.as_str())) {
1079 debug!("Parser::check_terminator: terminator={:?}", arg.terminator);
1080 Some(ParseResult::ValuesDone)
1081 } else {
1082 None
1083 }
1084 }
1085
1086 fn push_arg_values(
1087 &self,
1088 arg: &Arg,
1089 raw_vals: Vec<OsString>,
1090 source: ValueSource,
1091 matcher: &mut ArgMatcher,
1092 ) -> ClapResult<()> {
1093 debug!("Parser::push_arg_values: {raw_vals:?}");
1094
1095 for raw_val in raw_vals {
1096 self.cur_idx.set(self.cur_idx.get() + 1);
1098 debug!(
1099 "Parser::add_single_val_to_arg: cur_idx:={}",
1100 self.cur_idx.get()
1101 );
1102 let value_parser = arg.get_value_parser();
1103 let val = ok!(value_parser.parse_ref(self.cmd, Some(arg), &raw_val, source));
1104
1105 matcher.add_val_to(arg.get_id(), val, raw_val);
1106 matcher.add_index_to(arg.get_id(), self.cur_idx.get());
1107 }
1108
1109 Ok(())
1110 }
1111
1112 fn resolve_pending(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1113 let pending = match matcher.take_pending() {
1114 Some(pending) => pending,
1115 None => {
1116 return Ok(());
1117 }
1118 };
1119
1120 debug!("Parser::resolve_pending: id={:?}", pending.id);
1121 let arg = self.cmd.find(&pending.id).expect(INTERNAL_ERROR_MSG);
1122 let _ = ok!(self.react(
1123 pending.ident,
1124 ValueSource::CommandLine,
1125 arg,
1126 pending.raw_vals,
1127 pending.trailing_idx,
1128 matcher,
1129 ));
1130
1131 Ok(())
1132 }
1133
1134 fn react(
1135 &self,
1136 ident: Option<Identifier>,
1137 source: ValueSource,
1138 arg: &Arg,
1139 mut raw_vals: Vec<OsString>,
1140 mut trailing_idx: Option<usize>,
1141 matcher: &mut ArgMatcher,
1142 ) -> ClapResult<ParseResult> {
1143 ok!(self.resolve_pending(matcher));
1144
1145 debug!(
1146 "Parser::react action={:?}, identifier={:?}, source={:?}",
1147 arg.get_action(),
1148 ident,
1149 source
1150 );
1151
1152 if source == ValueSource::CommandLine {
1155 ok!(self.verify_num_args(arg, &raw_vals));
1156 }
1157
1158 if raw_vals.is_empty() {
1159 if !arg.default_missing_vals.is_empty() {
1161 debug!("Parser::react: has default_missing_vals");
1162 trailing_idx = None;
1163 raw_vals.extend(
1164 arg.default_missing_vals
1165 .iter()
1166 .map(|s| s.as_os_str().to_owned()),
1167 );
1168 }
1169 }
1170
1171 if let Some(val_delim) = arg.get_value_delimiter() {
1172 if self.cmd.is_dont_delimit_trailing_values_set() && trailing_idx == Some(0) {
1173 } else {
1175 let mut val_delim_buffer = [0; 4];
1176 let val_delim = val_delim.encode_utf8(&mut val_delim_buffer);
1177 let mut split_raw_vals = Vec::with_capacity(raw_vals.len());
1178 for (i, raw_val) in raw_vals.into_iter().enumerate() {
1179 if !raw_val.contains(val_delim)
1180 || (self.cmd.is_dont_delimit_trailing_values_set()
1181 && trailing_idx == Some(i))
1182 {
1183 split_raw_vals.push(raw_val);
1184 } else {
1185 split_raw_vals.extend(raw_val.split(val_delim).map(|x| x.to_owned()));
1186 }
1187 }
1188 raw_vals = split_raw_vals;
1189 }
1190 }
1191
1192 match arg.get_action() {
1193 ArgAction::Set => {
1194 if source == ValueSource::CommandLine
1195 && matches!(ident, Some(Identifier::Short) | Some(Identifier::Long))
1196 {
1197 self.cur_idx.set(self.cur_idx.get() + 1);
1199 debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
1200 }
1201 if matcher.remove(arg.get_id())
1202 && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1203 {
1204 return Err(ClapError::argument_conflict(
1205 self.cmd,
1206 arg.to_string(),
1207 vec![arg.to_string()],
1208 Usage::new(self.cmd).create_usage_with_title(&[]),
1209 ));
1210 }
1211 self.start_custom_arg(matcher, arg, source);
1212 ok!(self.push_arg_values(arg, raw_vals, source, matcher));
1213 if cfg!(debug_assertions) && matcher.needs_more_vals(arg) {
1214 debug!(
1215 "Parser::react not enough values passed in, leaving it to the validator to complain",
1216 );
1217 }
1218 Ok(ParseResult::ValuesDone)
1219 }
1220 ArgAction::Append => {
1221 if source == ValueSource::CommandLine
1222 && matches!(ident, Some(Identifier::Short) | Some(Identifier::Long))
1223 {
1224 self.cur_idx.set(self.cur_idx.get() + 1);
1226 debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
1227 }
1228 self.start_custom_arg(matcher, arg, source);
1229 ok!(self.push_arg_values(arg, raw_vals, source, matcher));
1230 if cfg!(debug_assertions) && matcher.needs_more_vals(arg) {
1231 debug!(
1232 "Parser::react not enough values passed in, leaving it to the validator to complain",
1233 );
1234 }
1235 Ok(ParseResult::ValuesDone)
1236 }
1237 ArgAction::SetTrue => {
1238 let raw_vals = if raw_vals.is_empty() {
1239 vec![OsString::from("true")]
1240 } else {
1241 raw_vals
1242 };
1243
1244 if matcher.remove(arg.get_id())
1245 && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1246 {
1247 return Err(ClapError::argument_conflict(
1248 self.cmd,
1249 arg.to_string(),
1250 vec![arg.to_string()],
1251 Usage::new(self.cmd).create_usage_with_title(&[]),
1252 ));
1253 }
1254 self.start_custom_arg(matcher, arg, source);
1255 ok!(self.push_arg_values(arg, raw_vals, source, matcher));
1256 Ok(ParseResult::ValuesDone)
1257 }
1258 ArgAction::SetFalse => {
1259 let raw_vals = if raw_vals.is_empty() {
1260 vec![OsString::from("false")]
1261 } else {
1262 raw_vals
1263 };
1264
1265 if matcher.remove(arg.get_id())
1266 && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1267 {
1268 return Err(ClapError::argument_conflict(
1269 self.cmd,
1270 arg.to_string(),
1271 vec![arg.to_string()],
1272 Usage::new(self.cmd).create_usage_with_title(&[]),
1273 ));
1274 }
1275 self.start_custom_arg(matcher, arg, source);
1276 ok!(self.push_arg_values(arg, raw_vals, source, matcher));
1277 Ok(ParseResult::ValuesDone)
1278 }
1279 ArgAction::Count => {
1280 let raw_vals = if raw_vals.is_empty() {
1281 let existing_value = *matcher
1282 .get_one::<crate::builder::CountType>(arg.get_id().as_str())
1283 .unwrap_or(&0);
1284 let next_value = existing_value.saturating_add(1);
1285 vec![OsString::from(next_value.to_string())]
1286 } else {
1287 raw_vals
1288 };
1289
1290 matcher.remove(arg.get_id());
1291 self.start_custom_arg(matcher, arg, source);
1292 ok!(self.push_arg_values(arg, raw_vals, source, matcher));
1293 Ok(ParseResult::ValuesDone)
1294 }
1295 ArgAction::Help => {
1296 let use_long = match ident {
1297 Some(Identifier::Long) => true,
1298 Some(Identifier::Short) => false,
1299 Some(Identifier::Index) => true,
1300 None => true,
1301 };
1302 debug!("Help: use_long={use_long}");
1303 Err(self.help_err(use_long))
1304 }
1305 ArgAction::HelpShort => {
1306 let use_long = false;
1307 debug!("Help: use_long={use_long}");
1308 Err(self.help_err(use_long))
1309 }
1310 ArgAction::HelpLong => {
1311 let use_long = true;
1312 debug!("Help: use_long={use_long}");
1313 Err(self.help_err(use_long))
1314 }
1315 ArgAction::Version => {
1316 let use_long = match ident {
1317 Some(Identifier::Long) => true,
1318 Some(Identifier::Short) => false,
1319 Some(Identifier::Index) => true,
1320 None => true,
1321 };
1322 debug!("Version: use_long={use_long}");
1323 Err(self.version_err(use_long))
1324 }
1325 }
1326 }
1327
1328 fn verify_num_args(&self, arg: &Arg, raw_vals: &[OsString]) -> ClapResult<()> {
1329 if self.cmd.is_ignore_errors_set() {
1330 return Ok(());
1331 }
1332
1333 let actual = raw_vals.len();
1334 let expected = arg.get_num_args().expect(INTERNAL_ERROR_MSG);
1335
1336 if 0 < expected.min_values() && actual == 0 {
1337 return Err(ClapError::empty_value(
1340 self.cmd,
1341 &super::get_possible_values_cli(arg)
1342 .iter()
1343 .filter(|pv| !pv.is_hide_set())
1344 .map(|n| n.get_name().to_owned())
1345 .collect::<Vec<_>>(),
1346 arg.to_string(),
1347 ));
1348 } else if let Some(expected) = expected.num_values() {
1349 if expected != actual {
1350 debug!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues");
1351 return Err(ClapError::wrong_number_of_values(
1352 self.cmd,
1353 arg.to_string(),
1354 expected,
1355 actual,
1356 Usage::new(self.cmd).create_usage_with_title(&[]),
1357 ));
1358 }
1359 } else if actual < expected.min_values() {
1360 return Err(ClapError::too_few_values(
1361 self.cmd,
1362 arg.to_string(),
1363 expected.min_values(),
1364 actual,
1365 Usage::new(self.cmd).create_usage_with_title(&[]),
1366 ));
1367 } else if expected.max_values() < actual {
1368 debug!("Validator::validate_arg_num_vals: Sending error TooManyValues");
1369 return Err(ClapError::too_many_values(
1370 self.cmd,
1371 raw_vals
1372 .last()
1373 .expect(INTERNAL_ERROR_MSG)
1374 .to_string_lossy()
1375 .into_owned(),
1376 arg.to_string(),
1377 Usage::new(self.cmd).create_usage_with_title(&[]),
1378 ));
1379 }
1380
1381 Ok(())
1382 }
1383
1384 fn remove_overrides(&self, arg: &Arg, matcher: &mut ArgMatcher) {
1385 debug!("Parser::remove_overrides: id={:?}", arg.id);
1386 for override_id in &arg.overrides {
1387 debug!("Parser::remove_overrides:iter:{override_id:?}: removing");
1388 matcher.remove(override_id);
1389 }
1390
1391 let mut transitive = Vec::new();
1393 for arg_id in matcher.arg_ids() {
1394 if let Some(overrider) = self.cmd.find(arg_id) {
1395 if overrider.overrides.contains(arg.get_id()) {
1396 transitive.push(overrider.get_id());
1397 }
1398 }
1399 }
1400 for overrider_id in transitive {
1401 debug!("Parser::remove_overrides:iter:{overrider_id:?}: removing");
1402 matcher.remove(overrider_id);
1403 }
1404 }
1405
1406 #[cfg(feature = "env")]
1407 fn add_env(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1408 debug!("Parser::add_env");
1409
1410 for arg in self.cmd.get_arguments() {
1411 if matcher.contains(&arg.id) {
1414 debug!("Parser::add_env: Skipping existing arg `{arg}`");
1415 continue;
1416 }
1417
1418 debug!("Parser::add_env: Checking arg `{arg}`");
1419 if let Some((_, Some(ref val))) = arg.env {
1420 debug!("Parser::add_env: Found an opt with value={val:?}");
1421 let arg_values = vec![val.to_owned()];
1422 let trailing_idx = None;
1423 let _ = ok!(self.react(
1424 None,
1425 ValueSource::EnvVariable,
1426 arg,
1427 arg_values,
1428 trailing_idx,
1429 matcher,
1430 ));
1431 }
1432 }
1433
1434 Ok(())
1435 }
1436
1437 fn add_defaults(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
1438 debug!("Parser::add_defaults");
1439
1440 for arg in self.cmd.get_arguments() {
1441 debug!("Parser::add_defaults:iter:{}:", arg.get_id());
1442 ok!(self.add_default_value(arg, matcher));
1443 }
1444
1445 Ok(())
1446 }
1447
1448 fn add_default_value(&self, arg: &Arg, matcher: &mut ArgMatcher) -> ClapResult<()> {
1449 if !arg.default_vals_ifs.is_empty() {
1450 debug!("Parser::add_default_value: has conditional defaults");
1451 if !matcher.contains(arg.get_id()) {
1452 for (id, val, default) in arg.default_vals_ifs.iter() {
1453 let add = if let Some(a) = matcher.get(id) {
1454 match val {
1455 crate::builder::ArgPredicate::Equals(v) => {
1456 a.raw_vals_flatten().any(|value| v == value)
1457 }
1458 crate::builder::ArgPredicate::IsPresent => true,
1459 }
1460 } else {
1461 false
1462 };
1463
1464 if add {
1465 if let Some(default) = default {
1466 let arg_values = vec![default.to_os_string()];
1467 let trailing_idx = None;
1468 let _ = ok!(self.react(
1469 None,
1470 ValueSource::DefaultValue,
1471 arg,
1472 arg_values,
1473 trailing_idx,
1474 matcher,
1475 ));
1476 }
1477 return Ok(());
1478 }
1479 }
1480 }
1481 } else {
1482 debug!("Parser::add_default_value: doesn't have conditional defaults");
1483 }
1484
1485 if !arg.default_vals.is_empty() {
1486 debug!(
1487 "Parser::add_default_value:iter:{}: has default vals",
1488 arg.get_id()
1489 );
1490 if matcher.contains(arg.get_id()) {
1491 debug!("Parser::add_default_value:iter:{}: was used", arg.get_id());
1492 } else {
1494 debug!(
1495 "Parser::add_default_value:iter:{}: wasn't used",
1496 arg.get_id()
1497 );
1498 let arg_values: Vec<_> = arg
1499 .default_vals
1500 .iter()
1501 .map(crate::builder::OsStr::to_os_string)
1502 .collect();
1503 let trailing_idx = None;
1504 let _ = ok!(self.react(
1505 None,
1506 ValueSource::DefaultValue,
1507 arg,
1508 arg_values,
1509 trailing_idx,
1510 matcher,
1511 ));
1512 }
1513 } else {
1514 debug!(
1515 "Parser::add_default_value:iter:{}: doesn't have default vals",
1516 arg.get_id()
1517 );
1518
1519 }
1521
1522 Ok(())
1523 }
1524
1525 fn start_custom_arg(&self, matcher: &mut ArgMatcher, arg: &Arg, source: ValueSource) {
1526 if source == ValueSource::CommandLine {
1527 self.remove_overrides(arg, matcher);
1529 }
1530 matcher.start_custom_arg(arg, source);
1531 if source.is_explicit() {
1532 for group in self.cmd.groups_for_arg(arg.get_id()) {
1533 matcher.start_custom_group(group.clone(), source);
1534 matcher.add_val_to(
1535 &group,
1536 AnyValue::new(arg.get_id().clone()),
1537 OsString::from(arg.get_id().as_str()),
1538 );
1539 }
1540 }
1541 }
1542}
1543
1544impl Parser<'_> {
1546 fn did_you_mean_error(
1548 &mut self,
1549 arg: &str,
1550 matcher: &mut ArgMatcher,
1551 remaining_args: &[&OsStr],
1552 trailing_values: bool,
1553 ) -> ClapError {
1554 debug!("Parser::did_you_mean_error: arg={arg}");
1555 let longs = self
1557 .cmd
1558 .get_keymap()
1559 .keys()
1560 .filter_map(|x| match x {
1561 KeyType::Long(l) => Some(l.to_string_lossy().into_owned()),
1562 _ => None,
1563 })
1564 .collect::<Vec<_>>();
1565 debug!("Parser::did_you_mean_error: longs={longs:?}");
1566
1567 let did_you_mean = suggestions::did_you_mean_flag(
1568 arg,
1569 remaining_args,
1570 longs.iter().map(|x| &x[..]),
1571 self.cmd.get_subcommands_mut(),
1572 );
1573
1574 if !self.cmd.is_ignore_errors_set() {
1576 if let Some((name, _)) = did_you_mean.as_ref() {
1577 if let Some(arg) = self.cmd.get_keymap().get(&name.as_ref()) {
1578 self.start_custom_arg(matcher, arg, ValueSource::CommandLine);
1579 }
1580 }
1581 }
1582 let did_you_mean = did_you_mean.map(|(arg, cmd)| (format!("--{arg}"), cmd));
1583
1584 let required = self.cmd.required_graph();
1585 let used: Vec<Id> = matcher
1586 .arg_ids()
1587 .filter(|arg_id| {
1588 matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent)
1589 })
1590 .filter(|n| self.cmd.find(n).map(|a| !a.is_hide_set()).unwrap_or(false))
1591 .cloned()
1592 .collect();
1593
1594 let suggested_trailing_arg = (did_you_mean.is_none()
1599 || self
1600 .cmd
1601 .get_positionals()
1602 .any(|arg| arg.is_last_set() || arg.is_trailing_var_arg_set()))
1603 && !trailing_values
1604 && self.cmd.has_positionals();
1605 ClapError::unknown_argument(
1606 self.cmd,
1607 format!("--{arg}"),
1608 did_you_mean,
1609 suggested_trailing_arg,
1610 Usage::new(self.cmd)
1611 .required(&required)
1612 .create_usage_with_title(&used),
1613 )
1614 }
1615
1616 fn help_err(&self, use_long: bool) -> ClapError {
1617 let styled = self.cmd.write_help_err(use_long);
1618 ClapError::display_help(self.cmd, styled)
1619 }
1620
1621 fn version_err(&self, use_long: bool) -> ClapError {
1622 let styled = self.cmd.write_version_err(use_long);
1623 ClapError::display_version(self.cmd, styled)
1624 }
1625}
1626
1627#[derive(Debug, PartialEq, Eq)]
1628pub(crate) enum ParseState {
1629 ValuesDone,
1630 Opt(Id),
1631 Pos(Id),
1632}
1633
1634#[derive(Debug, PartialEq, Clone)]
1636#[must_use]
1637enum ParseResult {
1638 FlagSubCommand(String),
1639 Opt(Id),
1640 ValuesDone,
1641 AttachedValueNotConsumed,
1644 UnneededAttachedValue {
1646 rest: String,
1647 used: Vec<Id>,
1648 arg: String,
1649 },
1650 MaybeHyphenValue,
1652 EqualsNotProvided {
1654 arg: String,
1655 },
1656 NoMatchingArg {
1658 arg: String,
1659 },
1660 NoArg,
1662}
1663
1664#[derive(Clone, Debug, PartialEq, Eq)]
1665pub(crate) struct PendingArg {
1666 pub(crate) id: Id,
1667 pub(crate) ident: Option<Identifier>,
1668 pub(crate) raw_vals: Vec<OsString>,
1669 pub(crate) trailing_idx: Option<usize>,
1670}
1671
1672#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1673pub(crate) enum Identifier {
1674 Short,
1675 Long,
1676 Index,
1677}