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