1 // Std 2 use std::{ 3 cell::Cell, 4 ffi::{OsStr, OsString}, 5 }; 6 7 // Third Party 8 use os_str_bytes::RawOsStr; 9 10 // Internal 11 use crate::{ 12 build::AppSettings as AS, 13 build::{App, Arg, ArgSettings}, 14 mkeymap::KeyType, 15 output::{fmt::Colorizer, Help, HelpWriter, Usage}, 16 parse::errors::Error as ClapError, 17 parse::errors::ErrorKind, 18 parse::errors::Result as ClapResult, 19 parse::features::suggestions, 20 parse::{ArgMatcher, SubCommand}, 21 parse::{Validator, ValueType}, 22 util::{ChildGraph, Id}, 23 INTERNAL_ERROR_MSG, INVALID_UTF8, 24 }; 25 26 pub(crate) enum ParseState { 27 ValuesDone, 28 Opt(Id), 29 Pos(Id), 30 } 31 32 /// Recoverable Parsing results. 33 #[derive(Debug, PartialEq, Clone)] 34 enum ParseResult { 35 FlagSubCommand(String), 36 Opt(Id), 37 ValuesDone, 38 /// Value attached to the short flag is not consumed(e.g. 'u' for `-cu` is 39 /// not consumed). 40 AttachedValueNotConsumed, 41 /// This long flag doesn't need a value but is provided one. 42 UnneededAttachedValue { 43 rest: String, 44 used: Vec<Id>, 45 arg: String, 46 }, 47 /// This flag might be an hyphen Value. 48 MaybeHyphenValue, 49 /// Equals required but not provided. 50 EqualsNotProvided { 51 arg: String, 52 }, 53 /// Failed to match a Arg. 54 NoMatchingArg { 55 arg: String, 56 }, 57 /// No argument found e.g. parser is given `-` when parsing a flag. 58 NoArg, 59 /// This is a Help flag. 60 HelpFlag, 61 /// This is a version flag. 62 VersionFlag, 63 } 64 65 #[derive(Debug)] 66 pub(crate) struct Input { 67 items: Vec<OsString>, 68 cursor: usize, 69 } 70 71 impl<I, T> From<I> for Input 72 where 73 I: Iterator<Item = T>, 74 T: Into<OsString> + Clone, 75 { from(val: I) -> Self76 fn from(val: I) -> Self { 77 Self { 78 items: val.map(|x| x.into()).collect(), 79 cursor: 0, 80 } 81 } 82 } 83 84 impl Input { next(&mut self) -> Option<(&OsStr, &[OsString])>85 pub(crate) fn next(&mut self) -> Option<(&OsStr, &[OsString])> { 86 if self.cursor >= self.items.len() { 87 None 88 } else { 89 let current = &self.items[self.cursor]; 90 self.cursor += 1; 91 let remaining = &self.items[self.cursor..]; 92 Some((current, remaining)) 93 } 94 } 95 96 /// Insert some items to the Input items just after current parsing cursor. 97 /// Usually used by replaced items recovering. insert(&mut self, insert_items: &[&str])98 pub(crate) fn insert(&mut self, insert_items: &[&str]) { 99 self.items = insert_items 100 .iter() 101 .map(OsString::from) 102 .chain(self.items.drain(self.cursor..)) 103 .collect(); 104 self.cursor = 0; 105 } 106 } 107 108 pub(crate) struct Parser<'help, 'app> { 109 pub(crate) app: &'app mut App<'help>, 110 pub(crate) required: ChildGraph<Id>, 111 pub(crate) overridden: Vec<Id>, 112 pub(crate) seen: Vec<Id>, 113 pub(crate) cur_idx: Cell<usize>, 114 /// Index of the previous flag subcommand in a group of flags. 115 pub(crate) flag_subcmd_at: Option<usize>, 116 /// Counter indicating the number of items to skip 117 /// when revisiting the group of flags which includes the flag subcommand. 118 pub(crate) flag_subcmd_skip: usize, 119 } 120 121 // Initializing Methods 122 impl<'help, 'app> Parser<'help, 'app> { new(app: &'app mut App<'help>) -> Self123 pub(crate) fn new(app: &'app mut App<'help>) -> Self { 124 let mut reqs = ChildGraph::with_capacity(5); 125 for a in app 126 .args 127 .args() 128 .filter(|a| a.settings.is_set(ArgSettings::Required)) 129 { 130 reqs.insert(a.id.clone()); 131 } 132 133 Parser { 134 app, 135 required: reqs, 136 overridden: Vec::new(), 137 seen: Vec::new(), 138 cur_idx: Cell::new(0), 139 flag_subcmd_at: None, 140 flag_subcmd_skip: 0, 141 } 142 } 143 144 #[cfg(debug_assertions)] _verify_positionals(&self) -> bool145 fn _verify_positionals(&self) -> bool { 146 debug!("Parser::_verify_positionals"); 147 // Because you must wait until all arguments have been supplied, this is the first chance 148 // to make assertions on positional argument indexes 149 // 150 // First we verify that the index highest supplied index, is equal to the number of 151 // positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3 152 // but no 2) 153 154 let highest_idx = self 155 .app 156 .args 157 .keys() 158 .filter_map(|x| { 159 if let KeyType::Position(n) = x { 160 Some(*n) 161 } else { 162 None 163 } 164 }) 165 .max() 166 .unwrap_or(0); 167 168 //_highest_idx(&self.positionals); 169 170 let num_p = self.app.args.keys().filter(|x| x.is_position()).count(); 171 172 assert!( 173 highest_idx == num_p, 174 "Found positional argument whose index is {} but there \ 175 are only {} positional arguments defined", 176 highest_idx, 177 num_p 178 ); 179 180 // Next we verify that only the highest index has a .multiple_values(true) (if any) 181 let only_highest = |a: &Arg| { 182 a.is_set(ArgSettings::MultipleValues) && (a.index.unwrap_or(0) != highest_idx) 183 }; 184 if self.app.get_positionals().any(only_highest) { 185 // First we make sure if there is a positional that allows multiple values 186 // the one before it (second to last) has one of these: 187 // * a value terminator 188 // * ArgSettings::Last 189 // * The last arg is Required 190 191 // We can't pass the closure (it.next()) to the macro directly because each call to 192 // find() (iterator, not macro) gets called repeatedly. 193 let last = &self.app.args[&KeyType::Position(highest_idx)]; 194 let second_to_last = &self.app.args[&KeyType::Position(highest_idx - 1)]; 195 196 // Either the final positional is required 197 // Or the second to last has a terminator or .last(true) set 198 let ok = last.is_set(ArgSettings::Required) 199 || (second_to_last.terminator.is_some() 200 || second_to_last.is_set(ArgSettings::Last)) 201 || last.is_set(ArgSettings::Last); 202 assert!( 203 ok, 204 "When using a positional argument with .multiple_values(true) that is *not the \ 205 last* positional argument, the last positional argument (i.e. the one \ 206 with the highest index) *must* have .required(true) or .last(true) set." 207 ); 208 209 // We make sure if the second to last is Multiple the last is ArgSettings::Last 210 let ok = second_to_last.is_set(ArgSettings::MultipleValues) 211 || last.is_set(ArgSettings::Last); 212 assert!( 213 ok, 214 "Only the last positional argument, or second to last positional \ 215 argument may be set to .multiple_values(true)" 216 ); 217 218 // Next we check how many have both Multiple and not a specific number of values set 219 let count = self 220 .app 221 .get_positionals() 222 .filter(|p| p.settings.is_set(ArgSettings::MultipleValues) && p.num_vals.is_none()) 223 .count(); 224 let ok = count <= 1 225 || (last.is_set(ArgSettings::Last) 226 && last.is_set(ArgSettings::MultipleValues) 227 && second_to_last.is_set(ArgSettings::MultipleValues) 228 && count == 2); 229 assert!( 230 ok, 231 "Only one positional argument with .multiple_values(true) set is allowed per \ 232 command, unless the second one also has .last(true) set" 233 ); 234 } 235 236 let mut found = false; 237 238 if self.is_set(AS::AllowMissingPositional) { 239 // Check that if a required positional argument is found, all positions with a lower 240 // index are also required. 241 let mut foundx2 = false; 242 243 for p in self.app.get_positionals() { 244 if foundx2 && !p.is_set(ArgSettings::Required) { 245 assert!( 246 p.is_set(ArgSettings::Required), 247 "Found non-required positional argument with a lower \ 248 index than a required positional argument by two or more: {:?} \ 249 index {:?}", 250 p.name, 251 p.index 252 ); 253 } else if p.is_set(ArgSettings::Required) && !p.is_set(ArgSettings::Last) { 254 // Args that .last(true) don't count since they can be required and have 255 // positionals with a lower index that aren't required 256 // Imagine: prog <req1> [opt1] -- <req2> 257 // Both of these are valid invocations: 258 // $ prog r1 -- r2 259 // $ prog r1 o1 -- r2 260 if found { 261 foundx2 = true; 262 continue; 263 } 264 found = true; 265 continue; 266 } else { 267 found = false; 268 } 269 } 270 } else { 271 // Check that if a required positional argument is found, all positions with a lower 272 // index are also required 273 for p in (1..=num_p).rev().filter_map(|n| self.app.args.get(&n)) { 274 if found { 275 assert!( 276 p.is_set(ArgSettings::Required), 277 "Found non-required positional argument with a lower \ 278 index than a required positional argument: {:?} index {:?}", 279 p.name, 280 p.index 281 ); 282 } else if p.is_set(ArgSettings::Required) && !p.is_set(ArgSettings::Last) { 283 // Args that .last(true) don't count since they can be required and have 284 // positionals with a lower index that aren't required 285 // Imagine: prog <req1> [opt1] -- <req2> 286 // Both of these are valid invocations: 287 // $ prog r1 -- r2 288 // $ prog r1 o1 -- r2 289 found = true; 290 continue; 291 } 292 } 293 } 294 assert!( 295 self.app 296 .get_positionals() 297 .filter(|p| p.is_set(ArgSettings::Last)) 298 .count() 299 < 2, 300 "Only one positional argument may have last(true) set. Found two." 301 ); 302 if self 303 .app 304 .get_positionals() 305 .any(|p| p.is_set(ArgSettings::Last) && p.is_set(ArgSettings::Required)) 306 && self.app.has_subcommands() 307 && !self.is_set(AS::SubcommandsNegateReqs) 308 { 309 panic!( 310 "Having a required positional argument with .last(true) set *and* child \ 311 subcommands without setting SubcommandsNegateReqs isn't compatible." 312 ); 313 } 314 315 true 316 } 317 318 // Does all the initializing and prepares the parser _build(&mut self)319 pub(crate) fn _build(&mut self) { 320 debug!("Parser::_build"); 321 322 #[cfg(debug_assertions)] 323 self._verify_positionals(); 324 325 for group in &self.app.groups { 326 if group.required { 327 let idx = self.required.insert(group.id.clone()); 328 for a in &group.requires { 329 self.required.insert_child(idx, a.clone()); 330 } 331 } 332 } 333 } 334 } 335 336 // Parsing Methods 337 impl<'help, 'app> Parser<'help, 'app> { 338 // The actual parsing function 339 #[allow(clippy::cognitive_complexity)] get_matches_with( &mut self, matcher: &mut ArgMatcher, it: &mut Input, ) -> ClapResult<()>340 pub(crate) fn get_matches_with( 341 &mut self, 342 matcher: &mut ArgMatcher, 343 it: &mut Input, 344 ) -> ClapResult<()> { 345 debug!("Parser::get_matches_with"); 346 // Verify all positional assertions pass 347 self._build(); 348 349 let mut subcmd_name: Option<String> = None; 350 let mut keep_state = false; 351 let mut parse_state = ParseState::ValuesDone; 352 let mut pos_counter = 1; 353 354 // Already met any valid arg(then we shouldn't expect subcommands after it). 355 let mut valid_arg_found = false; 356 // If the user already passed '--'. Meaning only positional args follow. 357 let mut trailing_values = false; 358 359 // Count of positional args 360 let positional_count = self.app.args.keys().filter(|x| x.is_position()).count(); 361 // If any arg sets .last(true) 362 let contains_last = self.app.args.args().any(|x| x.is_set(ArgSettings::Last)); 363 364 while let Some((arg_os, remaining_args)) = it.next() { 365 // Recover the replaced items if any. 366 if let Some((_replacer, replaced_items)) = self 367 .app 368 .replacers 369 .iter() 370 .find(|(key, _)| OsStr::new(key) == arg_os) 371 { 372 it.insert(replaced_items); 373 debug!( 374 "Parser::get_matches_with: found replacer: {:?}, target: {:?}", 375 _replacer, replaced_items 376 ); 377 continue; 378 } 379 380 let arg_os = RawOsStr::new(arg_os); 381 debug!( 382 "Parser::get_matches_with: Begin parsing '{:?}' ({:?})", 383 arg_os, 384 arg_os.as_raw_bytes() 385 ); 386 387 // Correct pos_counter. 388 pos_counter = { 389 let is_second_to_last = pos_counter + 1 == positional_count; 390 391 // The last positional argument, or second to last positional 392 // argument may be set to .multiple_values(true) 393 let low_index_mults = is_second_to_last 394 && self.app.get_positionals().any(|a| { 395 a.is_set(ArgSettings::MultipleValues) 396 && (positional_count != a.index.unwrap_or(0)) 397 }) 398 && self 399 .app 400 .get_positionals() 401 .last() 402 .map_or(false, |p_name| !p_name.is_set(ArgSettings::Last)); 403 404 let missing_pos = self.is_set(AS::AllowMissingPositional) 405 && is_second_to_last 406 && !trailing_values; 407 408 debug!( 409 "Parser::get_matches_with: Positional counter...{}", 410 pos_counter 411 ); 412 debug!( 413 "Parser::get_matches_with: Low index multiples...{:?}", 414 low_index_mults 415 ); 416 417 if low_index_mults || missing_pos { 418 let skip_current = if let Some(n) = remaining_args.get(0) { 419 if let Some(p) = self 420 .app 421 .get_positionals() 422 .find(|p| p.index == Some(pos_counter)) 423 { 424 // If next value looks like a new_arg or it's a 425 // subcommand, skip positional argument under current 426 // pos_counter(which means current value cannot be a 427 // positional argument with a value next to it), assume 428 // current value matches the next arg. 429 let n = RawOsStr::new(n); 430 self.is_new_arg(&n, p) 431 || self.possible_subcommand(&n, valid_arg_found).is_some() 432 } else { 433 true 434 } 435 } else { 436 true 437 }; 438 439 if skip_current { 440 debug!("Parser::get_matches_with: Bumping the positional counter..."); 441 pos_counter + 1 442 } else { 443 pos_counter 444 } 445 } else if trailing_values 446 && (self.is_set(AS::AllowMissingPositional) || contains_last) 447 { 448 // Came to -- and one positional has .last(true) set, so we go immediately 449 // to the last (highest index) positional 450 debug!("Parser::get_matches_with: .last(true) and --, setting last pos"); 451 positional_count 452 } else { 453 pos_counter 454 } 455 }; 456 457 // Has the user already passed '--'? Meaning only positional args follow 458 if !trailing_values { 459 if self.is_set(AS::SubcommandPrecedenceOverArg) 460 || !matches!(parse_state, ParseState::Opt(_) | ParseState::Pos(_)) 461 { 462 // Does the arg match a subcommand name, or any of its aliases (if defined) 463 let sc_name = self.possible_subcommand(&arg_os, valid_arg_found); 464 debug!("Parser::get_matches_with: sc={:?}", sc_name); 465 if let Some(sc_name) = sc_name { 466 if sc_name == "help" 467 && !self.is_set(AS::NoAutoHelp) 468 && !self.is_set(AS::DisableHelpSubcommand) 469 { 470 self.parse_help_subcommand(remaining_args)?; 471 } 472 subcmd_name = Some(sc_name.to_owned()); 473 break; 474 } 475 } 476 477 if let Some(long_arg) = arg_os.strip_prefix("--") { 478 let parse_result = self.parse_long_arg( 479 matcher, 480 long_arg, 481 &parse_state, 482 &mut valid_arg_found, 483 trailing_values, 484 ); 485 debug!( 486 "Parser::get_matches_with: After parse_long_arg {:?}", 487 parse_result 488 ); 489 match parse_result { 490 ParseResult::NoArg => { 491 debug!("Parser::get_matches_with: setting TrailingVals=true"); 492 trailing_values = true; 493 continue; 494 } 495 ParseResult::ValuesDone => { 496 parse_state = ParseState::ValuesDone; 497 continue; 498 } 499 ParseResult::Opt(id) => { 500 parse_state = ParseState::Opt(id); 501 continue; 502 } 503 ParseResult::FlagSubCommand(name) => { 504 debug!( 505 "Parser::get_matches_with: FlagSubCommand found in long arg {:?}", 506 &name 507 ); 508 subcmd_name = Some(name); 509 break; 510 } 511 ParseResult::EqualsNotProvided { arg } => { 512 return Err(ClapError::no_equals( 513 self.app, 514 arg, 515 Usage::new(self).create_usage_with_title(&[]), 516 )); 517 } 518 ParseResult::NoMatchingArg { arg } => { 519 let remaining_args: Vec<_> = remaining_args 520 .iter() 521 .map(|x| x.to_str().expect(INVALID_UTF8)) 522 .collect(); 523 return Err(self.did_you_mean_error(&arg, matcher, &remaining_args)); 524 } 525 ParseResult::UnneededAttachedValue { rest, used, arg } => { 526 return Err(ClapError::too_many_values( 527 self.app, 528 rest, 529 arg, 530 Usage::new(self).create_usage_no_title(&used), 531 )) 532 } 533 ParseResult::HelpFlag => { 534 return Err(self.help_err(true)); 535 } 536 ParseResult::VersionFlag => { 537 return Err(self.version_err(true)); 538 } 539 ParseResult::MaybeHyphenValue => { 540 // Maybe a hyphen value, do nothing. 541 } 542 ParseResult::AttachedValueNotConsumed => { 543 unreachable!() 544 } 545 } 546 } else if let Some(short_arg) = arg_os.strip_prefix("-") { 547 // Arg looks like a short flag, and not a possible number 548 549 // Try to parse short args like normal, if AllowLeadingHyphen or 550 // AllowNegativeNumbers is set, parse_short_arg will *not* throw 551 // an error, and instead return Ok(None) 552 let parse_result = self.parse_short_arg( 553 matcher, 554 short_arg, 555 &parse_state, 556 pos_counter, 557 &mut valid_arg_found, 558 trailing_values, 559 ); 560 // If it's None, we then check if one of those two AppSettings was set 561 debug!( 562 "Parser::get_matches_with: After parse_short_arg {:?}", 563 parse_result 564 ); 565 match parse_result { 566 ParseResult::NoArg => { 567 // Is a single dash `-`, try positional. 568 } 569 ParseResult::ValuesDone => { 570 parse_state = ParseState::ValuesDone; 571 continue; 572 } 573 ParseResult::Opt(id) => { 574 parse_state = ParseState::Opt(id); 575 continue; 576 } 577 ParseResult::FlagSubCommand(name) => { 578 // If there are more short flags to be processed, we should keep the state, and later 579 // revisit the current group of short flags skipping the subcommand. 580 keep_state = self 581 .flag_subcmd_at 582 .map(|at| { 583 it.cursor -= 1; 584 // Since we are now saving the current state, the number of flags to skip during state recovery should 585 // be the current index (`cur_idx`) minus ONE UNIT TO THE LEFT of the starting position. 586 self.flag_subcmd_skip = self.cur_idx.get() - at + 1; 587 }) 588 .is_some(); 589 590 debug!( 591 "Parser::get_matches_with:FlagSubCommandShort: subcmd_name={}, keep_state={}, flag_subcmd_skip={}", 592 name, 593 keep_state, 594 self.flag_subcmd_skip 595 ); 596 597 subcmd_name = Some(name); 598 break; 599 } 600 ParseResult::EqualsNotProvided { arg } => { 601 return Err(ClapError::no_equals( 602 self.app, 603 arg, 604 Usage::new(self).create_usage_with_title(&[]), 605 )) 606 } 607 ParseResult::NoMatchingArg { arg } => { 608 return Err(ClapError::unknown_argument( 609 self.app, 610 arg, 611 None, 612 Usage::new(self).create_usage_with_title(&[]), 613 )); 614 } 615 ParseResult::HelpFlag => { 616 return Err(self.help_err(false)); 617 } 618 ParseResult::VersionFlag => { 619 return Err(self.version_err(false)); 620 } 621 ParseResult::MaybeHyphenValue => { 622 // Maybe a hyphen value, do nothing. 623 } 624 ParseResult::UnneededAttachedValue { .. } 625 | ParseResult::AttachedValueNotConsumed => unreachable!(), 626 } 627 } 628 629 if let ParseState::Opt(id) = &parse_state { 630 // Assume this is a value of a previous arg. 631 632 // get the option so we can check the settings 633 let parse_result = self.add_val_to_arg( 634 &self.app[id], 635 &arg_os, 636 matcher, 637 ValueType::CommandLine, 638 true, 639 trailing_values, 640 ); 641 parse_state = match parse_result { 642 ParseResult::Opt(id) => ParseState::Opt(id), 643 ParseResult::ValuesDone => ParseState::ValuesDone, 644 _ => unreachable!(), 645 }; 646 // get the next value from the iterator 647 continue; 648 } 649 } 650 651 if let Some(p) = self.app.args.get(&pos_counter) { 652 if p.is_set(ArgSettings::Last) && !trailing_values { 653 return Err(ClapError::unknown_argument( 654 self.app, 655 arg_os.to_str_lossy().into_owned(), 656 None, 657 Usage::new(self).create_usage_with_title(&[]), 658 )); 659 } 660 661 if self.is_set(AS::TrailingVarArg) && pos_counter == positional_count { 662 trailing_values = true; 663 } 664 665 self.seen.push(p.id.clone()); 666 // Creating new value group rather than appending when the arg 667 // doesn't have any value. This behaviour is right because 668 // positional arguments are always present continiously. 669 let append = self.arg_have_val(matcher, p); 670 self.add_val_to_arg( 671 p, 672 &arg_os, 673 matcher, 674 ValueType::CommandLine, 675 append, 676 trailing_values, 677 ); 678 679 // Increase occurrence no matter if we are appending, occurrences 680 // of positional argument equals to number of values rather than 681 // the number of value groups. 682 self.inc_occurrence_of_arg(matcher, p); 683 684 // Only increment the positional counter if it doesn't allow multiples 685 if !p.settings.is_set(ArgSettings::MultipleValues) { 686 pos_counter += 1; 687 parse_state = ParseState::ValuesDone; 688 } else { 689 parse_state = ParseState::Pos(p.id.clone()); 690 } 691 valid_arg_found = true; 692 } else if self.is_set(AS::AllowExternalSubcommands) { 693 // Get external subcommand name 694 let sc_name = match arg_os.to_str() { 695 Some(s) => s.to_string(), 696 None => { 697 return Err(ClapError::invalid_utf8( 698 self.app, 699 Usage::new(self).create_usage_with_title(&[]), 700 )); 701 } 702 }; 703 704 // Collect the external subcommand args 705 let mut sc_m = ArgMatcher::default(); 706 707 while let Some((v, _)) = it.next() { 708 if !self.is_set(AS::AllowInvalidUtf8ForExternalSubcommands) 709 && v.to_str().is_none() 710 { 711 return Err(ClapError::invalid_utf8( 712 self.app, 713 Usage::new(self).create_usage_with_title(&[]), 714 )); 715 } 716 sc_m.add_val_to( 717 &Id::empty_hash(), 718 v.to_os_string(), 719 ValueType::CommandLine, 720 false, 721 ); 722 } 723 724 matcher.subcommand(SubCommand { 725 name: sc_name.clone(), 726 id: sc_name.into(), 727 matches: sc_m.into_inner(), 728 }); 729 730 self.remove_overrides(matcher); 731 732 return Validator::new(self).validate( 733 parse_state, 734 subcmd_name.is_some(), 735 matcher, 736 trailing_values, 737 ); 738 } else { 739 // Start error processing 740 return Err(self.match_arg_error(&arg_os, valid_arg_found, trailing_values)); 741 } 742 } 743 744 if let Some(ref pos_sc_name) = subcmd_name { 745 let sc_name = self 746 .app 747 .find_subcommand(pos_sc_name) 748 .expect(INTERNAL_ERROR_MSG) 749 .name 750 .clone(); 751 self.parse_subcommand(&sc_name, matcher, it, keep_state)?; 752 } else if self.is_set(AS::SubcommandRequired) { 753 let bn = self.app.bin_name.as_ref().unwrap_or(&self.app.name); 754 return Err(ClapError::missing_subcommand( 755 self.app, 756 bn.to_string(), 757 Usage::new(self).create_usage_with_title(&[]), 758 )); 759 } else if self.is_set(AS::SubcommandRequiredElseHelp) { 760 debug!("Parser::get_matches_with: SubcommandRequiredElseHelp=true"); 761 let message = self.write_help_err()?; 762 return Err(ClapError::new( 763 message, 764 ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand, 765 )); 766 } 767 768 self.remove_overrides(matcher); 769 770 Validator::new(self).validate(parse_state, subcmd_name.is_some(), matcher, trailing_values) 771 } 772 match_arg_error( &self, arg_os: &RawOsStr, valid_arg_found: bool, trailing_values: bool, ) -> ClapError773 fn match_arg_error( 774 &self, 775 arg_os: &RawOsStr, 776 valid_arg_found: bool, 777 trailing_values: bool, 778 ) -> ClapError { 779 // If argument follows a `--` 780 if trailing_values { 781 // If the arg matches a subcommand name, or any of its aliases (if defined) 782 if self.possible_subcommand(arg_os, valid_arg_found).is_some() { 783 return ClapError::unnecessary_double_dash( 784 self.app, 785 arg_os.to_str_lossy().into_owned(), 786 Usage::new(self).create_usage_with_title(&[]), 787 ); 788 } 789 } 790 let candidates = 791 suggestions::did_you_mean(&arg_os.to_str_lossy(), self.app.all_subcommand_names()); 792 // If the argument looks like a subcommand. 793 if !candidates.is_empty() { 794 let candidates: Vec<_> = candidates 795 .iter() 796 .map(|candidate| format!("'{}'", candidate)) 797 .collect(); 798 return ClapError::invalid_subcommand( 799 self.app, 800 arg_os.to_str_lossy().into_owned(), 801 candidates.join(" or "), 802 self.app 803 .bin_name 804 .as_ref() 805 .unwrap_or(&self.app.name) 806 .to_string(), 807 Usage::new(self).create_usage_with_title(&[]), 808 ); 809 } 810 // If the argument must be a subcommand. 811 if !self.app.has_args() || self.is_set(AS::InferSubcommands) && self.app.has_subcommands() { 812 return ClapError::unrecognized_subcommand( 813 self.app, 814 arg_os.to_str_lossy().into_owned(), 815 self.app 816 .bin_name 817 .as_ref() 818 .unwrap_or(&self.app.name) 819 .to_string(), 820 ); 821 } 822 ClapError::unknown_argument( 823 self.app, 824 arg_os.to_str_lossy().into_owned(), 825 None, 826 Usage::new(self).create_usage_with_title(&[]), 827 ) 828 } 829 830 // Checks if the arg matches a subcommand name, or any of its aliases (if defined) possible_subcommand(&self, arg_os: &RawOsStr, valid_arg_found: bool) -> Option<&str>831 fn possible_subcommand(&self, arg_os: &RawOsStr, valid_arg_found: bool) -> Option<&str> { 832 debug!("Parser::possible_subcommand: arg={:?}", arg_os); 833 834 if !(self.is_set(AS::ArgsNegateSubcommands) && valid_arg_found) { 835 if self.is_set(AS::InferSubcommands) { 836 // For subcommand `test`, we accepts it's prefix: `t`, `te`, 837 // `tes` and `test`. 838 let v = self 839 .app 840 .all_subcommand_names() 841 .filter(|s| RawOsStr::from_str(s).starts_with_os(arg_os)) 842 .collect::<Vec<_>>(); 843 844 if v.len() == 1 { 845 return Some(v[0]); 846 } 847 848 // If there is any ambiguity, fallback to non-infer subcommand 849 // search. 850 } 851 if let Some(sc) = self.app.find_subcommand(arg_os) { 852 return Some(&sc.name); 853 } 854 } 855 None 856 } 857 858 // Checks if the arg matches a long flag subcommand name, or any of its aliases (if defined) possible_long_flag_subcommand(&self, arg_os: &RawOsStr) -> Option<&str>859 fn possible_long_flag_subcommand(&self, arg_os: &RawOsStr) -> Option<&str> { 860 debug!("Parser::possible_long_flag_subcommand: arg={:?}", arg_os); 861 if self.is_set(AS::InferSubcommands) { 862 let options = self 863 .app 864 .get_subcommands() 865 .fold(Vec::new(), |mut options, sc| { 866 if let Some(long) = sc.long_flag { 867 if RawOsStr::from_str(long).starts_with_os(arg_os) { 868 options.push(long); 869 } 870 options.extend( 871 sc.get_all_aliases() 872 .filter(|alias| RawOsStr::from_str(alias).starts_with_os(arg_os)), 873 ) 874 } 875 options 876 }); 877 if options.len() == 1 { 878 return Some(options[0]); 879 } 880 881 for sc in options { 882 if sc == arg_os { 883 return Some(sc); 884 } 885 } 886 } else if let Some(sc_name) = self.app.find_long_subcmd(arg_os) { 887 return Some(sc_name); 888 } 889 None 890 } 891 parse_help_subcommand(&self, cmds: &[OsString]) -> ClapResult<ParseResult>892 fn parse_help_subcommand(&self, cmds: &[OsString]) -> ClapResult<ParseResult> { 893 debug!("Parser::parse_help_subcommand"); 894 895 let mut bin_name = self.app.bin_name.as_ref().unwrap_or(&self.app.name).clone(); 896 897 let mut sc = { 898 // @TODO @perf: cloning all these Apps isn't great, but since it's just displaying the 899 // help message there are bigger fish to fry 900 let mut sc = self.app.clone(); 901 902 for cmd in cmds.iter() { 903 sc = if let Some(c) = sc.find_subcommand(cmd) { 904 c 905 } else if let Some(c) = sc.find_subcommand(&cmd.to_string_lossy()) { 906 c 907 } else { 908 return Err(ClapError::unrecognized_subcommand( 909 self.app, 910 cmd.to_string_lossy().into_owned(), 911 self.app 912 .bin_name 913 .as_ref() 914 .unwrap_or(&self.app.name) 915 .to_string(), 916 )); 917 } 918 .clone(); 919 920 if cmd == OsStr::new("help") { 921 let pb = Arg::new("subcommand") 922 .index(1) 923 .setting(ArgSettings::TakesValue) 924 .setting(ArgSettings::MultipleValues) 925 .value_name("SUBCOMMAND") 926 .about("The subcommand whose help message to display"); 927 sc = sc.arg(pb); 928 } 929 930 sc._build(); 931 bin_name.push(' '); 932 bin_name.push_str(&sc.name); 933 } 934 935 sc 936 }; 937 sc = sc.bin_name(bin_name); 938 939 let parser = Parser::new(&mut sc); 940 941 Err(parser.help_err(self.app.is_set(AS::UseLongFormatForHelpSubcommand))) 942 } 943 is_new_arg(&self, next: &RawOsStr, current_positional: &Arg) -> bool944 fn is_new_arg(&self, next: &RawOsStr, current_positional: &Arg) -> bool { 945 debug!( 946 "Parser::is_new_arg: {:?}:{:?}", 947 next, current_positional.name 948 ); 949 950 if self.is_set(AS::AllowLeadingHyphen) 951 || self.app[¤t_positional.id].is_set(ArgSettings::AllowHyphenValues) 952 || (self.is_set(AS::AllowNegativeNumbers) && next.to_str_lossy().parse::<f64>().is_ok()) 953 { 954 // If allow hyphen, this isn't a new arg. 955 debug!("Parser::is_new_arg: Allow hyphen"); 956 false 957 } else if next.starts_with("--") { 958 // If this is a long flag, this is a new arg. 959 debug!("Parser::is_new_arg: -- found"); 960 true 961 } else if next.starts_with("-") { 962 debug!("Parser::is_new_arg: - found"); 963 // If this is a short flag, this is a new arg. But a singe '-' by 964 // itself is a value and typically means "stdin" on unix systems. 965 next.raw_len() != 1 966 } else { 967 debug!("Parser::is_new_arg: value"); 968 // Nothing special, this is a value. 969 false 970 } 971 } 972 parse_subcommand( &mut self, sc_name: &str, matcher: &mut ArgMatcher, it: &mut Input, keep_state: bool, ) -> ClapResult<()>973 fn parse_subcommand( 974 &mut self, 975 sc_name: &str, 976 matcher: &mut ArgMatcher, 977 it: &mut Input, 978 keep_state: bool, 979 ) -> ClapResult<()> { 980 debug!("Parser::parse_subcommand"); 981 982 let mut mid_string = String::from(" "); 983 984 if !self.is_set(AS::SubcommandsNegateReqs) { 985 let reqs = Usage::new(self).get_required_usage_from(&[], None, true); // maybe Some(m) 986 987 for s in &reqs { 988 mid_string.push_str(s); 989 mid_string.push(' '); 990 } 991 } 992 993 let partial_parsing_enabled = self.is_set(AS::IgnoreErrors); 994 995 if let Some(sc) = self.app.subcommands.iter_mut().find(|s| s.name == sc_name) { 996 let mut sc_matcher = ArgMatcher::default(); 997 // Display subcommand name, short and long in usage 998 let mut sc_names = sc.name.clone(); 999 let mut flag_subcmd = false; 1000 if let Some(l) = sc.long_flag { 1001 sc_names.push_str(&format!(", --{}", l)); 1002 flag_subcmd = true; 1003 } 1004 if let Some(s) = sc.short_flag { 1005 sc_names.push_str(&format!(", -{}", s)); 1006 flag_subcmd = true; 1007 } 1008 1009 if flag_subcmd { 1010 sc_names = format!("{{{}}}", sc_names); 1011 } 1012 1013 sc.usage = Some( 1014 self.app 1015 .bin_name 1016 .as_ref() 1017 .map(|bin_name| format!("{}{}{}", bin_name, mid_string, sc_names)) 1018 .unwrap_or(sc_names), 1019 ); 1020 1021 // bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by 1022 // a space 1023 sc.bin_name = Some(format!( 1024 "{}{}{}", 1025 self.app.bin_name.as_ref().unwrap_or(&String::new()), 1026 if self.app.bin_name.is_some() { " " } else { "" }, 1027 &*sc.name 1028 )); 1029 1030 // Ensure all args are built and ready to parse 1031 sc._build(); 1032 1033 debug!("Parser::parse_subcommand: About to parse sc={}", sc.name); 1034 1035 { 1036 let mut p = Parser::new(sc); 1037 // HACK: maintain indexes between parsers 1038 // FlagSubCommand short arg needs to revisit the current short args, but skip the subcommand itself 1039 if keep_state { 1040 p.cur_idx.set(self.cur_idx.get()); 1041 p.flag_subcmd_at = self.flag_subcmd_at; 1042 p.flag_subcmd_skip = self.flag_subcmd_skip; 1043 } 1044 if let Err(error) = p.get_matches_with(&mut sc_matcher, it) { 1045 if partial_parsing_enabled { 1046 debug!( 1047 "Parser::parse_subcommand: ignored error in subcommand {}: {:?}", 1048 sc_name, error 1049 ); 1050 } else { 1051 return Err(error); 1052 } 1053 } 1054 } 1055 matcher.subcommand(SubCommand { 1056 id: sc.id.clone(), 1057 name: sc.name.clone(), 1058 matches: sc_matcher.into_inner(), 1059 }); 1060 } 1061 Ok(()) 1062 } 1063 1064 // Retrieves the names of all args the user has supplied thus far, except required ones 1065 // because those will be listed in self.required check_for_help_and_version_str(&self, arg: &RawOsStr) -> Option<ParseResult>1066 fn check_for_help_and_version_str(&self, arg: &RawOsStr) -> Option<ParseResult> { 1067 debug!("Parser::check_for_help_and_version_str"); 1068 debug!( 1069 "Parser::check_for_help_and_version_str: Checking if --{:?} is help or version...", 1070 arg 1071 ); 1072 1073 if let Some(help) = self.app.find(&Id::help_hash()) { 1074 if let Some(h) = help.long { 1075 if arg == h && !self.is_set(AS::NoAutoHelp) && !self.is_set(AS::DisableHelpFlag) { 1076 debug!("Help"); 1077 return Some(ParseResult::HelpFlag); 1078 } 1079 } 1080 } 1081 1082 if let Some(version) = self.app.find(&Id::version_hash()) { 1083 if let Some(v) = version.long { 1084 if arg == v 1085 && !self.is_set(AS::NoAutoVersion) 1086 && !self.is_set(AS::DisableVersionFlag) 1087 { 1088 debug!("Version"); 1089 return Some(ParseResult::VersionFlag); 1090 } 1091 } 1092 } 1093 1094 debug!("Neither"); 1095 None 1096 } 1097 check_for_help_and_version_char(&self, arg: char) -> Option<ParseResult>1098 fn check_for_help_and_version_char(&self, arg: char) -> Option<ParseResult> { 1099 debug!("Parser::check_for_help_and_version_char"); 1100 debug!( 1101 "Parser::check_for_help_and_version_char: Checking if -{} is help or version...", 1102 arg 1103 ); 1104 1105 if let Some(help) = self.app.find(&Id::help_hash()) { 1106 if let Some(h) = help.short { 1107 if arg == h && !self.is_set(AS::NoAutoHelp) && !self.is_set(AS::DisableHelpFlag) { 1108 debug!("Help"); 1109 return Some(ParseResult::HelpFlag); 1110 } 1111 } 1112 } 1113 1114 if let Some(version) = self.app.find(&Id::version_hash()) { 1115 if let Some(v) = version.short { 1116 if arg == v 1117 && !self.is_set(AS::NoAutoVersion) 1118 && !self.is_set(AS::DisableVersionFlag) 1119 { 1120 debug!("Version"); 1121 return Some(ParseResult::VersionFlag); 1122 } 1123 } 1124 } 1125 1126 debug!("Neither"); 1127 None 1128 } 1129 use_long_help(&self) -> bool1130 fn use_long_help(&self) -> bool { 1131 debug!("Parser::use_long_help"); 1132 // In this case, both must be checked. This allows the retention of 1133 // original formatting, but also ensures that the actual -h or --help 1134 // specified by the user is sent through. If HiddenShortHelp is not included, 1135 // then items specified with hidden_short_help will also be hidden. 1136 let should_long = |v: &Arg| { 1137 v.long_about.is_some() 1138 || v.is_set(ArgSettings::HiddenLongHelp) 1139 || v.is_set(ArgSettings::HiddenShortHelp) 1140 }; 1141 1142 self.app.long_about.is_some() 1143 || self.app.before_long_help.is_some() 1144 || self.app.after_long_help.is_some() 1145 || self.app.args.args().any(should_long) 1146 || self.app.subcommands.iter().any(|s| s.long_about.is_some()) 1147 } 1148 parse_long_arg( &mut self, matcher: &mut ArgMatcher, long_arg: &RawOsStr, parse_state: &ParseState, valid_arg_found: &mut bool, trailing_values: bool, ) -> ParseResult1149 fn parse_long_arg( 1150 &mut self, 1151 matcher: &mut ArgMatcher, 1152 long_arg: &RawOsStr, 1153 parse_state: &ParseState, 1154 valid_arg_found: &mut bool, 1155 trailing_values: bool, 1156 ) -> ParseResult { 1157 // maybe here lifetime should be 'a 1158 debug!("Parser::parse_long_arg"); 1159 1160 if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if 1161 self.app[opt].is_set(ArgSettings::AllowHyphenValues)) 1162 { 1163 return ParseResult::MaybeHyphenValue; 1164 } 1165 1166 // Update the current index 1167 self.cur_idx.set(self.cur_idx.get() + 1); 1168 debug!("Parser::parse_long_arg: cur_idx:={}", self.cur_idx.get()); 1169 1170 debug!("Parser::parse_long_arg: Does it contain '='..."); 1171 if long_arg.is_empty() { 1172 return ParseResult::NoArg; 1173 } 1174 let (arg, val) = if let Some(index) = long_arg.find("=") { 1175 let (p0, p1) = long_arg.split_at(index); 1176 debug!("Yes '{:?}'", p1); 1177 (p0, Some(p1)) 1178 } else { 1179 debug!("No"); 1180 (long_arg, None) 1181 }; 1182 1183 let opt = if let Some(opt) = self.app.args.get(&*arg.to_os_str()) { 1184 debug!( 1185 "Parser::parse_long_arg: Found valid opt or flag '{}'", 1186 opt.to_string() 1187 ); 1188 Some(opt) 1189 } else if self.is_set(AS::InferLongArgs) { 1190 let arg_str = arg.to_str_lossy(); 1191 self.app.args.args().find(|a| { 1192 a.long.map_or(false, |long| long.starts_with(&*arg_str)) 1193 || a.aliases 1194 .iter() 1195 .any(|(alias, _)| alias.starts_with(&*arg_str)) 1196 }) 1197 } else { 1198 None 1199 }; 1200 1201 if let Some(opt) = opt { 1202 *valid_arg_found = true; 1203 self.seen.push(opt.id.clone()); 1204 if opt.is_set(ArgSettings::TakesValue) { 1205 debug!( 1206 "Parser::parse_long_arg: Found an opt with value '{:?}'", 1207 &val 1208 ); 1209 self.parse_opt(val, opt, matcher, trailing_values) 1210 } else if let Some(rest) = val { 1211 debug!("Parser::parse_long_arg: Got invalid literal `{:?}`", rest); 1212 let used: Vec<Id> = matcher 1213 .arg_names() 1214 .filter(|&n| { 1215 self.app.find(n).map_or(true, |a| { 1216 !(a.is_set(ArgSettings::Hidden) || self.required.contains(&a.id)) 1217 }) 1218 }) 1219 .cloned() 1220 .collect(); 1221 1222 ParseResult::UnneededAttachedValue { 1223 rest: rest.to_str_lossy().into_owned(), 1224 used, 1225 arg: opt.to_string(), 1226 } 1227 } else if let Some(parse_result) = self.check_for_help_and_version_str(arg) { 1228 parse_result 1229 } else { 1230 debug!("Parser::parse_long_arg: Presence validated"); 1231 self.parse_flag(opt, matcher) 1232 } 1233 } else if let Some(sc_name) = self.possible_long_flag_subcommand(arg) { 1234 ParseResult::FlagSubCommand(sc_name.to_string()) 1235 } else if self.is_set(AS::AllowLeadingHyphen) { 1236 ParseResult::MaybeHyphenValue 1237 } else { 1238 ParseResult::NoMatchingArg { 1239 arg: arg.to_str_lossy().into_owned(), 1240 } 1241 } 1242 } 1243 parse_short_arg( &mut self, matcher: &mut ArgMatcher, short_arg: &RawOsStr, parse_state: &ParseState, pos_counter: usize, valid_arg_found: &mut bool, trailing_values: bool, ) -> ParseResult1244 fn parse_short_arg( 1245 &mut self, 1246 matcher: &mut ArgMatcher, 1247 short_arg: &RawOsStr, 1248 parse_state: &ParseState, 1249 // change this to possible pos_arg when removing the usage of &mut Parser. 1250 pos_counter: usize, 1251 valid_arg_found: &mut bool, 1252 trailing_values: bool, 1253 ) -> ParseResult { 1254 debug!("Parser::parse_short_arg: short_arg={:?}", short_arg); 1255 let arg = short_arg.to_str_lossy(); 1256 1257 if (self.is_set(AS::AllowNegativeNumbers) && arg.parse::<f64>().is_ok()) 1258 || (self.is_set(AS::AllowLeadingHyphen) 1259 && arg.chars().any(|c| !self.app.contains_short(c))) 1260 || matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) 1261 if self.app[opt].is_set(ArgSettings::AllowHyphenValues)) 1262 || self 1263 .app 1264 .args 1265 .get(&pos_counter) 1266 .map_or(false, |arg| arg.is_set(ArgSettings::AllowHyphenValues)) 1267 { 1268 return ParseResult::MaybeHyphenValue; 1269 } 1270 1271 let mut ret = ParseResult::NoArg; 1272 1273 let skip = self.flag_subcmd_skip; 1274 self.flag_subcmd_skip = 0; 1275 for c in arg.chars().skip(skip) { 1276 debug!("Parser::parse_short_arg:iter:{}", c); 1277 1278 // update each index because `-abcd` is four indices to clap 1279 self.cur_idx.set(self.cur_idx.get() + 1); 1280 debug!( 1281 "Parser::parse_short_arg:iter:{}: cur_idx:={}", 1282 c, 1283 self.cur_idx.get() 1284 ); 1285 1286 // Check for matching short options, and return the name if there is no trailing 1287 // concatenated value: -oval 1288 // Option: -o 1289 // Value: val 1290 if let Some(opt) = self.app.args.get(&c) { 1291 debug!( 1292 "Parser::parse_short_arg:iter:{}: Found valid opt or flag", 1293 c 1294 ); 1295 *valid_arg_found = true; 1296 self.seen.push(opt.id.clone()); 1297 if !opt.is_set(ArgSettings::TakesValue) { 1298 if let Some(parse_result) = self.check_for_help_and_version_char(c) { 1299 return parse_result; 1300 } 1301 ret = self.parse_flag(opt, matcher); 1302 continue; 1303 } 1304 1305 // Check for trailing concatenated value 1306 let val = short_arg.split_once(c).expect(INTERNAL_ERROR_MSG).1; 1307 debug!( 1308 "Parser::parse_short_arg:iter:{}: val={:?} (bytes), val={:?} (ascii), short_arg={:?}", 1309 c, val, val.as_raw_bytes(), short_arg 1310 ); 1311 let val = Some(val).filter(|v| !v.is_empty()); 1312 1313 // Default to "we're expecting a value later". 1314 // 1315 // If attached value is not consumed, we may have more short 1316 // flags to parse, continue. 1317 // 1318 // e.g. `-xvf`, when RequireEquals && x.min_vals == 0, we don't 1319 // consume the `vf`, even if it's provided as value. 1320 match self.parse_opt(val, opt, matcher, trailing_values) { 1321 ParseResult::AttachedValueNotConsumed => continue, 1322 x => return x, 1323 } 1324 } 1325 1326 return if let Some(sc_name) = self.app.find_short_subcmd(c) { 1327 debug!("Parser::parse_short_arg:iter:{}: subcommand={}", c, sc_name); 1328 let name = sc_name.to_string(); 1329 let done_short_args = { 1330 let cur_idx = self.cur_idx.get(); 1331 // Get the index of the previously saved flag subcommand in the group of flags (if exists). 1332 // If it is a new flag subcommand, then the formentioned index should be the current one 1333 // (ie. `cur_idx`), and should be registered. 1334 let at = *self.flag_subcmd_at.get_or_insert(cur_idx); 1335 // If we are done, then the difference of indices (cur_idx - at) should be (end - at) which 1336 // should equal to (arg.len() - 1), 1337 // where `end` is the index of the end of the group. 1338 cur_idx - at == arg.len() - 1 1339 }; 1340 if done_short_args { 1341 self.flag_subcmd_at = None; 1342 } 1343 ParseResult::FlagSubCommand(name) 1344 } else { 1345 ParseResult::NoMatchingArg { 1346 arg: format!("-{}", c), 1347 } 1348 }; 1349 } 1350 ret 1351 } 1352 parse_opt( &self, attached_value: Option<&RawOsStr>, opt: &Arg<'help>, matcher: &mut ArgMatcher, trailing_values: bool, ) -> ParseResult1353 fn parse_opt( 1354 &self, 1355 attached_value: Option<&RawOsStr>, 1356 opt: &Arg<'help>, 1357 matcher: &mut ArgMatcher, 1358 trailing_values: bool, 1359 ) -> ParseResult { 1360 debug!( 1361 "Parser::parse_opt; opt={}, val={:?}", 1362 opt.name, attached_value 1363 ); 1364 debug!("Parser::parse_opt; opt.settings={:?}", opt.settings); 1365 // has_eq: --flag=value 1366 let has_eq = matches!(attached_value, Some(fv) if fv.starts_with("=")); 1367 1368 debug!("Parser::parse_opt; Checking for val..."); 1369 // RequireEquals is set, but no '=' is provided, try throwing error. 1370 if opt.is_set(ArgSettings::RequireEquals) && !has_eq { 1371 if opt.min_vals == Some(0) { 1372 debug!("Requires equals, but min_vals == 0"); 1373 // We assume this case is valid: require equals, but min_vals == 0. 1374 if !opt.default_missing_vals.is_empty() { 1375 debug!("Parser::parse_opt: has default_missing_vals"); 1376 self.add_multiple_vals_to_arg( 1377 opt, 1378 opt.default_missing_vals.iter().map(OsString::from), 1379 matcher, 1380 ValueType::CommandLine, 1381 false, 1382 ); 1383 }; 1384 self.inc_occurrence_of_arg(matcher, opt); 1385 if attached_value.is_some() { 1386 ParseResult::AttachedValueNotConsumed 1387 } else { 1388 ParseResult::ValuesDone 1389 } 1390 } else { 1391 debug!("Requires equals but not provided. Error."); 1392 ParseResult::EqualsNotProvided { 1393 arg: opt.to_string(), 1394 } 1395 } 1396 } else if let Some(fv) = attached_value { 1397 let v = fv.strip_prefix("=").unwrap_or(fv); 1398 debug!("Found - {:?}, len: {}", v, v.raw_len()); 1399 debug!( 1400 "Parser::parse_opt: {:?} contains '='...{:?}", 1401 fv, 1402 fv.starts_with("=") 1403 ); 1404 self.add_val_to_arg( 1405 opt, 1406 v, 1407 matcher, 1408 ValueType::CommandLine, 1409 false, 1410 trailing_values, 1411 ); 1412 self.inc_occurrence_of_arg(matcher, opt); 1413 ParseResult::ValuesDone 1414 } else { 1415 debug!("Parser::parse_opt: More arg vals required..."); 1416 self.inc_occurrence_of_arg(matcher, opt); 1417 matcher.new_val_group(&opt.id); 1418 for group in self.app.groups_for_arg(&opt.id) { 1419 matcher.new_val_group(&group); 1420 } 1421 ParseResult::Opt(opt.id.clone()) 1422 } 1423 } 1424 add_val_to_arg( &self, arg: &Arg<'help>, val: &RawOsStr, matcher: &mut ArgMatcher, ty: ValueType, append: bool, trailing_values: bool, ) -> ParseResult1425 fn add_val_to_arg( 1426 &self, 1427 arg: &Arg<'help>, 1428 val: &RawOsStr, 1429 matcher: &mut ArgMatcher, 1430 ty: ValueType, 1431 append: bool, 1432 trailing_values: bool, 1433 ) -> ParseResult { 1434 debug!("Parser::add_val_to_arg; arg={}, val={:?}", arg.name, val); 1435 debug!( 1436 "Parser::add_val_to_arg; trailing_values={:?}, DontDelimTrailingVals={:?}", 1437 trailing_values, 1438 self.is_set(AS::DontDelimitTrailingValues) 1439 ); 1440 if !(trailing_values && self.is_set(AS::DontDelimitTrailingValues)) { 1441 if let Some(delim) = arg.val_delim { 1442 let arg_split = val.split(delim); 1443 let vals = if let Some(t) = arg.terminator { 1444 let mut vals = vec![]; 1445 for val in arg_split { 1446 if t == val { 1447 break; 1448 } 1449 vals.push(val); 1450 } 1451 vals 1452 } else { 1453 arg_split.collect() 1454 }; 1455 self.add_multiple_vals_to_arg( 1456 arg, 1457 vals.into_iter().map(|x| x.to_os_str().into_owned()), 1458 matcher, 1459 ty, 1460 append, 1461 ); 1462 // If there was a delimiter used or we must use the delimiter to 1463 // separate the values or no more vals is needed, we're not 1464 // looking for more values. 1465 return if val.contains(delim) 1466 || arg.is_set(ArgSettings::RequireDelimiter) 1467 || !matcher.needs_more_vals(arg) 1468 { 1469 ParseResult::ValuesDone 1470 } else { 1471 ParseResult::Opt(arg.id.clone()) 1472 }; 1473 } 1474 } 1475 if let Some(t) = arg.terminator { 1476 if t == val { 1477 return ParseResult::ValuesDone; 1478 } 1479 } 1480 self.add_single_val_to_arg(arg, val.to_os_str().into_owned(), matcher, ty, append); 1481 if matcher.needs_more_vals(arg) { 1482 ParseResult::Opt(arg.id.clone()) 1483 } else { 1484 ParseResult::ValuesDone 1485 } 1486 } 1487 add_multiple_vals_to_arg( &self, arg: &Arg<'help>, vals: impl Iterator<Item = OsString>, matcher: &mut ArgMatcher, ty: ValueType, append: bool, )1488 fn add_multiple_vals_to_arg( 1489 &self, 1490 arg: &Arg<'help>, 1491 vals: impl Iterator<Item = OsString>, 1492 matcher: &mut ArgMatcher, 1493 ty: ValueType, 1494 append: bool, 1495 ) { 1496 // If not appending, create a new val group and then append vals in. 1497 if !append { 1498 matcher.new_val_group(&arg.id); 1499 for group in self.app.groups_for_arg(&arg.id) { 1500 matcher.new_val_group(&group); 1501 } 1502 } 1503 for val in vals { 1504 self.add_single_val_to_arg(arg, val, matcher, ty, true); 1505 } 1506 } 1507 add_single_val_to_arg( &self, arg: &Arg<'help>, val: OsString, matcher: &mut ArgMatcher, ty: ValueType, append: bool, )1508 fn add_single_val_to_arg( 1509 &self, 1510 arg: &Arg<'help>, 1511 val: OsString, 1512 matcher: &mut ArgMatcher, 1513 ty: ValueType, 1514 append: bool, 1515 ) { 1516 debug!("Parser::add_single_val_to_arg: adding val...{:?}", val); 1517 1518 // update the current index because each value is a distinct index to clap 1519 self.cur_idx.set(self.cur_idx.get() + 1); 1520 debug!( 1521 "Parser::add_single_val_to_arg: cur_idx:={}", 1522 self.cur_idx.get() 1523 ); 1524 1525 // Increment or create the group "args" 1526 for group in self.app.groups_for_arg(&arg.id) { 1527 matcher.add_val_to(&group, val.clone(), ty, append); 1528 } 1529 1530 matcher.add_val_to(&arg.id, val, ty, append); 1531 matcher.add_index_to(&arg.id, self.cur_idx.get(), ty); 1532 } 1533 arg_have_val(&self, matcher: &mut ArgMatcher, arg: &Arg<'help>) -> bool1534 fn arg_have_val(&self, matcher: &mut ArgMatcher, arg: &Arg<'help>) -> bool { 1535 matcher.arg_have_val(&arg.id) 1536 } 1537 parse_flag(&self, flag: &Arg<'help>, matcher: &mut ArgMatcher) -> ParseResult1538 fn parse_flag(&self, flag: &Arg<'help>, matcher: &mut ArgMatcher) -> ParseResult { 1539 debug!("Parser::parse_flag"); 1540 1541 matcher.add_index_to(&flag.id, self.cur_idx.get(), ValueType::CommandLine); 1542 self.inc_occurrence_of_arg(matcher, flag); 1543 1544 ParseResult::ValuesDone 1545 } 1546 remove_overrides(&mut self, matcher: &mut ArgMatcher)1547 fn remove_overrides(&mut self, matcher: &mut ArgMatcher) { 1548 debug!("Parser::remove_overrides"); 1549 let mut to_rem: Vec<Id> = Vec::new(); 1550 let mut self_override: Vec<Id> = Vec::new(); 1551 let mut arg_overrides = Vec::new(); 1552 for name in matcher.arg_names() { 1553 debug!("Parser::remove_overrides:iter:{:?}", name); 1554 if let Some(overrider) = self.app.find(name) { 1555 let mut override_self = false; 1556 for overridee in &overrider.overrides { 1557 debug!( 1558 "Parser::remove_overrides:iter:{:?} => {:?}", 1559 name, overrider 1560 ); 1561 if *overridee == overrider.id { 1562 override_self = true; 1563 } else { 1564 arg_overrides.push((overrider.id.clone(), overridee)); 1565 arg_overrides.push((overridee.clone(), &overrider.id)); 1566 } 1567 } 1568 // Only do self override for argument that is not positional 1569 // argument or flag with MultipleOccurrences setting enabled. 1570 if (self.is_set(AS::AllArgsOverrideSelf) || override_self) 1571 && !overrider.is_set(ArgSettings::MultipleOccurrences) 1572 && !overrider.is_positional() 1573 { 1574 debug!( 1575 "Parser::remove_overrides:iter:{:?}:iter:{:?}: self override", 1576 name, overrider 1577 ); 1578 self_override.push(overrider.id.clone()); 1579 } 1580 } 1581 } 1582 1583 // remove future overrides in reverse seen order 1584 for arg in self.seen.iter().rev() { 1585 for (a, overr) in arg_overrides.iter().filter(|(a, _)| a == arg) { 1586 if !to_rem.contains(a) { 1587 to_rem.push((*overr).clone()); 1588 } 1589 } 1590 } 1591 1592 // Do self overrides 1593 for name in &self_override { 1594 debug!("Parser::remove_overrides:iter:self:{:?}: resetting", name); 1595 if let Some(ma) = matcher.get_mut(name) { 1596 ma.occurs = 1; 1597 ma.override_vals(); 1598 } 1599 } 1600 1601 // Finally remove conflicts 1602 for name in &to_rem { 1603 debug!("Parser::remove_overrides:iter:{:?}: removing", name); 1604 matcher.remove(name); 1605 self.overridden.push(name.clone()); 1606 } 1607 } 1608 add_defaults(&mut self, matcher: &mut ArgMatcher, trailing_values: bool)1609 pub(crate) fn add_defaults(&mut self, matcher: &mut ArgMatcher, trailing_values: bool) { 1610 debug!("Parser::add_defaults"); 1611 1612 for o in self.app.get_opts() { 1613 debug!("Parser::add_defaults:iter:{}:", o.name); 1614 self.add_value(o, matcher, ValueType::DefaultValue, trailing_values); 1615 } 1616 1617 for p in self.app.get_positionals() { 1618 debug!("Parser::add_defaults:iter:{}:", p.name); 1619 self.add_value(p, matcher, ValueType::DefaultValue, trailing_values); 1620 } 1621 } 1622 add_value( &self, arg: &Arg<'help>, matcher: &mut ArgMatcher, ty: ValueType, trailing_values: bool, )1623 fn add_value( 1624 &self, 1625 arg: &Arg<'help>, 1626 matcher: &mut ArgMatcher, 1627 ty: ValueType, 1628 trailing_values: bool, 1629 ) { 1630 if !arg.default_vals_ifs.is_empty() { 1631 debug!("Parser::add_value: has conditional defaults"); 1632 if matcher.get(&arg.id).is_none() { 1633 for (id, val, default) in arg.default_vals_ifs.iter() { 1634 let add = if let Some(a) = matcher.get(id) { 1635 if let Some(v) = val { 1636 a.vals_flatten().any(|value| v == value) 1637 } else { 1638 true 1639 } 1640 } else { 1641 false 1642 }; 1643 1644 if add { 1645 if let Some(default) = default { 1646 self.add_val_to_arg( 1647 arg, 1648 &RawOsStr::new(default), 1649 matcher, 1650 ty, 1651 false, 1652 trailing_values, 1653 ); 1654 } 1655 return; 1656 } 1657 } 1658 } 1659 } else { 1660 debug!("Parser::add_value: doesn't have conditional defaults"); 1661 } 1662 1663 fn process_default_vals(arg: &Arg<'_>, default_vals: &[&OsStr]) -> Vec<OsString> { 1664 if let Some(delim) = arg.val_delim { 1665 let mut vals = vec![]; 1666 for val in default_vals { 1667 let val = RawOsStr::new(val); 1668 for val in val.split(delim) { 1669 vals.push(val.to_os_str().into_owned()); 1670 } 1671 } 1672 vals 1673 } else { 1674 default_vals.iter().map(OsString::from).collect() 1675 } 1676 } 1677 1678 if !arg.default_vals.is_empty() { 1679 debug!("Parser::add_value:iter:{}: has default vals", arg.name); 1680 if matcher.get(&arg.id).is_some() { 1681 debug!("Parser::add_value:iter:{}: was used", arg.name); 1682 // do nothing 1683 } else { 1684 debug!("Parser::add_value:iter:{}: wasn't used", arg.name); 1685 1686 self.add_multiple_vals_to_arg( 1687 arg, 1688 process_default_vals(arg, &arg.default_vals).into_iter(), 1689 matcher, 1690 ty, 1691 false, 1692 ); 1693 } 1694 } else { 1695 debug!( 1696 "Parser::add_value:iter:{}: doesn't have default vals", 1697 arg.name 1698 ); 1699 1700 // do nothing 1701 } 1702 1703 if !arg.default_missing_vals.is_empty() { 1704 debug!( 1705 "Parser::add_value:iter:{}: has default missing vals", 1706 arg.name 1707 ); 1708 match matcher.get(&arg.id) { 1709 Some(ma) if ma.is_vals_empty() => { 1710 debug!( 1711 "Parser::add_value:iter:{}: has no user defined vals", 1712 arg.name 1713 ); 1714 self.add_multiple_vals_to_arg( 1715 arg, 1716 process_default_vals(arg, &arg.default_missing_vals).into_iter(), 1717 matcher, 1718 ty, 1719 false, 1720 ); 1721 } 1722 None => { 1723 debug!("Parser::add_value:iter:{}: wasn't used", arg.name); 1724 // do nothing 1725 } 1726 _ => { 1727 debug!("Parser::add_value:iter:{}: has user defined vals", arg.name); 1728 // do nothing 1729 } 1730 } 1731 } else { 1732 debug!( 1733 "Parser::add_value:iter:{}: doesn't have default missing vals", 1734 arg.name 1735 ); 1736 1737 // do nothing 1738 } 1739 } 1740 1741 #[cfg(feature = "env")] add_env( &mut self, matcher: &mut ArgMatcher, trailing_values: bool, ) -> ClapResult<()>1742 pub(crate) fn add_env( 1743 &mut self, 1744 matcher: &mut ArgMatcher, 1745 trailing_values: bool, 1746 ) -> ClapResult<()> { 1747 use crate::util::str_to_bool; 1748 1749 self.app.args.args().try_for_each(|a| { 1750 // Use env only if the arg was absent among command line args, 1751 // early return if this is not the case. 1752 if matcher.get(&a.id).map_or(false, |a| a.occurs != 0) { 1753 debug!("Parser::add_env: Skipping existing arg `{}`", a); 1754 return Ok(()); 1755 } 1756 1757 debug!("Parser::add_env: Checking arg `{}`", a); 1758 if let Some((_, Some(ref val))) = a.env { 1759 let val = RawOsStr::new(val); 1760 1761 if a.is_set(ArgSettings::TakesValue) { 1762 debug!( 1763 "Parser::add_env: Found an opt with value={:?}, trailing={:?}", 1764 val, trailing_values 1765 ); 1766 self.add_val_to_arg( 1767 a, 1768 &val, 1769 matcher, 1770 ValueType::EnvVariable, 1771 false, 1772 trailing_values, 1773 ); 1774 return Ok(()); 1775 } 1776 1777 debug!("Parser::add_env: Checking for help and version"); 1778 // Early return on `HelpFlag` or `VersionFlag`. 1779 match self.check_for_help_and_version_str(&val) { 1780 Some(ParseResult::HelpFlag) => { 1781 return Err(self.help_err(true)); 1782 } 1783 Some(ParseResult::VersionFlag) => { 1784 return Err(self.version_err(true)); 1785 } 1786 _ => (), 1787 } 1788 1789 debug!("Parser::add_env: Found a flag with value `{:?}`", val); 1790 let predicate = str_to_bool(val.to_str_lossy()); 1791 debug!("Parser::add_env: Found boolean literal `{}`", predicate); 1792 if predicate { 1793 matcher.add_index_to(&a.id, self.cur_idx.get(), ValueType::EnvVariable); 1794 } 1795 } 1796 1797 Ok(()) 1798 }) 1799 } 1800 1801 /// Increase occurrence of specific argument and the grouped arg it's in. inc_occurrence_of_arg(&self, matcher: &mut ArgMatcher, arg: &Arg<'help>)1802 fn inc_occurrence_of_arg(&self, matcher: &mut ArgMatcher, arg: &Arg<'help>) { 1803 matcher.inc_occurrence_of(&arg.id, arg.is_set(ArgSettings::IgnoreCase)); 1804 // Increment or create the group "args" 1805 for group in self.app.groups_for_arg(&arg.id) { 1806 matcher.inc_occurrence_of(&group, false); 1807 } 1808 } 1809 } 1810 1811 // Error, Help, and Version Methods 1812 impl<'help, 'app> Parser<'help, 'app> { 1813 /// 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: &[&str], ) -> ClapError1814 fn did_you_mean_error( 1815 &mut self, 1816 arg: &str, 1817 matcher: &mut ArgMatcher, 1818 remaining_args: &[&str], 1819 ) -> ClapError { 1820 debug!("Parser::did_you_mean_error: arg={}", arg); 1821 // Didn't match a flag or option 1822 let longs = self 1823 .app 1824 .args 1825 .keys() 1826 .filter_map(|x| match x { 1827 KeyType::Long(l) => Some(l.to_string_lossy().into_owned()), 1828 _ => None, 1829 }) 1830 .collect::<Vec<_>>(); 1831 debug!("Parser::did_you_mean_error: longs={:?}", longs); 1832 1833 let did_you_mean = suggestions::did_you_mean_flag( 1834 arg, 1835 remaining_args, 1836 longs.iter().map(|x| &x[..]), 1837 self.app.subcommands.as_mut_slice(), 1838 ); 1839 1840 // Add the arg to the matches to build a proper usage string 1841 if let Some((name, _)) = did_you_mean.as_ref() { 1842 if let Some(opt) = self.app.args.get(&name.as_ref()) { 1843 self.inc_occurrence_of_arg(matcher, opt); 1844 } 1845 } 1846 1847 let used: Vec<Id> = matcher 1848 .arg_names() 1849 .filter(|n| { 1850 self.app.find(n).map_or(true, |a| { 1851 !(self.required.contains(&a.id) || a.is_set(ArgSettings::Hidden)) 1852 }) 1853 }) 1854 .cloned() 1855 .collect(); 1856 1857 ClapError::unknown_argument( 1858 self.app, 1859 format!("--{}", arg), 1860 did_you_mean, 1861 Usage::new(self).create_usage_with_title(&*used), 1862 ) 1863 } 1864 write_help_err(&self) -> ClapResult<Colorizer>1865 pub(crate) fn write_help_err(&self) -> ClapResult<Colorizer> { 1866 let mut c = Colorizer::new(true, self.app.get_color()); 1867 Help::new(HelpWriter::Buffer(&mut c), self, false).write_help()?; 1868 Ok(c) 1869 } 1870 help_err(&self, mut use_long: bool) -> ClapError1871 fn help_err(&self, mut use_long: bool) -> ClapError { 1872 debug!( 1873 "Parser::help_err: use_long={:?}", 1874 use_long && self.use_long_help() 1875 ); 1876 1877 use_long = use_long && self.use_long_help(); 1878 let mut c = Colorizer::new(false, self.app.get_color()); 1879 1880 match Help::new(HelpWriter::Buffer(&mut c), self, use_long).write_help() { 1881 Err(e) => e.into(), 1882 _ => ClapError::new(c, ErrorKind::DisplayHelp), 1883 } 1884 } 1885 version_err(&self, use_long: bool) -> ClapError1886 fn version_err(&self, use_long: bool) -> ClapError { 1887 debug!("Parser::version_err"); 1888 1889 let msg = self.app._render_version(use_long); 1890 let mut c = Colorizer::new(false, self.app.get_color()); 1891 c.none(msg); 1892 ClapError::new(c, ErrorKind::DisplayVersion) 1893 } 1894 } 1895 1896 // Query Methods 1897 impl<'help, 'app> Parser<'help, 'app> { is_set(&self, s: AS) -> bool1898 pub(crate) fn is_set(&self, s: AS) -> bool { 1899 self.app.is_set(s) 1900 } 1901 } 1902