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