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