1 // Std 2 #[cfg(all(feature = "debug", any(target_os = "windows", target_arch = "wasm32")))] 3 use osstringext::OsStrExt3; 4 use std::cell::Cell; 5 use std::ffi::{OsStr, OsString}; 6 use std::fmt::Display; 7 use std::fs::File; 8 use std::io::{self, BufWriter, Write}; 9 use std::iter::Peekable; 10 #[cfg(all( 11 feature = "debug", 12 not(any(target_os = "windows", target_arch = "wasm32")) 13 ))] 14 use std::os::unix::ffi::OsStrExt; 15 use std::path::PathBuf; 16 use std::slice::Iter; 17 18 // Internal 19 use app::help::Help; 20 use app::meta::AppMeta; 21 use app::settings::AppFlags; 22 use app::settings::AppSettings as AS; 23 use app::usage; 24 use app::validator::Validator; 25 use app::App; 26 use args::settings::ArgSettings; 27 use args::{ 28 AnyArg, Arg, ArgGroup, ArgMatcher, Base, FlagBuilder, OptBuilder, PosBuilder, Switched, 29 }; 30 use completions::ComplGen; 31 use completions::Shell; 32 use errors::Result as ClapResult; 33 use errors::{Error, ErrorKind}; 34 use fmt::ColorWhen; 35 use map::{self, VecMap}; 36 use osstringext::OsStrExt2; 37 use suggestions; 38 use SubCommand; 39 use INTERNAL_ERROR_MSG; 40 use INVALID_UTF8; 41 42 #[derive(Debug, PartialEq, Copy, Clone)] 43 #[doc(hidden)] 44 pub enum ParseResult<'a> { 45 Flag, 46 Opt(&'a str), 47 Pos(&'a str), 48 MaybeHyphenValue, 49 MaybeNegNum, 50 NotFound, 51 ValuesDone, 52 } 53 54 #[allow(missing_debug_implementations)] 55 #[doc(hidden)] 56 #[derive(Clone, Default)] 57 pub struct Parser<'a, 'b> 58 where 59 'a: 'b, 60 { 61 pub meta: AppMeta<'b>, 62 settings: AppFlags, 63 pub g_settings: AppFlags, 64 pub flags: Vec<FlagBuilder<'a, 'b>>, 65 pub opts: Vec<OptBuilder<'a, 'b>>, 66 pub positionals: VecMap<PosBuilder<'a, 'b>>, 67 pub subcommands: Vec<App<'a, 'b>>, 68 pub groups: Vec<ArgGroup<'a>>, 69 pub global_args: Vec<Arg<'a, 'b>>, 70 pub required: Vec<&'a str>, 71 pub r_ifs: Vec<(&'a str, &'b str, &'a str)>, 72 pub overrides: Vec<(&'b str, &'a str)>, 73 help_short: Option<char>, 74 version_short: Option<char>, 75 cache: Option<&'a str>, 76 pub help_message: Option<&'a str>, 77 pub version_message: Option<&'a str>, 78 cur_idx: Cell<usize>, 79 } 80 81 impl<'a, 'b> Parser<'a, 'b> 82 where 83 'a: 'b, 84 { with_name(n: String) -> Self85 pub fn with_name(n: String) -> Self { 86 Parser { 87 meta: AppMeta::with_name(n), 88 g_settings: AppFlags::zeroed(), 89 cur_idx: Cell::new(0), 90 ..Default::default() 91 } 92 } 93 help_short(&mut self, s: &str)94 pub fn help_short(&mut self, s: &str) { 95 let c = s 96 .trim_left_matches(|c| c == '-') 97 .chars() 98 .nth(0) 99 .unwrap_or('h'); 100 self.help_short = Some(c); 101 } 102 version_short(&mut self, s: &str)103 pub fn version_short(&mut self, s: &str) { 104 let c = s 105 .trim_left_matches(|c| c == '-') 106 .chars() 107 .nth(0) 108 .unwrap_or('V'); 109 self.version_short = Some(c); 110 } 111 gen_completions_to<W: Write>(&mut self, for_shell: Shell, buf: &mut W)112 pub fn gen_completions_to<W: Write>(&mut self, for_shell: Shell, buf: &mut W) { 113 if !self.is_set(AS::Propagated) { 114 self.propagate_help_version(); 115 self.build_bin_names(); 116 self.propagate_globals(); 117 self.propagate_settings(); 118 self.set(AS::Propagated); 119 } 120 121 ComplGen::new(self).generate(for_shell, buf) 122 } 123 gen_completions(&mut self, for_shell: Shell, od: OsString)124 pub fn gen_completions(&mut self, for_shell: Shell, od: OsString) { 125 use std::error::Error; 126 127 let out_dir = PathBuf::from(od); 128 let name = &*self.meta.bin_name.as_ref().unwrap().clone(); 129 let file_name = match for_shell { 130 Shell::Bash => format!("{}.bash", name), 131 Shell::Fish => format!("{}.fish", name), 132 Shell::Zsh => format!("_{}", name), 133 Shell::PowerShell => format!("_{}.ps1", name), 134 Shell::Elvish => format!("{}.elv", name), 135 }; 136 137 let mut file = match File::create(out_dir.join(file_name)) { 138 Err(why) => panic!("couldn't create completion file: {}", why.description()), 139 Ok(file) => file, 140 }; 141 self.gen_completions_to(for_shell, &mut file) 142 } 143 144 #[inline] app_debug_asserts(&self) -> bool145 fn app_debug_asserts(&self) -> bool { 146 assert!(self.verify_positionals()); 147 let should_err = self.groups.iter().all(|g| { 148 g.args.iter().all(|arg| { 149 (self.flags.iter().any(|f| &f.b.name == arg) 150 || self.opts.iter().any(|o| &o.b.name == arg) 151 || self.positionals.values().any(|p| &p.b.name == arg) 152 || self.groups.iter().any(|g| &g.name == arg)) 153 }) 154 }); 155 let g = self.groups.iter().find(|g| { 156 g.args.iter().any(|arg| { 157 !(self.flags.iter().any(|f| &f.b.name == arg) 158 || self.opts.iter().any(|o| &o.b.name == arg) 159 || self.positionals.values().any(|p| &p.b.name == arg) 160 || self.groups.iter().any(|g| &g.name == arg)) 161 }) 162 }); 163 assert!( 164 should_err, 165 "The group '{}' contains the arg '{}' that doesn't actually exist.", 166 g.unwrap().name, 167 g.unwrap() 168 .args 169 .iter() 170 .find(|arg| !(self.flags.iter().any(|f| &&f.b.name == arg) 171 || self.opts.iter().any(|o| &&o.b.name == arg) 172 || self.positionals.values().any(|p| &&p.b.name == arg) 173 || self.groups.iter().any(|g| &&g.name == arg))) 174 .unwrap() 175 ); 176 true 177 } 178 179 #[inline] debug_asserts(&self, a: &Arg) -> bool180 fn debug_asserts(&self, a: &Arg) -> bool { 181 assert!( 182 !arg_names!(self).any(|name| name == a.b.name), 183 format!("Non-unique argument name: {} is already in use", a.b.name) 184 ); 185 if let Some(l) = a.s.long { 186 assert!( 187 !self.contains_long(l), 188 "Argument long must be unique\n\n\t--{} is already in use", 189 l 190 ); 191 } 192 if let Some(s) = a.s.short { 193 assert!( 194 !self.contains_short(s), 195 "Argument short must be unique\n\n\t-{} is already in use", 196 s 197 ); 198 } 199 let i = if a.index.is_none() { 200 (self.positionals.len() + 1) 201 } else { 202 a.index.unwrap() as usize 203 }; 204 assert!( 205 !self.positionals.contains_key(i), 206 "Argument \"{}\" has the same index as another positional \ 207 argument\n\n\tPerhaps try .multiple(true) to allow one positional argument \ 208 to take multiple values", 209 a.b.name 210 ); 211 assert!( 212 !(a.is_set(ArgSettings::Required) && a.is_set(ArgSettings::Global)), 213 "Global arguments cannot be required.\n\n\t'{}' is marked as \ 214 global and required", 215 a.b.name 216 ); 217 if a.b.is_set(ArgSettings::Last) { 218 assert!( 219 !self 220 .positionals 221 .values() 222 .any(|p| p.b.is_set(ArgSettings::Last)), 223 "Only one positional argument may have last(true) set. Found two." 224 ); 225 assert!(a.s.long.is_none(), 226 "Flags or Options may not have last(true) set. {} has both a long and last(true) set.", 227 a.b.name); 228 assert!(a.s.short.is_none(), 229 "Flags or Options may not have last(true) set. {} has both a short and last(true) set.", 230 a.b.name); 231 } 232 true 233 } 234 235 #[inline] add_conditional_reqs(&mut self, a: &Arg<'a, 'b>)236 fn add_conditional_reqs(&mut self, a: &Arg<'a, 'b>) { 237 if let Some(ref r_ifs) = a.r_ifs { 238 for &(arg, val) in r_ifs { 239 self.r_ifs.push((arg, val, a.b.name)); 240 } 241 } 242 } 243 244 #[inline] add_arg_groups(&mut self, a: &Arg<'a, 'b>)245 fn add_arg_groups(&mut self, a: &Arg<'a, 'b>) { 246 if let Some(ref grps) = a.b.groups { 247 for g in grps { 248 let mut found = false; 249 if let Some(ref mut ag) = self.groups.iter_mut().find(|grp| &grp.name == g) { 250 ag.args.push(a.b.name); 251 found = true; 252 } 253 if !found { 254 let mut ag = ArgGroup::with_name(g); 255 ag.args.push(a.b.name); 256 self.groups.push(ag); 257 } 258 } 259 } 260 } 261 262 #[inline] add_reqs(&mut self, a: &Arg<'a, 'b>)263 fn add_reqs(&mut self, a: &Arg<'a, 'b>) { 264 if a.is_set(ArgSettings::Required) { 265 // If the arg is required, add all it's requirements to master required list 266 self.required.push(a.b.name); 267 if let Some(ref areqs) = a.b.requires { 268 for name in areqs 269 .iter() 270 .filter(|&&(val, _)| val.is_none()) 271 .map(|&(_, name)| name) 272 { 273 self.required.push(name); 274 } 275 } 276 } 277 } 278 279 #[inline] implied_settings(&mut self, a: &Arg<'a, 'b>)280 fn implied_settings(&mut self, a: &Arg<'a, 'b>) { 281 if a.is_set(ArgSettings::Last) { 282 // if an arg has `Last` set, we need to imply DontCollapseArgsInUsage so that args 283 // in the usage string don't get confused or left out. 284 self.set(AS::DontCollapseArgsInUsage); 285 self.set(AS::ContainsLast); 286 } 287 if let Some(l) = a.s.long { 288 if l == "version" { 289 self.unset(AS::NeedsLongVersion); 290 } else if l == "help" { 291 self.unset(AS::NeedsLongHelp); 292 } 293 } 294 } 295 296 // actually adds the arguments add_arg(&mut self, a: Arg<'a, 'b>)297 pub fn add_arg(&mut self, a: Arg<'a, 'b>) { 298 // if it's global we have to clone anyways 299 if a.is_set(ArgSettings::Global) { 300 return self.add_arg_ref(&a); 301 } 302 debug_assert!(self.debug_asserts(&a)); 303 self.add_conditional_reqs(&a); 304 self.add_arg_groups(&a); 305 self.add_reqs(&a); 306 self.implied_settings(&a); 307 if a.index.is_some() || (a.s.short.is_none() && a.s.long.is_none()) { 308 let i = if a.index.is_none() { 309 (self.positionals.len() + 1) 310 } else { 311 a.index.unwrap() as usize 312 }; 313 self.positionals 314 .insert(i, PosBuilder::from_arg(a, i as u64)); 315 } else if a.is_set(ArgSettings::TakesValue) { 316 let mut ob = OptBuilder::from(a); 317 ob.s.unified_ord = self.flags.len() + self.opts.len(); 318 self.opts.push(ob); 319 } else { 320 let mut fb = FlagBuilder::from(a); 321 fb.s.unified_ord = self.flags.len() + self.opts.len(); 322 self.flags.push(fb); 323 } 324 } 325 // actually adds the arguments but from a borrow (which means we have to do some cloning) add_arg_ref(&mut self, a: &Arg<'a, 'b>)326 pub fn add_arg_ref(&mut self, a: &Arg<'a, 'b>) { 327 debug_assert!(self.debug_asserts(a)); 328 self.add_conditional_reqs(a); 329 self.add_arg_groups(a); 330 self.add_reqs(a); 331 self.implied_settings(a); 332 if a.index.is_some() || (a.s.short.is_none() && a.s.long.is_none()) { 333 let i = if a.index.is_none() { 334 (self.positionals.len() + 1) 335 } else { 336 a.index.unwrap() as usize 337 }; 338 let pb = PosBuilder::from_arg_ref(a, i as u64); 339 self.positionals.insert(i, pb); 340 } else if a.is_set(ArgSettings::TakesValue) { 341 let mut ob = OptBuilder::from(a); 342 ob.s.unified_ord = self.flags.len() + self.opts.len(); 343 self.opts.push(ob); 344 } else { 345 let mut fb = FlagBuilder::from(a); 346 fb.s.unified_ord = self.flags.len() + self.opts.len(); 347 self.flags.push(fb); 348 } 349 if a.is_set(ArgSettings::Global) { 350 self.global_args.push(a.into()); 351 } 352 } 353 add_group(&mut self, group: ArgGroup<'a>)354 pub fn add_group(&mut self, group: ArgGroup<'a>) { 355 if group.required { 356 self.required.push(group.name); 357 if let Some(ref reqs) = group.requires { 358 self.required.extend_from_slice(reqs); 359 } 360 // if let Some(ref bl) = group.conflicts { 361 // self.blacklist.extend_from_slice(bl); 362 // } 363 } 364 if self.groups.iter().any(|g| g.name == group.name) { 365 let grp = self 366 .groups 367 .iter_mut() 368 .find(|g| g.name == group.name) 369 .expect(INTERNAL_ERROR_MSG); 370 grp.args.extend_from_slice(&group.args); 371 grp.requires = group.requires.clone(); 372 grp.conflicts = group.conflicts.clone(); 373 grp.required = group.required; 374 } else { 375 self.groups.push(group); 376 } 377 } 378 add_subcommand(&mut self, mut subcmd: App<'a, 'b>)379 pub fn add_subcommand(&mut self, mut subcmd: App<'a, 'b>) { 380 debugln!( 381 "Parser::add_subcommand: term_w={:?}, name={}", 382 self.meta.term_w, 383 subcmd.p.meta.name 384 ); 385 subcmd.p.meta.term_w = self.meta.term_w; 386 if subcmd.p.meta.name == "help" { 387 self.unset(AS::NeedsSubcommandHelp); 388 } 389 390 self.subcommands.push(subcmd); 391 } 392 propagate_settings(&mut self)393 pub fn propagate_settings(&mut self) { 394 debugln!( 395 "Parser::propagate_settings: self={}, g_settings={:#?}", 396 self.meta.name, 397 self.g_settings 398 ); 399 for sc in &mut self.subcommands { 400 debugln!( 401 "Parser::propagate_settings: sc={}, settings={:#?}, g_settings={:#?}", 402 sc.p.meta.name, 403 sc.p.settings, 404 sc.p.g_settings 405 ); 406 // We have to create a new scope in order to tell rustc the borrow of `sc` is 407 // done and to recursively call this method 408 { 409 let vsc = self.settings.is_set(AS::VersionlessSubcommands); 410 let gv = self.settings.is_set(AS::GlobalVersion); 411 412 if vsc { 413 sc.p.set(AS::DisableVersion); 414 } 415 if gv && sc.p.meta.version.is_none() && self.meta.version.is_some() { 416 sc.p.set(AS::GlobalVersion); 417 sc.p.meta.version = Some(self.meta.version.unwrap()); 418 } 419 sc.p.settings = sc.p.settings | self.g_settings; 420 sc.p.g_settings = sc.p.g_settings | self.g_settings; 421 sc.p.meta.term_w = self.meta.term_w; 422 sc.p.meta.max_w = self.meta.max_w; 423 } 424 sc.p.propagate_settings(); 425 } 426 } 427 428 #[cfg_attr(feature = "lints", allow(needless_borrow))] derive_display_order(&mut self)429 pub fn derive_display_order(&mut self) { 430 if self.is_set(AS::DeriveDisplayOrder) { 431 let unified = self.is_set(AS::UnifiedHelpMessage); 432 for (i, o) in self 433 .opts 434 .iter_mut() 435 .enumerate() 436 .filter(|&(_, ref o)| o.s.disp_ord == 999) 437 { 438 o.s.disp_ord = if unified { o.s.unified_ord } else { i }; 439 } 440 for (i, f) in self 441 .flags 442 .iter_mut() 443 .enumerate() 444 .filter(|&(_, ref f)| f.s.disp_ord == 999) 445 { 446 f.s.disp_ord = if unified { f.s.unified_ord } else { i }; 447 } 448 for (i, sc) in &mut self 449 .subcommands 450 .iter_mut() 451 .enumerate() 452 .filter(|&(_, ref sc)| sc.p.meta.disp_ord == 999) 453 { 454 sc.p.meta.disp_ord = i; 455 } 456 } 457 for sc in &mut self.subcommands { 458 sc.p.derive_display_order(); 459 } 460 } 461 required(&self) -> Iter<&str>462 pub fn required(&self) -> Iter<&str> { 463 self.required.iter() 464 } 465 466 #[cfg_attr(feature = "lints", allow(needless_borrow))] 467 #[inline] has_args(&self) -> bool468 pub fn has_args(&self) -> bool { 469 !(self.flags.is_empty() && self.opts.is_empty() && self.positionals.is_empty()) 470 } 471 472 #[inline] has_opts(&self) -> bool473 pub fn has_opts(&self) -> bool { 474 !self.opts.is_empty() 475 } 476 477 #[inline] has_flags(&self) -> bool478 pub fn has_flags(&self) -> bool { 479 !self.flags.is_empty() 480 } 481 482 #[inline] has_positionals(&self) -> bool483 pub fn has_positionals(&self) -> bool { 484 !self.positionals.is_empty() 485 } 486 487 #[inline] has_subcommands(&self) -> bool488 pub fn has_subcommands(&self) -> bool { 489 !self.subcommands.is_empty() 490 } 491 492 #[inline] has_visible_opts(&self) -> bool493 pub fn has_visible_opts(&self) -> bool { 494 if self.opts.is_empty() { 495 return false; 496 } 497 self.opts.iter().any(|o| !o.is_set(ArgSettings::Hidden)) 498 } 499 500 #[inline] has_visible_flags(&self) -> bool501 pub fn has_visible_flags(&self) -> bool { 502 if self.flags.is_empty() { 503 return false; 504 } 505 self.flags.iter().any(|f| !f.is_set(ArgSettings::Hidden)) 506 } 507 508 #[inline] has_visible_positionals(&self) -> bool509 pub fn has_visible_positionals(&self) -> bool { 510 if self.positionals.is_empty() { 511 return false; 512 } 513 self.positionals 514 .values() 515 .any(|p| !p.is_set(ArgSettings::Hidden)) 516 } 517 518 #[inline] has_visible_subcommands(&self) -> bool519 pub fn has_visible_subcommands(&self) -> bool { 520 self.has_subcommands() 521 && self 522 .subcommands 523 .iter() 524 .filter(|sc| sc.p.meta.name != "help") 525 .any(|sc| !sc.p.is_set(AS::Hidden)) 526 } 527 528 #[inline] is_set(&self, s: AS) -> bool529 pub fn is_set(&self, s: AS) -> bool { 530 self.settings.is_set(s) 531 } 532 533 #[inline] set(&mut self, s: AS)534 pub fn set(&mut self, s: AS) { 535 self.settings.set(s) 536 } 537 538 #[inline] unset(&mut self, s: AS)539 pub fn unset(&mut self, s: AS) { 540 self.settings.unset(s) 541 } 542 543 #[cfg_attr(feature = "lints", allow(block_in_if_condition_stmt))] verify_positionals(&self) -> bool544 pub fn verify_positionals(&self) -> bool { 545 // Because you must wait until all arguments have been supplied, this is the first chance 546 // to make assertions on positional argument indexes 547 // 548 // First we verify that the index highest supplied index, is equal to the number of 549 // positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3 550 // but no 2) 551 if let Some((idx, p)) = self.positionals.iter().rev().next() { 552 assert!( 553 !(idx != self.positionals.len()), 554 "Found positional argument \"{}\" whose index is {} but there \ 555 are only {} positional arguments defined", 556 p.b.name, 557 idx, 558 self.positionals.len() 559 ); 560 } 561 562 // Next we verify that only the highest index has a .multiple(true) (if any) 563 if self.positionals.values().any(|a| { 564 a.b.is_set(ArgSettings::Multiple) && (a.index as usize != self.positionals.len()) 565 }) { 566 let mut it = self.positionals.values().rev(); 567 let last = it.next().unwrap(); 568 let second_to_last = it.next().unwrap(); 569 // Either the final positional is required 570 // Or the second to last has a terminator or .last(true) set 571 let ok = last.is_set(ArgSettings::Required) 572 || (second_to_last.v.terminator.is_some() 573 || second_to_last.b.is_set(ArgSettings::Last)) 574 || last.is_set(ArgSettings::Last); 575 assert!( 576 ok, 577 "When using a positional argument with .multiple(true) that is *not the \ 578 last* positional argument, the last positional argument (i.e the one \ 579 with the highest index) *must* have .required(true) or .last(true) set." 580 ); 581 let ok = second_to_last.is_set(ArgSettings::Multiple) || last.is_set(ArgSettings::Last); 582 assert!( 583 ok, 584 "Only the last positional argument, or second to last positional \ 585 argument may be set to .multiple(true)" 586 ); 587 588 let count = self 589 .positionals 590 .values() 591 .filter(|p| p.b.settings.is_set(ArgSettings::Multiple) && p.v.num_vals.is_none()) 592 .count(); 593 let ok = count <= 1 594 || (last.is_set(ArgSettings::Last) 595 && last.is_set(ArgSettings::Multiple) 596 && second_to_last.is_set(ArgSettings::Multiple) 597 && count == 2); 598 assert!( 599 ok, 600 "Only one positional argument with .multiple(true) set is allowed per \ 601 command, unless the second one also has .last(true) set" 602 ); 603 } 604 605 if self.is_set(AS::AllowMissingPositional) { 606 // Check that if a required positional argument is found, all positions with a lower 607 // index are also required. 608 let mut found = false; 609 let mut foundx2 = false; 610 for p in self.positionals.values().rev() { 611 if foundx2 && !p.b.settings.is_set(ArgSettings::Required) { 612 assert!( 613 p.b.is_set(ArgSettings::Required), 614 "Found positional argument which is not required with a lower \ 615 index than a required positional argument by two or more: {:?} \ 616 index {}", 617 p.b.name, 618 p.index 619 ); 620 } else if p.b.is_set(ArgSettings::Required) && !p.b.is_set(ArgSettings::Last) { 621 // Args that .last(true) don't count since they can be required and have 622 // positionals with a lower index that aren't required 623 // Imagine: prog <req1> [opt1] -- <req2> 624 // Both of these are valid invocations: 625 // $ prog r1 -- r2 626 // $ prog r1 o1 -- r2 627 if found { 628 foundx2 = true; 629 continue; 630 } 631 found = true; 632 continue; 633 } else { 634 found = false; 635 } 636 } 637 } else { 638 // Check that if a required positional argument is found, all positions with a lower 639 // index are also required 640 let mut found = false; 641 for p in self.positionals.values().rev() { 642 if found { 643 assert!( 644 p.b.is_set(ArgSettings::Required), 645 "Found positional argument which is not required with a lower \ 646 index than a required positional argument: {:?} index {}", 647 p.b.name, 648 p.index 649 ); 650 } else if p.b.is_set(ArgSettings::Required) && !p.b.is_set(ArgSettings::Last) { 651 // Args that .last(true) don't count since they can be required and have 652 // positionals with a lower index that aren't required 653 // Imagine: prog <req1> [opt1] -- <req2> 654 // Both of these are valid invocations: 655 // $ prog r1 -- r2 656 // $ prog r1 o1 -- r2 657 found = true; 658 continue; 659 } 660 } 661 } 662 if self 663 .positionals 664 .values() 665 .any(|p| p.b.is_set(ArgSettings::Last) && p.b.is_set(ArgSettings::Required)) 666 && self.has_subcommands() 667 && !self.is_set(AS::SubcommandsNegateReqs) 668 { 669 panic!( 670 "Having a required positional argument with .last(true) set *and* child \ 671 subcommands without setting SubcommandsNegateReqs isn't compatible." 672 ); 673 } 674 675 true 676 } 677 propagate_globals(&mut self)678 pub fn propagate_globals(&mut self) { 679 for sc in &mut self.subcommands { 680 // We have to create a new scope in order to tell rustc the borrow of `sc` is 681 // done and to recursively call this method 682 { 683 for a in &self.global_args { 684 sc.p.add_arg_ref(a); 685 } 686 } 687 sc.p.propagate_globals(); 688 } 689 } 690 691 // Checks if the arg matches a subcommand name, or any of it's aliases (if defined) possible_subcommand(&self, arg_os: &OsStr) -> (bool, Option<&str>)692 fn possible_subcommand(&self, arg_os: &OsStr) -> (bool, Option<&str>) { 693 #[cfg(any(target_os = "windows", target_arch = "wasm32"))] 694 use osstringext::OsStrExt3; 695 #[cfg(not(any(target_os = "windows", target_arch = "wasm32")))] 696 use std::os::unix::ffi::OsStrExt; 697 debugln!("Parser::possible_subcommand: arg={:?}", arg_os); 698 fn starts(h: &str, n: &OsStr) -> bool { 699 let n_bytes = n.as_bytes(); 700 let h_bytes = OsStr::new(h).as_bytes(); 701 702 h_bytes.starts_with(n_bytes) 703 } 704 705 if self.is_set(AS::ArgsNegateSubcommands) && self.is_set(AS::ValidArgFound) { 706 return (false, None); 707 } 708 if !self.is_set(AS::InferSubcommands) { 709 if let Some(sc) = find_subcmd!(self, arg_os) { 710 return (true, Some(&sc.p.meta.name)); 711 } 712 } else { 713 let v = self 714 .subcommands 715 .iter() 716 .filter(|s| { 717 starts(&s.p.meta.name[..], &*arg_os) 718 || (s.p.meta.aliases.is_some() 719 && s.p 720 .meta 721 .aliases 722 .as_ref() 723 .unwrap() 724 .iter() 725 .filter(|&&(a, _)| starts(a, &*arg_os)) 726 .count() 727 == 1) 728 }) 729 .map(|sc| &sc.p.meta.name) 730 .collect::<Vec<_>>(); 731 732 for sc in &v { 733 if OsStr::new(sc) == arg_os { 734 return (true, Some(sc)); 735 } 736 } 737 738 if v.len() == 1 { 739 return (true, Some(v[0])); 740 } 741 } 742 (false, None) 743 } 744 parse_help_subcommand<I, T>(&self, it: &mut I) -> ClapResult<ParseResult<'a>> where I: Iterator<Item = T>, T: Into<OsString>,745 fn parse_help_subcommand<I, T>(&self, it: &mut I) -> ClapResult<ParseResult<'a>> 746 where 747 I: Iterator<Item = T>, 748 T: Into<OsString>, 749 { 750 debugln!("Parser::parse_help_subcommand;"); 751 let cmds: Vec<OsString> = it.map(|c| c.into()).collect(); 752 let mut help_help = false; 753 let mut bin_name = self 754 .meta 755 .bin_name 756 .as_ref() 757 .unwrap_or(&self.meta.name) 758 .clone(); 759 let mut sc = { 760 let mut sc: &Parser = self; 761 for (i, cmd) in cmds.iter().enumerate() { 762 if &*cmd.to_string_lossy() == "help" { 763 // cmd help help 764 help_help = true; 765 } 766 if let Some(c) = sc 767 .subcommands 768 .iter() 769 .find(|s| &*s.p.meta.name == cmd) 770 .map(|sc| &sc.p) 771 { 772 sc = c; 773 if i == cmds.len() - 1 { 774 break; 775 } 776 } else if let Some(c) = sc 777 .subcommands 778 .iter() 779 .find(|s| { 780 if let Some(ref als) = s.p.meta.aliases { 781 als.iter().any(|&(a, _)| a == &*cmd.to_string_lossy()) 782 } else { 783 false 784 } 785 }) 786 .map(|sc| &sc.p) 787 { 788 sc = c; 789 if i == cmds.len() - 1 { 790 break; 791 } 792 } else { 793 return Err(Error::unrecognized_subcommand( 794 cmd.to_string_lossy().into_owned(), 795 self.meta.bin_name.as_ref().unwrap_or(&self.meta.name), 796 self.color(), 797 )); 798 } 799 bin_name = format!("{} {}", bin_name, &*sc.meta.name); 800 } 801 sc.clone() 802 }; 803 if help_help { 804 let mut pb = PosBuilder::new("subcommand", 1); 805 pb.b.help = Some("The subcommand whose help message to display"); 806 pb.set(ArgSettings::Multiple); 807 sc.positionals.insert(1, pb); 808 sc.settings = sc.settings | self.g_settings; 809 } else { 810 sc.create_help_and_version(); 811 } 812 if sc.meta.bin_name != self.meta.bin_name { 813 sc.meta.bin_name = Some(format!("{} {}", bin_name, sc.meta.name)); 814 } 815 Err(sc._help(false)) 816 } 817 818 // allow wrong self convention due to self.valid_neg_num = true and it's a private method 819 #[cfg_attr(feature = "lints", allow(wrong_self_convention))] is_new_arg(&mut self, arg_os: &OsStr, needs_val_of: ParseResult) -> bool820 fn is_new_arg(&mut self, arg_os: &OsStr, needs_val_of: ParseResult) -> bool { 821 debugln!("Parser::is_new_arg:{:?}:{:?}", arg_os, needs_val_of); 822 let app_wide_settings = if self.is_set(AS::AllowLeadingHyphen) { 823 true 824 } else if self.is_set(AS::AllowNegativeNumbers) { 825 let a = arg_os.to_string_lossy(); 826 if a.parse::<i64>().is_ok() || a.parse::<f64>().is_ok() { 827 self.set(AS::ValidNegNumFound); 828 true 829 } else { 830 false 831 } 832 } else { 833 false 834 }; 835 let arg_allows_tac = match needs_val_of { 836 ParseResult::Opt(name) => { 837 let o = self 838 .opts 839 .iter() 840 .find(|o| o.b.name == name) 841 .expect(INTERNAL_ERROR_MSG); 842 (o.is_set(ArgSettings::AllowLeadingHyphen) || app_wide_settings) 843 } 844 ParseResult::Pos(name) => { 845 let p = self 846 .positionals 847 .values() 848 .find(|p| p.b.name == name) 849 .expect(INTERNAL_ERROR_MSG); 850 (p.is_set(ArgSettings::AllowLeadingHyphen) || app_wide_settings) 851 } 852 ParseResult::ValuesDone => return true, 853 _ => false, 854 }; 855 debugln!("Parser::is_new_arg: arg_allows_tac={:?}", arg_allows_tac); 856 857 // Is this a new argument, or values from a previous option? 858 let mut ret = if arg_os.starts_with(b"--") { 859 debugln!("Parser::is_new_arg: -- found"); 860 if arg_os.len() == 2 && !arg_allows_tac { 861 return true; // We have to return true so override everything else 862 } else if arg_allows_tac { 863 return false; 864 } 865 true 866 } else if arg_os.starts_with(b"-") { 867 debugln!("Parser::is_new_arg: - found"); 868 // a singe '-' by itself is a value and typically means "stdin" on unix systems 869 !(arg_os.len() == 1) 870 } else { 871 debugln!("Parser::is_new_arg: probably value"); 872 false 873 }; 874 875 ret = ret && !arg_allows_tac; 876 877 debugln!("Parser::is_new_arg: starts_new_arg={:?}", ret); 878 ret 879 } 880 881 // The actual parsing function 882 #[cfg_attr(feature = "lints", allow(while_let_on_iterator, collapsible_if))] get_matches_with<I, T>( &mut self, matcher: &mut ArgMatcher<'a>, it: &mut Peekable<I>, ) -> ClapResult<()> where I: Iterator<Item = T>, T: Into<OsString> + Clone,883 pub fn get_matches_with<I, T>( 884 &mut self, 885 matcher: &mut ArgMatcher<'a>, 886 it: &mut Peekable<I>, 887 ) -> ClapResult<()> 888 where 889 I: Iterator<Item = T>, 890 T: Into<OsString> + Clone, 891 { 892 debugln!("Parser::get_matches_with;"); 893 // Verify all positional assertions pass 894 debug_assert!(self.app_debug_asserts()); 895 if self.positionals.values().any(|a| { 896 a.b.is_set(ArgSettings::Multiple) && (a.index as usize != self.positionals.len()) 897 }) && self 898 .positionals 899 .values() 900 .last() 901 .map_or(false, |p| !p.is_set(ArgSettings::Last)) 902 { 903 self.settings.set(AS::LowIndexMultiplePositional); 904 } 905 let has_args = self.has_args(); 906 907 // Next we create the `--help` and `--version` arguments and add them if 908 // necessary 909 self.create_help_and_version(); 910 911 let mut subcmd_name: Option<String> = None; 912 let mut needs_val_of: ParseResult<'a> = ParseResult::NotFound; 913 let mut pos_counter = 1; 914 let mut sc_is_external = false; 915 while let Some(arg) = it.next() { 916 let arg_os = arg.into(); 917 debugln!( 918 "Parser::get_matches_with: Begin parsing '{:?}' ({:?})", 919 arg_os, 920 &*arg_os.as_bytes() 921 ); 922 923 self.unset(AS::ValidNegNumFound); 924 // Is this a new argument, or values from a previous option? 925 let starts_new_arg = self.is_new_arg(&arg_os, needs_val_of); 926 if !self.is_set(AS::TrailingValues) 927 && arg_os.starts_with(b"--") 928 && arg_os.len() == 2 929 && starts_new_arg 930 { 931 debugln!("Parser::get_matches_with: setting TrailingVals=true"); 932 self.set(AS::TrailingValues); 933 continue; 934 } 935 936 // Has the user already passed '--'? Meaning only positional args follow 937 if !self.is_set(AS::TrailingValues) { 938 // Does the arg match a subcommand name, or any of it's aliases (if defined) 939 { 940 match needs_val_of { 941 ParseResult::Opt(_) | ParseResult::Pos(_) => (), 942 _ => { 943 let (is_match, sc_name) = self.possible_subcommand(&arg_os); 944 debugln!( 945 "Parser::get_matches_with: possible_sc={:?}, sc={:?}", 946 is_match, 947 sc_name 948 ); 949 if is_match { 950 let sc_name = sc_name.expect(INTERNAL_ERROR_MSG); 951 if sc_name == "help" && self.is_set(AS::NeedsSubcommandHelp) { 952 self.parse_help_subcommand(it)?; 953 } 954 subcmd_name = Some(sc_name.to_owned()); 955 break; 956 } 957 } 958 } 959 } 960 961 if starts_new_arg { 962 let check_all = self.is_set(AS::AllArgsOverrideSelf); 963 { 964 let any_arg = find_any_by_name!(self, self.cache.unwrap_or("")); 965 matcher.process_arg_overrides( 966 any_arg, 967 &mut self.overrides, 968 &mut self.required, 969 check_all, 970 ); 971 } 972 973 if arg_os.starts_with(b"--") { 974 needs_val_of = self.parse_long_arg(matcher, &arg_os, it)?; 975 debugln!( 976 "Parser:get_matches_with: After parse_long_arg {:?}", 977 needs_val_of 978 ); 979 match needs_val_of { 980 ParseResult::Flag | ParseResult::Opt(..) | ParseResult::ValuesDone => { 981 continue 982 } 983 _ => (), 984 } 985 } else if arg_os.starts_with(b"-") && arg_os.len() != 1 { 986 // Try to parse short args like normal, if AllowLeadingHyphen or 987 // AllowNegativeNumbers is set, parse_short_arg will *not* throw 988 // an error, and instead return Ok(None) 989 needs_val_of = self.parse_short_arg(matcher, &arg_os)?; 990 // If it's None, we then check if one of those two AppSettings was set 991 debugln!( 992 "Parser:get_matches_with: After parse_short_arg {:?}", 993 needs_val_of 994 ); 995 match needs_val_of { 996 ParseResult::MaybeNegNum => { 997 if !(arg_os.to_string_lossy().parse::<i64>().is_ok() 998 || arg_os.to_string_lossy().parse::<f64>().is_ok()) 999 { 1000 return Err(Error::unknown_argument( 1001 &*arg_os.to_string_lossy(), 1002 "", 1003 &*usage::create_error_usage(self, matcher, None), 1004 self.color(), 1005 )); 1006 } 1007 } 1008 ParseResult::Opt(..) | ParseResult::Flag | ParseResult::ValuesDone => { 1009 continue 1010 } 1011 _ => (), 1012 } 1013 } 1014 } else { 1015 if let ParseResult::Opt(name) = needs_val_of { 1016 // Check to see if parsing a value from a previous arg 1017 let arg = self 1018 .opts 1019 .iter() 1020 .find(|o| o.b.name == name) 1021 .expect(INTERNAL_ERROR_MSG); 1022 // get the OptBuilder so we can check the settings 1023 needs_val_of = self.add_val_to_arg(arg, &arg_os, matcher)?; 1024 // get the next value from the iterator 1025 continue; 1026 } 1027 } 1028 } 1029 1030 if !(self.is_set(AS::ArgsNegateSubcommands) && self.is_set(AS::ValidArgFound)) 1031 && !self.is_set(AS::InferSubcommands) 1032 && !self.is_set(AS::AllowExternalSubcommands) 1033 { 1034 if let Some(cdate) = 1035 suggestions::did_you_mean(&*arg_os.to_string_lossy(), sc_names!(self)) 1036 { 1037 return Err(Error::invalid_subcommand( 1038 arg_os.to_string_lossy().into_owned(), 1039 cdate, 1040 self.meta.bin_name.as_ref().unwrap_or(&self.meta.name), 1041 &*usage::create_error_usage(self, matcher, None), 1042 self.color(), 1043 )); 1044 } 1045 } 1046 1047 let low_index_mults = self.is_set(AS::LowIndexMultiplePositional) 1048 && pos_counter == (self.positionals.len() - 1); 1049 let missing_pos = self.is_set(AS::AllowMissingPositional) 1050 && (pos_counter == (self.positionals.len() - 1) 1051 && !self.is_set(AS::TrailingValues)); 1052 debugln!( 1053 "Parser::get_matches_with: Positional counter...{}", 1054 pos_counter 1055 ); 1056 debugln!( 1057 "Parser::get_matches_with: Low index multiples...{:?}", 1058 low_index_mults 1059 ); 1060 if low_index_mults || missing_pos { 1061 if let Some(na) = it.peek() { 1062 let n = (*na).clone().into(); 1063 needs_val_of = if needs_val_of != ParseResult::ValuesDone { 1064 if let Some(p) = self.positionals.get(pos_counter) { 1065 ParseResult::Pos(p.b.name) 1066 } else { 1067 ParseResult::ValuesDone 1068 } 1069 } else { 1070 ParseResult::ValuesDone 1071 }; 1072 let sc_match = { self.possible_subcommand(&n).0 }; 1073 if self.is_new_arg(&n, needs_val_of) 1074 || sc_match 1075 || suggestions::did_you_mean(&n.to_string_lossy(), sc_names!(self)) 1076 .is_some() 1077 { 1078 debugln!("Parser::get_matches_with: Bumping the positional counter..."); 1079 pos_counter += 1; 1080 } 1081 } else { 1082 debugln!("Parser::get_matches_with: Bumping the positional counter..."); 1083 pos_counter += 1; 1084 } 1085 } else if (self.is_set(AS::AllowMissingPositional) && self.is_set(AS::TrailingValues)) 1086 || (self.is_set(AS::ContainsLast) && self.is_set(AS::TrailingValues)) 1087 { 1088 // Came to -- and one postional has .last(true) set, so we go immediately 1089 // to the last (highest index) positional 1090 debugln!("Parser::get_matches_with: .last(true) and --, setting last pos"); 1091 pos_counter = self.positionals.len(); 1092 } 1093 if let Some(p) = self.positionals.get(pos_counter) { 1094 if p.is_set(ArgSettings::Last) && !self.is_set(AS::TrailingValues) { 1095 return Err(Error::unknown_argument( 1096 &*arg_os.to_string_lossy(), 1097 "", 1098 &*usage::create_error_usage(self, matcher, None), 1099 self.color(), 1100 )); 1101 } 1102 if !self.is_set(AS::TrailingValues) 1103 && (self.is_set(AS::TrailingVarArg) && pos_counter == self.positionals.len()) 1104 { 1105 self.settings.set(AS::TrailingValues); 1106 } 1107 if self.cache.map_or(true, |name| name != p.b.name) { 1108 let check_all = self.is_set(AS::AllArgsOverrideSelf); 1109 { 1110 let any_arg = find_any_by_name!(self, self.cache.unwrap_or("")); 1111 matcher.process_arg_overrides( 1112 any_arg, 1113 &mut self.overrides, 1114 &mut self.required, 1115 check_all, 1116 ); 1117 } 1118 self.cache = Some(p.b.name); 1119 } 1120 let _ = self.add_val_to_arg(p, &arg_os, matcher)?; 1121 1122 matcher.inc_occurrence_of(p.b.name); 1123 let _ = self 1124 .groups_for_arg(p.b.name) 1125 .and_then(|vec| Some(matcher.inc_occurrences_of(&*vec))); 1126 1127 self.settings.set(AS::ValidArgFound); 1128 // Only increment the positional counter if it doesn't allow multiples 1129 if !p.b.settings.is_set(ArgSettings::Multiple) { 1130 pos_counter += 1; 1131 } 1132 self.settings.set(AS::ValidArgFound); 1133 } else if self.is_set(AS::AllowExternalSubcommands) { 1134 // Get external subcommand name 1135 let sc_name = match arg_os.to_str() { 1136 Some(s) => s.to_string(), 1137 None => { 1138 if !self.is_set(AS::StrictUtf8) { 1139 return Err(Error::invalid_utf8( 1140 &*usage::create_error_usage(self, matcher, None), 1141 self.color(), 1142 )); 1143 } 1144 arg_os.to_string_lossy().into_owned() 1145 } 1146 }; 1147 1148 // Collect the external subcommand args 1149 let mut sc_m = ArgMatcher::new(); 1150 while let Some(v) = it.next() { 1151 let a = v.into(); 1152 if a.to_str().is_none() && !self.is_set(AS::StrictUtf8) { 1153 return Err(Error::invalid_utf8( 1154 &*usage::create_error_usage(self, matcher, None), 1155 self.color(), 1156 )); 1157 } 1158 sc_m.add_val_to("", &a); 1159 } 1160 1161 matcher.subcommand(SubCommand { 1162 name: sc_name, 1163 matches: sc_m.into(), 1164 }); 1165 sc_is_external = true; 1166 } else if !((self.is_set(AS::AllowLeadingHyphen) 1167 || self.is_set(AS::AllowNegativeNumbers)) 1168 && arg_os.starts_with(b"-")) 1169 && !self.is_set(AS::InferSubcommands) 1170 { 1171 return Err(Error::unknown_argument( 1172 &*arg_os.to_string_lossy(), 1173 "", 1174 &*usage::create_error_usage(self, matcher, None), 1175 self.color(), 1176 )); 1177 } else if !has_args || self.is_set(AS::InferSubcommands) && self.has_subcommands() { 1178 if let Some(cdate) = 1179 suggestions::did_you_mean(&*arg_os.to_string_lossy(), sc_names!(self)) 1180 { 1181 return Err(Error::invalid_subcommand( 1182 arg_os.to_string_lossy().into_owned(), 1183 cdate, 1184 self.meta.bin_name.as_ref().unwrap_or(&self.meta.name), 1185 &*usage::create_error_usage(self, matcher, None), 1186 self.color(), 1187 )); 1188 } else { 1189 return Err(Error::unrecognized_subcommand( 1190 arg_os.to_string_lossy().into_owned(), 1191 self.meta.bin_name.as_ref().unwrap_or(&self.meta.name), 1192 self.color(), 1193 )); 1194 } 1195 } else { 1196 return Err(Error::unknown_argument( 1197 &*arg_os.to_string_lossy(), 1198 "", 1199 &*usage::create_error_usage(self, matcher, None), 1200 self.color(), 1201 )); 1202 } 1203 } 1204 1205 if !sc_is_external { 1206 if let Some(ref pos_sc_name) = subcmd_name { 1207 let sc_name = { 1208 find_subcmd!(self, pos_sc_name) 1209 .expect(INTERNAL_ERROR_MSG) 1210 .p 1211 .meta 1212 .name 1213 .clone() 1214 }; 1215 self.parse_subcommand(&*sc_name, matcher, it)?; 1216 } else if self.is_set(AS::SubcommandRequired) { 1217 let bn = self.meta.bin_name.as_ref().unwrap_or(&self.meta.name); 1218 return Err(Error::missing_subcommand( 1219 bn, 1220 &usage::create_error_usage(self, matcher, None), 1221 self.color(), 1222 )); 1223 } else if self.is_set(AS::SubcommandRequiredElseHelp) { 1224 debugln!("Parser::get_matches_with: SubcommandRequiredElseHelp=true"); 1225 let mut out = vec![]; 1226 self.write_help_err(&mut out)?; 1227 return Err(Error { 1228 message: String::from_utf8_lossy(&*out).into_owned(), 1229 kind: ErrorKind::MissingArgumentOrSubcommand, 1230 info: None, 1231 }); 1232 } 1233 } 1234 1235 // In case the last arg was new, we need to process it's overrides 1236 let check_all = self.is_set(AS::AllArgsOverrideSelf); 1237 { 1238 let any_arg = find_any_by_name!(self, self.cache.unwrap_or("")); 1239 matcher.process_arg_overrides( 1240 any_arg, 1241 &mut self.overrides, 1242 &mut self.required, 1243 check_all, 1244 ); 1245 } 1246 1247 self.remove_overrides(matcher); 1248 1249 Validator::new(self).validate(needs_val_of, subcmd_name, matcher) 1250 } 1251 remove_overrides(&mut self, matcher: &mut ArgMatcher)1252 fn remove_overrides(&mut self, matcher: &mut ArgMatcher) { 1253 debugln!("Parser::remove_overrides:{:?};", self.overrides); 1254 for &(overr, name) in &self.overrides { 1255 debugln!("Parser::remove_overrides:iter:({},{});", overr, name); 1256 if matcher.is_present(overr) { 1257 debugln!( 1258 "Parser::remove_overrides:iter:({},{}): removing {};", 1259 overr, 1260 name, 1261 name 1262 ); 1263 matcher.remove(name); 1264 for i in (0..self.required.len()).rev() { 1265 debugln!( 1266 "Parser::remove_overrides:iter:({},{}): removing required {};", 1267 overr, 1268 name, 1269 name 1270 ); 1271 if self.required[i] == name { 1272 self.required.swap_remove(i); 1273 break; 1274 } 1275 } 1276 } 1277 } 1278 } 1279 propagate_help_version(&mut self)1280 fn propagate_help_version(&mut self) { 1281 debugln!("Parser::propagate_help_version;"); 1282 self.create_help_and_version(); 1283 for sc in &mut self.subcommands { 1284 sc.p.propagate_help_version(); 1285 } 1286 } 1287 build_bin_names(&mut self)1288 fn build_bin_names(&mut self) { 1289 debugln!("Parser::build_bin_names;"); 1290 for sc in &mut self.subcommands { 1291 debug!("Parser::build_bin_names:iter: bin_name set..."); 1292 if sc.p.meta.bin_name.is_none() { 1293 sdebugln!("No"); 1294 let bin_name = format!( 1295 "{}{}{}", 1296 self.meta 1297 .bin_name 1298 .as_ref() 1299 .unwrap_or(&self.meta.name.clone()), 1300 if self.meta.bin_name.is_some() { 1301 " " 1302 } else { 1303 "" 1304 }, 1305 &*sc.p.meta.name 1306 ); 1307 debugln!( 1308 "Parser::build_bin_names:iter: Setting bin_name of {} to {}", 1309 self.meta.name, 1310 bin_name 1311 ); 1312 sc.p.meta.bin_name = Some(bin_name); 1313 } else { 1314 sdebugln!("yes ({:?})", sc.p.meta.bin_name); 1315 } 1316 debugln!( 1317 "Parser::build_bin_names:iter: Calling build_bin_names from...{}", 1318 sc.p.meta.name 1319 ); 1320 sc.p.build_bin_names(); 1321 } 1322 } 1323 parse_subcommand<I, T>( &mut self, sc_name: &str, matcher: &mut ArgMatcher<'a>, it: &mut Peekable<I>, ) -> ClapResult<()> where I: Iterator<Item = T>, T: Into<OsString> + Clone,1324 fn parse_subcommand<I, T>( 1325 &mut self, 1326 sc_name: &str, 1327 matcher: &mut ArgMatcher<'a>, 1328 it: &mut Peekable<I>, 1329 ) -> ClapResult<()> 1330 where 1331 I: Iterator<Item = T>, 1332 T: Into<OsString> + Clone, 1333 { 1334 use std::fmt::Write; 1335 debugln!("Parser::parse_subcommand;"); 1336 let mut mid_string = String::new(); 1337 if !self.is_set(AS::SubcommandsNegateReqs) { 1338 let mut hs: Vec<&str> = self.required.iter().map(|n| &**n).collect(); 1339 for k in matcher.arg_names() { 1340 hs.push(k); 1341 } 1342 let reqs = usage::get_required_usage_from(self, &hs, Some(matcher), None, false); 1343 1344 for s in &reqs { 1345 write!(&mut mid_string, " {}", s).expect(INTERNAL_ERROR_MSG); 1346 } 1347 } 1348 mid_string.push_str(" "); 1349 if let Some(ref mut sc) = self 1350 .subcommands 1351 .iter_mut() 1352 .find(|s| s.p.meta.name == sc_name) 1353 { 1354 let mut sc_matcher = ArgMatcher::new(); 1355 // bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by 1356 // a space 1357 sc.p.meta.usage = Some(format!( 1358 "{}{}{}", 1359 self.meta.bin_name.as_ref().unwrap_or(&String::new()), 1360 if self.meta.bin_name.is_some() { 1361 &*mid_string 1362 } else { 1363 "" 1364 }, 1365 &*sc.p.meta.name 1366 )); 1367 sc.p.meta.bin_name = Some(format!( 1368 "{}{}{}", 1369 self.meta.bin_name.as_ref().unwrap_or(&String::new()), 1370 if self.meta.bin_name.is_some() { 1371 " " 1372 } else { 1373 "" 1374 }, 1375 &*sc.p.meta.name 1376 )); 1377 debugln!( 1378 "Parser::parse_subcommand: About to parse sc={}", 1379 sc.p.meta.name 1380 ); 1381 debugln!("Parser::parse_subcommand: sc settings={:#?}", sc.p.settings); 1382 sc.p.get_matches_with(&mut sc_matcher, it)?; 1383 matcher.subcommand(SubCommand { 1384 name: sc.p.meta.name.clone(), 1385 matches: sc_matcher.into(), 1386 }); 1387 } 1388 Ok(()) 1389 } 1390 groups_for_arg(&self, name: &str) -> Option<Vec<&'a str>>1391 pub fn groups_for_arg(&self, name: &str) -> Option<Vec<&'a str>> { 1392 debugln!("Parser::groups_for_arg: name={}", name); 1393 1394 if self.groups.is_empty() { 1395 debugln!("Parser::groups_for_arg: No groups defined"); 1396 return None; 1397 } 1398 let mut res = vec![]; 1399 debugln!("Parser::groups_for_arg: Searching through groups..."); 1400 for grp in &self.groups { 1401 for a in &grp.args { 1402 if a == &name { 1403 sdebugln!("\tFound '{}'", grp.name); 1404 res.push(&*grp.name); 1405 } 1406 } 1407 } 1408 if res.is_empty() { 1409 return None; 1410 } 1411 1412 Some(res) 1413 } 1414 args_in_group(&self, group: &str) -> Vec<String>1415 pub fn args_in_group(&self, group: &str) -> Vec<String> { 1416 debug_assert!(self.app_debug_asserts()); 1417 1418 let mut g_vec = vec![]; 1419 let mut args = vec![]; 1420 1421 for n in &self 1422 .groups 1423 .iter() 1424 .find(|g| g.name == group) 1425 .expect(INTERNAL_ERROR_MSG) 1426 .args 1427 { 1428 if let Some(f) = self.flags.iter().find(|f| &f.b.name == n) { 1429 args.push(f.to_string()); 1430 } else if let Some(f) = self.opts.iter().find(|o| &o.b.name == n) { 1431 args.push(f.to_string()); 1432 } else if let Some(p) = self.positionals.values().find(|p| &p.b.name == n) { 1433 args.push(p.b.name.to_owned()); 1434 } else { 1435 g_vec.push(*n); 1436 } 1437 } 1438 1439 for av in g_vec.iter().map(|g| self.args_in_group(g)) { 1440 args.extend(av); 1441 } 1442 args.dedup(); 1443 args.iter().map(ToOwned::to_owned).collect() 1444 } 1445 arg_names_in_group(&self, group: &str) -> Vec<&'a str>1446 pub fn arg_names_in_group(&self, group: &str) -> Vec<&'a str> { 1447 let mut g_vec = vec![]; 1448 let mut args = vec![]; 1449 1450 for n in &self 1451 .groups 1452 .iter() 1453 .find(|g| g.name == group) 1454 .expect(INTERNAL_ERROR_MSG) 1455 .args 1456 { 1457 if self.groups.iter().any(|g| g.name == *n) { 1458 args.extend(self.arg_names_in_group(n)); 1459 g_vec.push(*n); 1460 } else if !args.contains(n) { 1461 args.push(*n); 1462 } 1463 } 1464 1465 args.iter().map(|s| *s).collect() 1466 } 1467 create_help_and_version(&mut self)1468 pub fn create_help_and_version(&mut self) { 1469 debugln!("Parser::create_help_and_version;"); 1470 // name is "hclap_help" because flags are sorted by name 1471 if !self.is_set(AS::DisableHelpFlags) && !self.contains_long("help") { 1472 debugln!("Parser::create_help_and_version: Building --help"); 1473 if self.help_short.is_none() && !self.contains_short('h') { 1474 self.help_short = Some('h'); 1475 } 1476 let arg = FlagBuilder { 1477 b: Base { 1478 name: "hclap_help", 1479 help: self.help_message.or(Some("Prints help information")), 1480 ..Default::default() 1481 }, 1482 s: Switched { 1483 short: self.help_short, 1484 long: Some("help"), 1485 ..Default::default() 1486 }, 1487 }; 1488 self.flags.push(arg); 1489 } 1490 if !self.is_set(AS::DisableVersion) && !self.contains_long("version") { 1491 debugln!("Parser::create_help_and_version: Building --version"); 1492 if self.version_short.is_none() && !self.contains_short('V') { 1493 self.version_short = Some('V'); 1494 } 1495 // name is "vclap_version" because flags are sorted by name 1496 let arg = FlagBuilder { 1497 b: Base { 1498 name: "vclap_version", 1499 help: self.version_message.or(Some("Prints version information")), 1500 ..Default::default() 1501 }, 1502 s: Switched { 1503 short: self.version_short, 1504 long: Some("version"), 1505 ..Default::default() 1506 }, 1507 }; 1508 self.flags.push(arg); 1509 } 1510 if !self.subcommands.is_empty() 1511 && !self.is_set(AS::DisableHelpSubcommand) 1512 && self.is_set(AS::NeedsSubcommandHelp) 1513 { 1514 debugln!("Parser::create_help_and_version: Building help"); 1515 self.subcommands.push( 1516 App::new("help") 1517 .about("Prints this message or the help of the given subcommand(s)"), 1518 ); 1519 } 1520 } 1521 1522 // Retrieves the names of all args the user has supplied thus far, except required ones 1523 // because those will be listed in self.required check_for_help_and_version_str(&self, arg: &OsStr) -> ClapResult<()>1524 fn check_for_help_and_version_str(&self, arg: &OsStr) -> ClapResult<()> { 1525 debugln!("Parser::check_for_help_and_version_str;"); 1526 debug!( 1527 "Parser::check_for_help_and_version_str: Checking if --{} is help or version...", 1528 arg.to_str().unwrap() 1529 ); 1530 if arg == "help" && self.is_set(AS::NeedsLongHelp) { 1531 sdebugln!("Help"); 1532 return Err(self._help(true)); 1533 } 1534 if arg == "version" && self.is_set(AS::NeedsLongVersion) { 1535 sdebugln!("Version"); 1536 return Err(self._version(true)); 1537 } 1538 sdebugln!("Neither"); 1539 1540 Ok(()) 1541 } 1542 check_for_help_and_version_char(&self, arg: char) -> ClapResult<()>1543 fn check_for_help_and_version_char(&self, arg: char) -> ClapResult<()> { 1544 debugln!("Parser::check_for_help_and_version_char;"); 1545 debug!( 1546 "Parser::check_for_help_and_version_char: Checking if -{} is help or version...", 1547 arg 1548 ); 1549 if let Some(h) = self.help_short { 1550 if arg == h && self.is_set(AS::NeedsLongHelp) { 1551 sdebugln!("Help"); 1552 return Err(self._help(false)); 1553 } 1554 } 1555 if let Some(v) = self.version_short { 1556 if arg == v && self.is_set(AS::NeedsLongVersion) { 1557 sdebugln!("Version"); 1558 return Err(self._version(false)); 1559 } 1560 } 1561 sdebugln!("Neither"); 1562 Ok(()) 1563 } 1564 use_long_help(&self) -> bool1565 fn use_long_help(&self) -> bool { 1566 // In this case, both must be checked. This allows the retention of 1567 // original formatting, but also ensures that the actual -h or --help 1568 // specified by the user is sent through. If HiddenShortHelp is not included, 1569 // then items specified with hidden_short_help will also be hidden. 1570 let should_long = |v: &Base| { 1571 v.long_help.is_some() 1572 || v.is_set(ArgSettings::HiddenLongHelp) 1573 || v.is_set(ArgSettings::HiddenShortHelp) 1574 }; 1575 1576 self.meta.long_about.is_some() 1577 || self.flags.iter().any(|f| should_long(&f.b)) 1578 || self.opts.iter().any(|o| should_long(&o.b)) 1579 || self.positionals.values().any(|p| should_long(&p.b)) 1580 || self 1581 .subcommands 1582 .iter() 1583 .any(|s| s.p.meta.long_about.is_some()) 1584 } 1585 _help(&self, mut use_long: bool) -> Error1586 fn _help(&self, mut use_long: bool) -> Error { 1587 debugln!("Parser::_help: use_long={:?}", use_long); 1588 use_long = use_long && self.use_long_help(); 1589 let mut buf = vec![]; 1590 match Help::write_parser_help(&mut buf, self, use_long) { 1591 Err(e) => e, 1592 _ => Error { 1593 message: String::from_utf8(buf).unwrap_or_default(), 1594 kind: ErrorKind::HelpDisplayed, 1595 info: None, 1596 }, 1597 } 1598 } 1599 _version(&self, use_long: bool) -> Error1600 fn _version(&self, use_long: bool) -> Error { 1601 debugln!("Parser::_version: "); 1602 let out = io::stdout(); 1603 let mut buf_w = BufWriter::new(out.lock()); 1604 match self.print_version(&mut buf_w, use_long) { 1605 Err(e) => e, 1606 _ => Error { 1607 message: String::new(), 1608 kind: ErrorKind::VersionDisplayed, 1609 info: None, 1610 }, 1611 } 1612 } 1613 parse_long_arg<I, T>( &mut self, matcher: &mut ArgMatcher<'a>, full_arg: &OsStr, it: &mut Peekable<I>, ) -> ClapResult<ParseResult<'a>> where I: Iterator<Item = T>, T: Into<OsString> + Clone,1614 fn parse_long_arg<I, T>( 1615 &mut self, 1616 matcher: &mut ArgMatcher<'a>, 1617 full_arg: &OsStr, 1618 it: &mut Peekable<I>, 1619 ) -> ClapResult<ParseResult<'a>> 1620 where 1621 I: Iterator<Item = T>, 1622 T: Into<OsString> + Clone, 1623 { 1624 // maybe here lifetime should be 'a 1625 debugln!("Parser::parse_long_arg;"); 1626 1627 // Update the current index 1628 self.cur_idx.set(self.cur_idx.get() + 1); 1629 1630 let mut val = None; 1631 debug!("Parser::parse_long_arg: Does it contain '='..."); 1632 let arg = if full_arg.contains_byte(b'=') { 1633 let (p0, p1) = full_arg.trim_left_matches(b'-').split_at_byte(b'='); 1634 sdebugln!("Yes '{:?}'", p1); 1635 val = Some(p1); 1636 p0 1637 } else { 1638 sdebugln!("No"); 1639 full_arg.trim_left_matches(b'-') 1640 }; 1641 1642 if let Some(opt) = find_opt_by_long!(@os self, arg) { 1643 debugln!( 1644 "Parser::parse_long_arg: Found valid opt '{}'", 1645 opt.to_string() 1646 ); 1647 self.settings.set(AS::ValidArgFound); 1648 let ret = self.parse_opt(val, opt, val.is_some(), matcher)?; 1649 if self.cache.map_or(true, |name| name != opt.b.name) { 1650 self.cache = Some(opt.b.name); 1651 } 1652 1653 return Ok(ret); 1654 } else if let Some(flag) = find_flag_by_long!(@os self, arg) { 1655 debugln!( 1656 "Parser::parse_long_arg: Found valid flag '{}'", 1657 flag.to_string() 1658 ); 1659 self.settings.set(AS::ValidArgFound); 1660 // Only flags could be help or version, and we need to check the raw long 1661 // so this is the first point to check 1662 self.check_for_help_and_version_str(arg)?; 1663 1664 self.parse_flag(flag, matcher)?; 1665 1666 // Handle conflicts, requirements, etc. 1667 if self.cache.map_or(true, |name| name != flag.b.name) { 1668 self.cache = Some(flag.b.name); 1669 } 1670 1671 return Ok(ParseResult::Flag); 1672 } else if self.is_set(AS::AllowLeadingHyphen) { 1673 return Ok(ParseResult::MaybeHyphenValue); 1674 } else if self.is_set(AS::ValidNegNumFound) { 1675 return Ok(ParseResult::MaybeNegNum); 1676 } 1677 1678 debugln!("Parser::parse_long_arg: Didn't match anything"); 1679 1680 let args_rest: Vec<_> = it.map(|x| x.clone().into()).collect(); 1681 let args_rest2: Vec<_> = args_rest 1682 .iter() 1683 .map(|x| x.to_str().expect(INVALID_UTF8)) 1684 .collect(); 1685 self.did_you_mean_error(arg.to_str().expect(INVALID_UTF8), matcher, &args_rest2[..]) 1686 .map(|_| ParseResult::NotFound) 1687 } 1688 1689 #[cfg_attr(feature = "lints", allow(len_zero))] parse_short_arg( &mut self, matcher: &mut ArgMatcher<'a>, full_arg: &OsStr, ) -> ClapResult<ParseResult<'a>>1690 fn parse_short_arg( 1691 &mut self, 1692 matcher: &mut ArgMatcher<'a>, 1693 full_arg: &OsStr, 1694 ) -> ClapResult<ParseResult<'a>> { 1695 debugln!("Parser::parse_short_arg: full_arg={:?}", full_arg); 1696 let arg_os = full_arg.trim_left_matches(b'-'); 1697 let arg = arg_os.to_string_lossy(); 1698 1699 // If AllowLeadingHyphen is set, we want to ensure `-val` gets parsed as `-val` and not 1700 // `-v` `-a` `-l` assuming `v` `a` and `l` are all, or mostly, valid shorts. 1701 if self.is_set(AS::AllowLeadingHyphen) { 1702 if arg.chars().any(|c| !self.contains_short(c)) { 1703 debugln!( 1704 "Parser::parse_short_arg: LeadingHyphenAllowed yet -{} isn't valid", 1705 arg 1706 ); 1707 return Ok(ParseResult::MaybeHyphenValue); 1708 } 1709 } else if self.is_set(AS::ValidNegNumFound) { 1710 // TODO: Add docs about having AllowNegativeNumbers and `-2` as a valid short 1711 // May be better to move this to *after* not finding a valid flag/opt? 1712 debugln!("Parser::parse_short_arg: Valid negative num..."); 1713 return Ok(ParseResult::MaybeNegNum); 1714 } 1715 1716 let mut ret = ParseResult::NotFound; 1717 for c in arg.chars() { 1718 debugln!("Parser::parse_short_arg:iter:{}", c); 1719 1720 // update each index because `-abcd` is four indices to clap 1721 self.cur_idx.set(self.cur_idx.get() + 1); 1722 1723 // Check for matching short options, and return the name if there is no trailing 1724 // concatenated value: -oval 1725 // Option: -o 1726 // Value: val 1727 if let Some(opt) = find_opt_by_short!(self, c) { 1728 debugln!("Parser::parse_short_arg:iter:{}: Found valid opt", c); 1729 self.settings.set(AS::ValidArgFound); 1730 // Check for trailing concatenated value 1731 let p: Vec<_> = arg.splitn(2, c).collect(); 1732 debugln!( 1733 "Parser::parse_short_arg:iter:{}: p[0]={:?}, p[1]={:?}", 1734 c, 1735 p[0].as_bytes(), 1736 p[1].as_bytes() 1737 ); 1738 let i = p[0].as_bytes().len() + 1; 1739 let val = if p[1].as_bytes().len() > 0 { 1740 debugln!( 1741 "Parser::parse_short_arg:iter:{}: val={:?} (bytes), val={:?} (ascii)", 1742 c, 1743 arg_os.split_at(i).1.as_bytes(), 1744 arg_os.split_at(i).1 1745 ); 1746 Some(arg_os.split_at(i).1) 1747 } else { 1748 None 1749 }; 1750 1751 // Default to "we're expecting a value later" 1752 let ret = self.parse_opt(val, opt, false, matcher)?; 1753 1754 if self.cache.map_or(true, |name| name != opt.b.name) { 1755 self.cache = Some(opt.b.name); 1756 } 1757 1758 return Ok(ret); 1759 } else if let Some(flag) = find_flag_by_short!(self, c) { 1760 debugln!("Parser::parse_short_arg:iter:{}: Found valid flag", c); 1761 self.settings.set(AS::ValidArgFound); 1762 // Only flags can be help or version 1763 self.check_for_help_and_version_char(c)?; 1764 ret = self.parse_flag(flag, matcher)?; 1765 1766 // Handle conflicts, requirements, overrides, etc. 1767 // Must be called here due to mutabililty 1768 if self.cache.map_or(true, |name| name != flag.b.name) { 1769 self.cache = Some(flag.b.name); 1770 } 1771 } else { 1772 let arg = format!("-{}", c); 1773 return Err(Error::unknown_argument( 1774 &*arg, 1775 "", 1776 &*usage::create_error_usage(self, matcher, None), 1777 self.color(), 1778 )); 1779 } 1780 } 1781 Ok(ret) 1782 } 1783 parse_opt( &self, val: Option<&OsStr>, opt: &OptBuilder<'a, 'b>, had_eq: bool, matcher: &mut ArgMatcher<'a>, ) -> ClapResult<ParseResult<'a>>1784 fn parse_opt( 1785 &self, 1786 val: Option<&OsStr>, 1787 opt: &OptBuilder<'a, 'b>, 1788 had_eq: bool, 1789 matcher: &mut ArgMatcher<'a>, 1790 ) -> ClapResult<ParseResult<'a>> { 1791 debugln!("Parser::parse_opt; opt={}, val={:?}", opt.b.name, val); 1792 debugln!("Parser::parse_opt; opt.settings={:?}", opt.b.settings); 1793 let mut has_eq = false; 1794 let no_val = val.is_none(); 1795 let empty_vals = opt.is_set(ArgSettings::EmptyValues); 1796 let min_vals_zero = opt.v.min_vals.unwrap_or(1) == 0; 1797 let needs_eq = opt.is_set(ArgSettings::RequireEquals); 1798 1799 debug!("Parser::parse_opt; Checking for val..."); 1800 if let Some(fv) = val { 1801 has_eq = fv.starts_with(&[b'=']) || had_eq; 1802 let v = fv.trim_left_matches(b'='); 1803 if !empty_vals && (v.len() == 0 || (needs_eq && !has_eq)) { 1804 sdebugln!("Found Empty - Error"); 1805 return Err(Error::empty_value( 1806 opt, 1807 &*usage::create_error_usage(self, matcher, None), 1808 self.color(), 1809 )); 1810 } 1811 sdebugln!("Found - {:?}, len: {}", v, v.len()); 1812 debugln!( 1813 "Parser::parse_opt: {:?} contains '='...{:?}", 1814 fv, 1815 fv.starts_with(&[b'=']) 1816 ); 1817 self.add_val_to_arg(opt, v, matcher)?; 1818 } else if needs_eq && !(empty_vals || min_vals_zero) { 1819 sdebugln!("None, but requires equals...Error"); 1820 return Err(Error::empty_value( 1821 opt, 1822 &*usage::create_error_usage(self, matcher, None), 1823 self.color(), 1824 )); 1825 } else { 1826 sdebugln!("None"); 1827 } 1828 1829 matcher.inc_occurrence_of(opt.b.name); 1830 // Increment or create the group "args" 1831 self.groups_for_arg(opt.b.name) 1832 .and_then(|vec| Some(matcher.inc_occurrences_of(&*vec))); 1833 1834 let needs_delim = opt.is_set(ArgSettings::RequireDelimiter); 1835 let mult = opt.is_set(ArgSettings::Multiple); 1836 if no_val && min_vals_zero && !has_eq && needs_eq { 1837 debugln!("Parser::parse_opt: More arg vals not required..."); 1838 return Ok(ParseResult::ValuesDone); 1839 } else if no_val || (mult && !needs_delim) && !has_eq && matcher.needs_more_vals(opt) { 1840 debugln!("Parser::parse_opt: More arg vals required..."); 1841 return Ok(ParseResult::Opt(opt.b.name)); 1842 } 1843 debugln!("Parser::parse_opt: More arg vals not required..."); 1844 Ok(ParseResult::ValuesDone) 1845 } 1846 add_val_to_arg<A>( &self, arg: &A, val: &OsStr, matcher: &mut ArgMatcher<'a>, ) -> ClapResult<ParseResult<'a>> where A: AnyArg<'a, 'b> + Display,1847 fn add_val_to_arg<A>( 1848 &self, 1849 arg: &A, 1850 val: &OsStr, 1851 matcher: &mut ArgMatcher<'a>, 1852 ) -> ClapResult<ParseResult<'a>> 1853 where 1854 A: AnyArg<'a, 'b> + Display, 1855 { 1856 debugln!("Parser::add_val_to_arg; arg={}, val={:?}", arg.name(), val); 1857 debugln!( 1858 "Parser::add_val_to_arg; trailing_vals={:?}, DontDelimTrailingVals={:?}", 1859 self.is_set(AS::TrailingValues), 1860 self.is_set(AS::DontDelimitTrailingValues) 1861 ); 1862 if !(self.is_set(AS::TrailingValues) && self.is_set(AS::DontDelimitTrailingValues)) { 1863 if let Some(delim) = arg.val_delim() { 1864 if val.is_empty() { 1865 Ok(self.add_single_val_to_arg(arg, val, matcher)?) 1866 } else { 1867 let mut iret = ParseResult::ValuesDone; 1868 for v in val.split(delim as u32 as u8) { 1869 iret = self.add_single_val_to_arg(arg, v, matcher)?; 1870 } 1871 // If there was a delimiter used, we're not looking for more values 1872 if val.contains_byte(delim as u32 as u8) 1873 || arg.is_set(ArgSettings::RequireDelimiter) 1874 { 1875 iret = ParseResult::ValuesDone; 1876 } 1877 Ok(iret) 1878 } 1879 } else { 1880 self.add_single_val_to_arg(arg, val, matcher) 1881 } 1882 } else { 1883 self.add_single_val_to_arg(arg, val, matcher) 1884 } 1885 } 1886 add_single_val_to_arg<A>( &self, arg: &A, v: &OsStr, matcher: &mut ArgMatcher<'a>, ) -> ClapResult<ParseResult<'a>> where A: AnyArg<'a, 'b> + Display,1887 fn add_single_val_to_arg<A>( 1888 &self, 1889 arg: &A, 1890 v: &OsStr, 1891 matcher: &mut ArgMatcher<'a>, 1892 ) -> ClapResult<ParseResult<'a>> 1893 where 1894 A: AnyArg<'a, 'b> + Display, 1895 { 1896 debugln!("Parser::add_single_val_to_arg;"); 1897 debugln!("Parser::add_single_val_to_arg: adding val...{:?}", v); 1898 1899 // update the current index because each value is a distinct index to clap 1900 self.cur_idx.set(self.cur_idx.get() + 1); 1901 1902 // @TODO @docs @p4: docs for indices should probably note that a terminator isn't a value 1903 // and therefore not reported in indices 1904 if let Some(t) = arg.val_terminator() { 1905 if t == v { 1906 return Ok(ParseResult::ValuesDone); 1907 } 1908 } 1909 1910 matcher.add_val_to(arg.name(), v); 1911 matcher.add_index_to(arg.name(), self.cur_idx.get()); 1912 1913 // Increment or create the group "args" 1914 if let Some(grps) = self.groups_for_arg(arg.name()) { 1915 for grp in grps { 1916 matcher.add_val_to(&*grp, v); 1917 } 1918 } 1919 1920 if matcher.needs_more_vals(arg) { 1921 return Ok(ParseResult::Opt(arg.name())); 1922 } 1923 Ok(ParseResult::ValuesDone) 1924 } 1925 parse_flag( &self, flag: &FlagBuilder<'a, 'b>, matcher: &mut ArgMatcher<'a>, ) -> ClapResult<ParseResult<'a>>1926 fn parse_flag( 1927 &self, 1928 flag: &FlagBuilder<'a, 'b>, 1929 matcher: &mut ArgMatcher<'a>, 1930 ) -> ClapResult<ParseResult<'a>> { 1931 debugln!("Parser::parse_flag;"); 1932 1933 matcher.inc_occurrence_of(flag.b.name); 1934 matcher.add_index_to(flag.b.name, self.cur_idx.get()); 1935 1936 // Increment or create the group "args" 1937 self.groups_for_arg(flag.b.name) 1938 .and_then(|vec| Some(matcher.inc_occurrences_of(&*vec))); 1939 1940 Ok(ParseResult::Flag) 1941 } 1942 did_you_mean_error( &self, arg: &str, matcher: &mut ArgMatcher<'a>, args_rest: &[&str], ) -> ClapResult<()>1943 fn did_you_mean_error( 1944 &self, 1945 arg: &str, 1946 matcher: &mut ArgMatcher<'a>, 1947 args_rest: &[&str], 1948 ) -> ClapResult<()> { 1949 // Didn't match a flag or option 1950 let suffix = 1951 suggestions::did_you_mean_flag_suffix(arg, &args_rest, longs!(self), &self.subcommands); 1952 1953 // Add the arg to the matches to build a proper usage string 1954 if let Some(name) = suffix.1 { 1955 if let Some(opt) = find_opt_by_long!(self, name) { 1956 self.groups_for_arg(&*opt.b.name) 1957 .and_then(|grps| Some(matcher.inc_occurrences_of(&*grps))); 1958 matcher.insert(&*opt.b.name); 1959 } else if let Some(flg) = find_flag_by_long!(self, name) { 1960 self.groups_for_arg(&*flg.b.name) 1961 .and_then(|grps| Some(matcher.inc_occurrences_of(&*grps))); 1962 matcher.insert(&*flg.b.name); 1963 } 1964 } 1965 1966 let used_arg = format!("--{}", arg); 1967 Err(Error::unknown_argument( 1968 &*used_arg, 1969 &*suffix.0, 1970 &*usage::create_error_usage(self, matcher, None), 1971 self.color(), 1972 )) 1973 } 1974 1975 // Prints the version to the user and exits if quit=true print_version<W: Write>(&self, w: &mut W, use_long: bool) -> ClapResult<()>1976 fn print_version<W: Write>(&self, w: &mut W, use_long: bool) -> ClapResult<()> { 1977 self.write_version(w, use_long)?; 1978 w.flush().map_err(Error::from) 1979 } 1980 write_version<W: Write>(&self, w: &mut W, use_long: bool) -> io::Result<()>1981 pub fn write_version<W: Write>(&self, w: &mut W, use_long: bool) -> io::Result<()> { 1982 let ver = if use_long { 1983 self.meta 1984 .long_version 1985 .unwrap_or_else(|| self.meta.version.unwrap_or("")) 1986 } else { 1987 self.meta 1988 .version 1989 .unwrap_or_else(|| self.meta.long_version.unwrap_or("")) 1990 }; 1991 if let Some(bn) = self.meta.bin_name.as_ref() { 1992 if bn.contains(' ') { 1993 // Incase we're dealing with subcommands i.e. git mv is translated to git-mv 1994 write!(w, "{} {}", bn.replace(" ", "-"), ver) 1995 } else { 1996 write!(w, "{} {}", &self.meta.name[..], ver) 1997 } 1998 } else { 1999 write!(w, "{} {}", &self.meta.name[..], ver) 2000 } 2001 } 2002 print_help(&self) -> ClapResult<()>2003 pub fn print_help(&self) -> ClapResult<()> { 2004 let out = io::stdout(); 2005 let mut buf_w = BufWriter::new(out.lock()); 2006 self.write_help(&mut buf_w) 2007 } 2008 write_help<W: Write>(&self, w: &mut W) -> ClapResult<()>2009 pub fn write_help<W: Write>(&self, w: &mut W) -> ClapResult<()> { 2010 Help::write_parser_help(w, self, false) 2011 } 2012 write_long_help<W: Write>(&self, w: &mut W) -> ClapResult<()>2013 pub fn write_long_help<W: Write>(&self, w: &mut W) -> ClapResult<()> { 2014 Help::write_parser_help(w, self, true) 2015 } 2016 write_help_err<W: Write>(&self, w: &mut W) -> ClapResult<()>2017 pub fn write_help_err<W: Write>(&self, w: &mut W) -> ClapResult<()> { 2018 Help::write_parser_help_to_stderr(w, self) 2019 } 2020 add_defaults(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()>2021 pub fn add_defaults(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> { 2022 debugln!("Parser::add_defaults;"); 2023 macro_rules! add_val { 2024 (@default $_self:ident, $a:ident, $m:ident) => { 2025 if let Some(ref val) = $a.v.default_val { 2026 debugln!("Parser::add_defaults:iter:{}: has default vals", $a.b.name); 2027 if $m.get($a.b.name).map(|ma| ma.vals.len()).map(|len| len == 0).unwrap_or(false) { 2028 debugln!("Parser::add_defaults:iter:{}: has no user defined vals", $a.b.name); 2029 $_self.add_val_to_arg($a, OsStr::new(val), $m)?; 2030 2031 if $_self.cache.map_or(true, |name| name != $a.name()) { 2032 $_self.cache = Some($a.name()); 2033 } 2034 } else if $m.get($a.b.name).is_some() { 2035 debugln!("Parser::add_defaults:iter:{}: has user defined vals", $a.b.name); 2036 } else { 2037 debugln!("Parser::add_defaults:iter:{}: wasn't used", $a.b.name); 2038 2039 $_self.add_val_to_arg($a, OsStr::new(val), $m)?; 2040 2041 if $_self.cache.map_or(true, |name| name != $a.name()) { 2042 $_self.cache = Some($a.name()); 2043 } 2044 } 2045 } else { 2046 debugln!("Parser::add_defaults:iter:{}: doesn't have default vals", $a.b.name); 2047 } 2048 }; 2049 ($_self:ident, $a:ident, $m:ident) => { 2050 if let Some(ref vm) = $a.v.default_vals_ifs { 2051 sdebugln!(" has conditional defaults"); 2052 let mut done = false; 2053 if $m.get($a.b.name).is_none() { 2054 for &(arg, val, default) in vm.values() { 2055 let add = if let Some(a) = $m.get(arg) { 2056 if let Some(v) = val { 2057 a.vals.iter().any(|value| v == value) 2058 } else { 2059 true 2060 } 2061 } else { 2062 false 2063 }; 2064 if add { 2065 $_self.add_val_to_arg($a, OsStr::new(default), $m)?; 2066 if $_self.cache.map_or(true, |name| name != $a.name()) { 2067 $_self.cache = Some($a.name()); 2068 } 2069 done = true; 2070 break; 2071 } 2072 } 2073 } 2074 2075 if done { 2076 continue; // outer loop (outside macro) 2077 } 2078 } else { 2079 sdebugln!(" doesn't have conditional defaults"); 2080 } 2081 add_val!(@default $_self, $a, $m) 2082 }; 2083 } 2084 2085 for o in &self.opts { 2086 debug!("Parser::add_defaults:iter:{}:", o.b.name); 2087 add_val!(self, o, matcher); 2088 } 2089 for p in self.positionals.values() { 2090 debug!("Parser::add_defaults:iter:{}:", p.b.name); 2091 add_val!(self, p, matcher); 2092 } 2093 Ok(()) 2094 } 2095 add_env(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()>2096 pub fn add_env(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> { 2097 macro_rules! add_val { 2098 ($_self:ident, $a:ident, $m:ident) => { 2099 if let Some(ref val) = $a.v.env { 2100 if $m 2101 .get($a.b.name) 2102 .map(|ma| ma.vals.len()) 2103 .map(|len| len == 0) 2104 .unwrap_or(false) 2105 { 2106 if let Some(ref val) = val.1 { 2107 $_self.add_val_to_arg($a, OsStr::new(val), $m)?; 2108 2109 if $_self.cache.map_or(true, |name| name != $a.name()) { 2110 $_self.cache = Some($a.name()); 2111 } 2112 } 2113 } else { 2114 if let Some(ref val) = val.1 { 2115 $_self.add_val_to_arg($a, OsStr::new(val), $m)?; 2116 2117 if $_self.cache.map_or(true, |name| name != $a.name()) { 2118 $_self.cache = Some($a.name()); 2119 } 2120 } 2121 } 2122 } 2123 }; 2124 } 2125 2126 for o in &self.opts { 2127 add_val!(self, o, matcher); 2128 } 2129 for p in self.positionals.values() { 2130 add_val!(self, p, matcher); 2131 } 2132 Ok(()) 2133 } 2134 flags(&self) -> Iter<FlagBuilder<'a, 'b>>2135 pub fn flags(&self) -> Iter<FlagBuilder<'a, 'b>> { 2136 self.flags.iter() 2137 } 2138 opts(&self) -> Iter<OptBuilder<'a, 'b>>2139 pub fn opts(&self) -> Iter<OptBuilder<'a, 'b>> { 2140 self.opts.iter() 2141 } 2142 positionals(&self) -> map::Values<PosBuilder<'a, 'b>>2143 pub fn positionals(&self) -> map::Values<PosBuilder<'a, 'b>> { 2144 self.positionals.values() 2145 } 2146 subcommands(&self) -> Iter<App>2147 pub fn subcommands(&self) -> Iter<App> { 2148 self.subcommands.iter() 2149 } 2150 2151 // Should we color the output? None=determined by output location, true=yes, false=no 2152 #[doc(hidden)] color(&self) -> ColorWhen2153 pub fn color(&self) -> ColorWhen { 2154 debugln!("Parser::color;"); 2155 debug!("Parser::color: Color setting..."); 2156 if self.is_set(AS::ColorNever) { 2157 sdebugln!("Never"); 2158 ColorWhen::Never 2159 } else if self.is_set(AS::ColorAlways) { 2160 sdebugln!("Always"); 2161 ColorWhen::Always 2162 } else { 2163 sdebugln!("Auto"); 2164 ColorWhen::Auto 2165 } 2166 } 2167 find_any_arg(&self, name: &str) -> Option<&AnyArg<'a, 'b>>2168 pub fn find_any_arg(&self, name: &str) -> Option<&AnyArg<'a, 'b>> { 2169 if let Some(f) = find_by_name!(self, name, flags, iter) { 2170 return Some(f); 2171 } 2172 if let Some(o) = find_by_name!(self, name, opts, iter) { 2173 return Some(o); 2174 } 2175 if let Some(p) = find_by_name!(self, name, positionals, values) { 2176 return Some(p); 2177 } 2178 None 2179 } 2180 2181 /// Check is a given string matches the binary name for this parser is_bin_name(&self, value: &str) -> bool2182 fn is_bin_name(&self, value: &str) -> bool { 2183 self.meta 2184 .bin_name 2185 .as_ref() 2186 .and_then(|name| Some(value == name)) 2187 .unwrap_or(false) 2188 } 2189 2190 /// Check is a given string is an alias for this parser is_alias(&self, value: &str) -> bool2191 fn is_alias(&self, value: &str) -> bool { 2192 self.meta 2193 .aliases 2194 .as_ref() 2195 .and_then(|aliases| { 2196 for alias in aliases { 2197 if alias.0 == value { 2198 return Some(true); 2199 } 2200 } 2201 Some(false) 2202 }) 2203 .unwrap_or(false) 2204 } 2205 2206 // Only used for completion scripts due to bin_name messiness 2207 #[cfg_attr(feature = "lints", allow(block_in_if_condition_stmt))] find_subcommand(&'b self, sc: &str) -> Option<&'b App<'a, 'b>>2208 pub fn find_subcommand(&'b self, sc: &str) -> Option<&'b App<'a, 'b>> { 2209 debugln!("Parser::find_subcommand: sc={}", sc); 2210 debugln!( 2211 "Parser::find_subcommand: Currently in Parser...{}", 2212 self.meta.bin_name.as_ref().unwrap() 2213 ); 2214 for s in &self.subcommands { 2215 if s.p.is_bin_name(sc) { 2216 return Some(s); 2217 } 2218 // XXX: why do we split here? 2219 // isn't `sc` supposed to be single word already? 2220 let last = sc.split(' ').rev().next().expect(INTERNAL_ERROR_MSG); 2221 if s.p.is_alias(last) { 2222 return Some(s); 2223 } 2224 2225 if let Some(app) = s.p.find_subcommand(sc) { 2226 return Some(app); 2227 } 2228 } 2229 None 2230 } 2231 2232 #[inline] contains_long(&self, l: &str) -> bool2233 fn contains_long(&self, l: &str) -> bool { 2234 longs!(self).any(|al| al == &l) 2235 } 2236 2237 #[inline] contains_short(&self, s: char) -> bool2238 fn contains_short(&self, s: char) -> bool { 2239 shorts!(self).any(|arg_s| arg_s == &s) 2240 } 2241 } 2242