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