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