2 use std
::collections
::{BTreeMap, HashMap, VecDeque}
;
3 use std
::ffi
::{OsStr, OsString}
;
6 use std
::io
::{self, BufWriter, Write}
;
7 #[cfg(feature = "debug")]
8 use std
::os
::unix
::ffi
::OsStrExt
;
9 use std
::path
::PathBuf
;
11 use std
::iter
::Peekable
;
14 use vec_map
::{self, VecMap}
;
17 use INTERNAL_ERROR_MSG
;
22 use app
::meta
::AppMeta
;
23 use app
::settings
::{AppFlags, AppSettings}
;
24 use args
::{AnyArg, ArgMatcher, Base, Switched, Arg, ArgGroup, FlagBuilder, OptBuilder, PosBuilder}
;
26 use args
::settings
::ArgSettings
;
27 use completions
::ComplGen
;
28 use errors
::{Error, ErrorKind}
;
29 use errors
::Result
as ClapResult
;
30 use fmt
::{Colorizer, ColorWhen}
;
31 use osstringext
::OsStrExt2
;
32 use completions
::Shell
;
35 #[allow(missing_debug_implementations)]
37 pub struct Parser
<'a
, 'b
>
41 required
: Vec
<&'a
str>,
42 r_ifs
: Vec
<(&'a
str, &'b
str, &'a
str)>,
43 pub short_list
: Vec
<char>,
44 pub long_list
: Vec
<&'b
str>,
45 blacklist
: Vec
<&'b
str>,
46 // A list of possible flags
47 pub flags
: Vec
<FlagBuilder
<'a
, 'b
>>,
48 // A list of possible options
49 pub opts
: Vec
<OptBuilder
<'a
, 'b
>>,
50 // A list of positional arguments
51 pub positionals
: VecMap
<PosBuilder
<'a
, 'b
>>,
52 // A list of subcommands
54 pub subcommands
: Vec
<App
<'a
, 'b
>>,
55 groups
: HashMap
<&'a
str, ArgGroup
<'a
>>,
56 pub global_args
: Vec
<Arg
<'a
, 'b
>>,
57 overrides
: Vec
<&'b
str>,
58 help_short
: Option
<char>,
59 version_short
: Option
<char>,
61 pub g_settings
: AppFlags
,
62 pub meta
: AppMeta
<'b
>,
66 // have we found a valid arg yet
70 impl<'a
, 'b
> Default
for Parser
<'a
, 'b
> {
71 fn default() -> Self {
76 positionals
: VecMap
::new(),
85 groups
: HashMap
::new(),
88 g_settings
: AppFlags
::new(),
89 settings
: AppFlags
::new(),
99 impl<'a
, 'b
> Parser
<'a
, 'b
>
102 pub fn with_name(n
: String
) -> Self {
103 Parser { meta: AppMeta::with_name(n), ..Default::default() }
106 pub fn help_short(&mut self, s
: &str) {
107 self.help_short
= s
.trim_left_matches(|c
| c
== '
-'
)
112 pub fn version_short(&mut self, s
: &str) {
113 self.version_short
= s
.trim_left_matches(|c
| c
== '
-'
)
118 pub fn gen_completions_to
<W
: Write
>(&mut self, for_shell
: Shell
, buf
: &mut W
) {
119 if !self.propogated
{
120 self.propogate_help_version();
121 self.build_bin_names();
122 self.propogate_globals();
123 self.propogate_settings();
124 self.propogated
= true;
127 ComplGen
::new(self).generate(for_shell
, buf
)
130 pub fn gen_completions(&mut self, for_shell
: Shell
, od
: OsString
) {
131 use std
::error
::Error
;
133 let out_dir
= PathBuf
::from(od
);
134 let name
= &*self.meta
.bin_name
.as_ref().unwrap().clone();
135 let file_name
= match for_shell
{
136 Shell
::Bash
=> format
!("{}.bash-completion", name
),
137 Shell
::Fish
=> format
!("{}.fish", name
),
138 Shell
::Zsh
=> format
!("_{}", name
),
139 Shell
::PowerShell
=> format
!("_{}.ps1", name
),
142 let mut file
= match File
::create(out_dir
.join(file_name
)) {
143 Err(why
) => panic
!("couldn't create completion file: {}", why
.description()),
146 self.gen_completions_to(for_shell
, &mut file
)
149 // actually adds the arguments
150 pub fn add_arg(&mut self, a
: &Arg
<'a
, 'b
>) {
151 debug_assert
!(!(self.flags
.iter().any(|f
| &f
.b
.name
== &a
.name
) ||
152 self.opts
.iter().any(|o
| o
.b
.name
== a
.name
) ||
153 self.positionals
.values().any(|p
| p
.b
.name
== a
.name
)),
154 format
!("Non-unique argument name: {} is already in use", a
.name
));
155 if let Some(ref r_ifs
) = a
.r_ifs
{
156 for &(arg
, val
) in r_ifs
{
157 self.r_ifs
.push((arg
, val
, a
.name
));
160 if let Some(ref grps
) = a
.groups
{
162 let ag
= self.groups
.entry(g
).or_insert_with(|| ArgGroup
::with_name(g
));
163 ag
.args
.push(a
.name
);
166 if let Some(s
) = a
.short
{
167 debug_assert
!(!self.short_list
.contains(&s
),
168 format
!("Argument short must be unique\n\n\t-{} is already in use",
170 self.short_list
.push(s
);
172 if let Some(l
) = a
.long
{
173 debug_assert
!(!self.long_list
.contains(&l
),
174 format
!("Argument long must be unique\n\n\t--{} is already in use",
176 self.long_list
.push(l
);
178 self.unset(AppSettings
::NeedsLongHelp
);
179 } else if l
== "version" {
180 self.unset(AppSettings
::NeedsLongVersion
);
183 if a
.is_set(ArgSettings
::Required
) {
184 self.required
.push(a
.name
);
186 if a
.index
.is_some() || (a
.short
.is_none() && a
.long
.is_none()) {
187 let i
= if a
.index
.is_none() {
188 (self.positionals
.len() + 1)
190 a
.index
.unwrap() as usize
192 debug_assert
!(!self.positionals
.contains_key(i
),
193 format
!("Argument \"{}\" has the same index as another positional \
194 argument\n\n\tPerhaps try .multiple(true) to allow one positional argument \
195 to take multiple values",
197 let pb
= PosBuilder
::from_arg(a
, i
as u64, &mut self.required
);
198 self.positionals
.insert(i
, pb
);
199 } else if a
.is_set(ArgSettings
::TakesValue
) {
200 let mut ob
= OptBuilder
::from_arg(a
, &mut self.required
);
201 let id
= self.opts
.len();
203 ob
.s
.unified_ord
= self.flags
.len() + self.opts
.len();
204 self.opts
.insert(id
, ob
);
206 let mut fb
= FlagBuilder
::from(a
);
207 let id
= self.flags
.len();
209 fb
.s
.unified_ord
= self.flags
.len() + self.opts
.len();
210 self.flags
.insert(id
, fb
);
212 if a
.is_set(ArgSettings
::Global
) {
213 debug_assert
!(!a
.is_set(ArgSettings
::Required
),
214 format
!("Global arguments cannot be required.\n\n\t'{}' is marked as \
215 global and required",
217 self.global_args
.push(a
.into());
221 pub fn add_group(&mut self, group
: ArgGroup
<'a
>) {
223 self.required
.push(group
.name
.into());
224 if let Some(ref reqs
) = group
.requires
{
225 self.required
.extend_from_slice(reqs
);
227 if let Some(ref bl
) = group
.conflicts
{
228 self.blacklist
.extend_from_slice(bl
);
231 let mut found
= false;
232 if let Some(ref mut grp
) = self.groups
.get_mut(&group
.name
) {
233 grp
.args
.extend_from_slice(&group
.args
);
234 grp
.requires
= group
.requires
.clone();
235 grp
.conflicts
= group
.conflicts
.clone();
236 grp
.required
= group
.required
;
240 self.groups
.insert(group
.name
.into(), group
);
244 pub fn add_subcommand(&mut self, mut subcmd
: App
<'a
, 'b
>) {
245 debugln
!("Parser::add_subcommand: term_w={:?}, name={}",
246 self.meta
.term_w
, subcmd
.p
.meta
.name
);
247 subcmd
.p
.meta
.term_w
= self.meta
.term_w
;
248 if subcmd
.p
.meta
.name
== "help" {
249 self.settings
.unset(AppSettings
::NeedsSubcommandHelp
);
252 self.subcommands
.push(subcmd
);
255 pub fn propogate_settings(&mut self) {
256 debugln
!("Parser::propogate_settings: self={}, g_settings={:#?}",
257 self.meta
.name
, self.g_settings
);
258 for sc
in &mut self.subcommands
{
259 debugln
!("Parser::propogate_settings: sc={}, settings={:#?}, g_settings={:#?}",
260 sc
.p
.meta
.name
, sc
.p
.settings
, sc
.p
.g_settings
);
261 // We have to create a new scope in order to tell rustc the borrow of `sc` is
262 // done and to recursively call this method
264 let vsc
= self.settings
.is_set(AppSettings
::VersionlessSubcommands
);
265 let gv
= self.settings
.is_set(AppSettings
::GlobalVersion
);
268 sc
.p
.settings
.set(AppSettings
::DisableVersion
);
270 if gv
&& sc
.p
.meta
.version
.is_none() && self.meta
.version
.is_some() {
271 sc
.p
.set(AppSettings
::GlobalVersion
);
272 sc
.p
.meta
.version
= Some(self.meta
.version
.unwrap());
274 sc
.p
.settings
= sc
.p
.settings
| self.g_settings
;
275 sc
.p
.g_settings
= sc
.p
.g_settings
| self.g_settings
;
277 sc
.p
.propogate_settings();
281 #[cfg_attr(feature = "lints", allow(needless_borrow))]
282 pub fn derive_display_order(&mut self) {
283 if self.settings
.is_set(AppSettings
::DeriveDisplayOrder
) {
284 let unified
= self.settings
.is_set(AppSettings
::UnifiedHelpMessage
);
285 for (i
, o
) in self.opts
288 .filter(|&(_
, ref o
)| o
.s
.disp_ord
== 999) {
289 o
.s
.disp_ord
= if unified { o.s.unified_ord }
else { i }
;
291 for (i
, f
) in self.flags
294 .filter(|&(_
, ref f
)| f
.s
.disp_ord
== 999) {
295 f
.s
.disp_ord
= if unified { f.s.unified_ord }
else { i }
;
297 for (i
, sc
) in &mut self.subcommands
300 .filter(|&(_
, ref sc
)| sc
.p
.meta
.disp_ord
== 999) {
301 sc
.p
.meta
.disp_ord
= i
;
304 for sc
in &mut self.subcommands
{
305 sc
.p
.derive_display_order();
309 pub fn required(&self) -> Iter
<&str> { self.required.iter() }
311 pub fn get_required_from(&self,
313 matcher
: Option
<&ArgMatcher
<'a
>>,
315 -> VecDeque
<String
> {
316 debugln
!("Parser::get_required_from: reqs={:?}, extra={:?}", reqs
, extra
);
317 let mut c_flags
: Vec
<&str> = vec
![];
318 let mut c_pos
: Vec
<&str> = vec
![];
319 let mut c_opt
: Vec
<&str> = vec
![];
320 let mut grps
: Vec
<&str> = vec
![];
321 macro_rules
! categorize
{
322 ($_self
:ident
, $name
:ident
, $c_flags
:ident
, $c_pos
:ident
, $c_opt
:ident
, $grps
:ident
) => {
323 if $_self
.flags
.iter().any(|f
| &f
.b
.name
== $name
) {
324 $c_flags
.push($name
);
325 } else if self.opts
.iter().any(|o
| &o
.b
.name
== $name
) {
327 } else if self.groups
.contains_key($name
) {
335 categorize
!(self, name
, c_flags
, c_pos
, c_opt
, grps
);
337 if let Some(ref name
) = extra
{
338 categorize
!(self, name
, c_flags
, c_pos
, c_opt
, grps
);
340 macro_rules
! fill_vecs
{
342 $t1
:ident
=> $v1
:ident
=> $i1
:ident
,
343 $t2
:ident
=> $v2
:ident
=> $i2
:ident
,
344 $t3
:ident
=> $v3
:ident
=> $i3
:ident
,
345 $gv
:ident
, $tmp
:ident
348 if let Some(a
) = self.$t1
.$
i1().filter(|arg
| &arg
.b
.name
== a
).next() {
349 if let Some(ref rl
) = a
.b
.requires
{
350 for &(_
, r
) in rl
.iter() {
351 if !reqs
.contains(&r
) {
352 if $_self
.$t1
.$
i1().any(|t
| &t
.b
.name
== &r
) {
354 } else if $_self
.$t2
.$
i2().any(|t
| &t
.b
.name
== &r
) {
356 } else if $_self
.$t3
.$
i3().any(|t
| &t
.b
.name
== &r
) {
358 } else if $_self
.groups
.contains_key(r
) {
370 let mut tmp
= vec
![];
372 flags
=> c_flags
=> iter
,
373 opts
=> c_opt
=> iter
,
374 positionals
=> c_pos
=> values
,
379 opts
=> c_opt
=> iter
,
380 flags
=> c_flags
=> iter
,
381 positionals
=> c_pos
=> values
,
386 positionals
=> c_pos
=> values
,
387 opts
=> c_opt
=> iter
,
388 flags
=> c_flags
=> iter
,
391 let mut ret_val
= VecDeque
::new();
396 let args_in_groups
= grps
.iter()
397 .flat_map(|g
| self.arg_names_in_group(g
))
398 .collect
::<Vec
<_
>>();
400 let pmap
= c_pos
.into_iter()
401 .filter(|&p
| matcher
.is_none() || !matcher
.as_ref().unwrap().contains(p
))
402 .filter_map(|p
| self.positionals
.values().find(|x
| x
.b
.name
== p
))
403 .filter(|p
| !args_in_groups
.contains(&p
.b
.name
))
404 .map(|p
| (p
.index
, p
))
405 .collect
::<BTreeMap
<u64, &PosBuilder
>>();// sort by index
406 debugln
!("Parser::get_required_from: args_in_groups={:?}", args_in_groups
);
407 for &p
in pmap
.values() {
408 let s
= p
.to_string();
409 if args_in_groups
.is_empty() || !args_in_groups
.contains(&&*s
) {
410 ret_val
.push_back(s
);
413 macro_rules
! write_arg
{
414 ($i
:expr
, $m
:ident
, $v
:ident
, $r
:ident
, $aig
:ident
) => {
416 if $m
.is_some() && $m
.as_ref().unwrap().contains(f
) || $aig
.contains(&f
) {
419 $r
.push_back($i
.filter(|flg
| &flg
.b
.name
== &f
).next().unwrap().to_string());
423 write_arg
!(self.flags
.iter(), matcher
, c_flags
, ret_val
, args_in_groups
);
424 write_arg
!(self.opts
.iter(), matcher
, c_opt
, ret_val
, args_in_groups
);
425 let mut g_vec
= vec
![];
427 let g_string
= self.args_in_group(g
)
429 g_vec
.push(format
!("<{}>", &g_string
[..g_string
.len()]));
433 ret_val
.push_back(g
);
439 // Gets the `[ARGS]` tag for the usage string
440 pub fn get_args_tag(&self) -> Option
<String
> {
441 debugln
!("Parser::get_args_tag;");
443 'outer
: for p
in self.positionals
.values().filter(|p
| !p
.is_set(ArgSettings
::Required
)) {
444 debugln
!("Parser::get_args_tag:iter:iter: p={};", p
.b
.name
);
445 if let Some(g_vec
) = self.groups_for_arg(p
.b
.name
) {
446 for grp_s
in &g_vec
{
447 debugln
!("Parser::get_args_tag:iter:iter: grp_s={};", grp_s
);
448 if let Some(grp
) = self.groups
.get(grp_s
) {
449 debug
!("Parser::get_args_tag:iter:iter: Is group required...{:?}", grp
.required
);
451 // if it's part of a required group we don't want to count it
458 debugln
!("Parser::get_args_tag:iter: {} Args not required", count
);
460 if !self.is_set(AppSettings
::DontCollapseArgsInUsage
) &&
461 (count
> 1 || self.positionals
.len() > 1) {
462 return None
; // [ARGS]
463 } else if count
== 1 {
464 let p
= self.positionals
466 .find(|p
| !p
.is_set(ArgSettings
::Required
))
467 .expect(INTERNAL_ERROR_MSG
);
468 return Some(format
!(" [{}]{}", p
.name_no_brackets(), p
.multiple_str()));
469 } else if self.is_set(AppSettings
::DontCollapseArgsInUsage
) &&
470 !self.positionals
.is_empty() {
471 return Some(self.positionals
473 .filter(|p
| !p
.is_set(ArgSettings
::Required
))
474 .map(|p
| format
!(" [{}]{}", p
.name_no_brackets(), p
.multiple_str()))
481 // Determines if we need the `[FLAGS]` tag in the usage string
482 pub fn needs_flags_tag(&self) -> bool
{
483 debugln
!("Parser::needs_flags_tag;");
484 'outer
: for f
in &self.flags
{
485 debugln
!("Parser::needs_flags_tag:iter: f={};", f
.b
.name
);
486 if let Some(l
) = f
.s
.long
{
487 if l
== "help" || l
== "version" {
488 // Don't print `[FLAGS]` just for help or version
492 if let Some(g_vec
) = self.groups_for_arg(f
.b
.name
) {
493 for grp_s
in &g_vec
{
494 debugln
!("Parser::needs_flags_tag:iter:iter: grp_s={};", grp_s
);
495 if let Some(grp
) = self.groups
.get(grp_s
) {
496 debug
!("Parser::needs_flags_tag:iter:iter: Is group required...{:?}", grp
.required
);
503 debugln
!("Parser::needs_flags_tag:iter: [FLAGS] required");
507 debugln
!("Parser::needs_flags_tag: [FLAGS] not required");
512 pub fn has_opts(&self) -> bool { !self.opts.is_empty() }
515 pub fn has_flags(&self) -> bool { !self.flags.is_empty() }
518 pub fn has_positionals(&self) -> bool { !self.positionals.is_empty() }
521 pub fn has_subcommands(&self) -> bool { !self.subcommands.is_empty() }
524 pub fn is_set(&self, s
: AppSettings
) -> bool { self.settings.is_set(s) }
527 pub fn set(&mut self, s
: AppSettings
) { self.settings.set(s) }
530 pub fn unset(&mut self, s
: AppSettings
) { self.settings.unset(s) }
532 #[cfg_attr(feature = "lints", allow(block_in_if_condition_stmt))]
533 pub fn verify_positionals(&mut self) {
534 // Because you must wait until all arguments have been supplied, this is the first chance
535 // to make assertions on positional argument indexes
537 // Firt we verify that the index highest supplied index, is equal to the number of
538 // positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3
540 if let Some((idx
, p
)) = self.positionals
.iter().rev().next() {
541 debug_assert
!(!(idx
!= self.positionals
.len()),
542 format
!("Found positional argument \"{}\" who's index is {} but there are \
543 only {} positional arguments defined",
546 self.positionals
.len()));
549 // Next we verify that only the highest index has a .multiple(true) (if any)
553 a
.b
.settings
.is_set(ArgSettings
::Multiple
) &&
554 (a
.index
as usize != self.positionals
.len())
558 let mut it
= self.positionals
.values().rev();
559 // Either the final positional is required
560 it
.next().unwrap().is_set(ArgSettings
::Required
)
561 // Or the second to last has a terminator set
562 || it
.next().unwrap().v
.terminator
.is_some()
564 "When using a positional argument with .multiple(true) that is *not the last* \
565 positional argument, the last positional argument (i.e the one with the highest \
566 index) *must* have .required(true) set."
570 let num
= self.positionals
.len() - 1;
571 self.positionals
.get(num
).unwrap().is_set(ArgSettings
::Multiple
)
573 "Only the last positional argument, or second to last positional argument may be set to .multiple(true)");
575 self.set(AppSettings
::LowIndexMultiplePositional
);
578 debug_assert
!(self.positionals
.values()
579 .filter(|p
| p
.b
.settings
.is_set(ArgSettings
::Multiple
)
580 && p
.v
.num_vals
.is_none())
583 "Only one positional argument with .multiple(true) set is allowed per command");
585 // If it's required we also need to ensure all previous positionals are
587 if self.is_set(AppSettings
::AllowMissingPositional
) {
588 let mut found
= false;
589 let mut foundx2
= false;
590 for p
in self.positionals
.values().rev() {
591 if foundx2
&& !p
.b
.settings
.is_set(ArgSettings
::Required
) {
592 // [arg1] <arg2> is Ok
593 // [arg1] <arg2> <arg3> Is not
594 debug_assert
!(p
.b
.settings
.is_set(ArgSettings
::Required
),
595 "Found positional argument which is not required with a lower index \
596 than a required positional argument by two or more: {:?} index {}",
599 } else if p
.b
.settings
.is_set(ArgSettings
::Required
) {
611 let mut found
= false;
612 for p
in self.positionals
.values().rev() {
614 debug_assert
!(p
.b
.settings
.is_set(ArgSettings
::Required
),
615 "Found positional argument which is not required with a lower index \
616 than a required positional argument: {:?} index {}",
619 } else if p
.b
.settings
.is_set(ArgSettings
::Required
) {
627 pub fn propogate_globals(&mut self) {
628 for sc
in &mut self.subcommands
{
629 // We have to create a new scope in order to tell rustc the borrow of `sc` is
630 // done and to recursively call this method
632 for a
in &self.global_args
{
636 sc
.p
.propogate_globals();
640 // Checks if the arg matches a subcommand name, or any of it's aliases (if defined)
642 fn possible_subcommand(&self, arg_os
: &OsStr
) -> bool
{
643 debugln
!("Parser::possible_subcommand: arg={:?}", arg_os
);
644 if self.is_set(AppSettings
::ArgsNegateSubcommands
) && self.valid_arg
{
650 &s
.p
.meta
.name
[..] == &*arg_os
||
651 (s
.p
.meta
.aliases
.is_some() &&
658 .any(|&(a
, _
)| a
== &*arg_os
))
662 fn parse_help_subcommand
<I
, T
>(&self, it
: &mut I
) -> ClapResult
<()>
663 where I
: Iterator
<Item
= T
>,
666 debugln
!("Parser::parse_help_subcommand;");
667 let cmds
: Vec
<OsString
> = it
.map(|c
| c
.into()).collect();
668 let mut help_help
= false;
669 let mut bin_name
= self.meta
672 .unwrap_or(&self.meta
.name
)
675 let mut sc
: &Parser
= self;
676 for (i
, cmd
) in cmds
.iter().enumerate() {
677 if &*cmd
.to_string_lossy() == "help" {
681 if let Some(c
) = sc
.subcommands
683 .find(|s
| &*s
.p
.meta
.name
== cmd
)
686 if i
== cmds
.len() - 1 {
689 } else if let Some(c
) = sc
.subcommands
691 .find(|s
| if let Some(ref als
) = s
.p
695 .any(|&(a
, _
)| &a
== &&*cmd
.to_string_lossy())
701 if i
== cmds
.len() - 1 {
705 return Err(Error
::unrecognized_subcommand(cmd
.to_string_lossy().into_owned(),
709 .unwrap_or(&self.meta
.name
),
712 bin_name
= format
!("{} {}",
719 let mut pb
= PosBuilder
::new("subcommand", 1);
720 pb
.b
.help
= Some("The subcommand whose help message to display");
721 pb
.set(ArgSettings
::Multiple
);
722 sc
.positionals
.insert(1, pb
);
723 sc
.settings
= sc
.settings
| self.g_settings
;
725 sc
.create_help_and_version();
727 if sc
.meta
.bin_name
!= self.meta
.bin_name
{
728 sc
.meta
.bin_name
= Some(format
!("{} {}", bin_name
, sc
.meta
.name
));
733 // allow wrong self convention due to self.valid_neg_num = true and it's a private method
734 #[cfg_attr(feature = "lints", allow(wrong_self_convention))]
736 fn is_new_arg(&mut self, arg_os
: &OsStr
, needs_val_of
: Option
<&'a
str>) -> bool
{
737 debugln
!("Parser::is_new_arg: arg={:?}, Needs Val of={:?}", arg_os
, needs_val_of
);
738 let app_wide_settings
= if self.is_set(AppSettings
::AllowLeadingHyphen
) {
740 } else if self.is_set(AppSettings
::AllowNegativeNumbers
) {
741 let a
= arg_os
.to_string_lossy();
742 if a
.parse
::<i64>().is_ok() || a
.parse
::<f64>().is_ok() {
743 self.valid_neg_num
= true;
751 let arg_allows_tac
= if let Some(name
) = needs_val_of
{
752 if let Some(o
) = find_by_name
!(self, &name
, opts
, iter
) {
753 (o
.is_set(ArgSettings
::AllowLeadingHyphen
) || app_wide_settings
)
754 } else if let Some(p
) = find_by_name
!(self, &name
, positionals
, values
) {
755 (p
.is_set(ArgSettings
::AllowLeadingHyphen
) || app_wide_settings
)
762 debugln
!("Parser::is_new_arg: Does arg allow leading hyphen...{:?}", arg_allows_tac
);
764 // Is this a new argument, or values from a previous option?
765 debug
!("Parser::is_new_arg: Starts new arg...");
766 let mut ret
= if arg_os
.starts_with(b
"--") {
768 if arg_os
.len_() == 2 {
769 return true; // We have to return true so override everything else
772 } else if arg_os
.starts_with(b
"-") {
774 // a singe '-' by itself is a value and typically means "stdin" on unix systems
775 !(arg_os
.len_() == 1)
777 sdebugln
!("Probable value");
781 ret
= ret
&& !arg_allows_tac
;
783 debugln
!("Parser::is_new_arg: Starts new arg...{:?}", ret
);
787 // The actual parsing function
788 #[cfg_attr(feature = "lints", allow(while_let_on_iterator, collapsible_if))]
789 pub fn get_matches_with
<I
, T
>(&mut self,
790 matcher
: &mut ArgMatcher
<'a
>,
791 it
: &mut Peekable
<I
>)
793 where I
: Iterator
<Item
= T
>,
794 T
: Into
<OsString
> + Clone
796 debugln
!("Parser::get_matches_with;");
797 // Verify all positional assertions pass
798 self.verify_positionals();
800 // Next we create the `--help` and `--version` arguments and add them if
802 self.create_help_and_version();
804 let mut subcmd_name
: Option
<String
> = None
;
805 let mut needs_val_of
: Option
<&'a
str> = None
;
806 let mut pos_counter
= 1;
807 while let Some(arg
) = it
.next() {
808 let arg_os
= arg
.into();
809 debugln
!("Parser::get_matches_with: Begin parsing '{:?}' ({:?})", arg_os
, &*arg_os
.as_bytes());
811 self.valid_neg_num
= false;
812 // Is this a new argument, or values from a previous option?
813 let starts_new_arg
= self.is_new_arg(&arg_os
, needs_val_of
);
815 // Has the user already passed '--'? Meaning only positional args follow
816 if !self.trailing_vals
{
817 // Does the arg match a subcommand name, or any of it's aliases (if defined)
818 if self.possible_subcommand(&arg_os
) {
819 if &*arg_os
== "help" && self.is_set(AppSettings
::NeedsSubcommandHelp
) {
820 try
!(self.parse_help_subcommand(it
));
822 subcmd_name
= Some(arg_os
.to_str().expect(INVALID_UTF8
).to_owned());
827 if let Some(name
) = needs_val_of
{
828 // Check to see if parsing a value from a previous arg
829 if let Some(arg
) = find_by_name
!(self, &name
, opts
, iter
) {
830 // get the OptBuilder so we can check the settings
831 needs_val_of
= try
!(self.add_val_to_arg(&*arg
, &arg_os
, matcher
));
832 // get the next value from the iterator
837 if arg_os
.starts_with(b
"--") {
838 if arg_os
.len_() == 2 {
839 // The user has passed '--' which means only positional args follow no
840 // matter what they start with
841 self.trailing_vals
= true;
845 needs_val_of
= try
!(self.parse_long_arg(matcher
, &arg_os
));
846 if !(needs_val_of
.is_none() && self.is_set(AppSettings
::AllowLeadingHyphen
)) {
849 } else if arg_os
.starts_with(b
"-") && arg_os
.len_() != 1 {
850 // Try to parse short args like normal, if AllowLeadingHyphen or
851 // AllowNegativeNumbers is set, parse_short_arg will *not* throw
852 // an error, and instead return Ok(None)
853 needs_val_of
= try
!(self.parse_short_arg(matcher
, &arg_os
));
854 // If it's None, we then check if one of those two AppSettings was set
855 if needs_val_of
.is_none() {
856 if self.is_set(AppSettings
::AllowNegativeNumbers
) {
857 if !(arg_os
.to_string_lossy().parse
::<i64>().is_ok() ||
858 arg_os
.to_string_lossy().parse
::<f64>().is_ok()) {
859 return Err(Error
::unknown_argument(&*arg_os
.to_string_lossy(),
861 &*self.create_current_usage(matcher
, None
),
864 } else if !self.is_set(AppSettings
::AllowLeadingHyphen
) {
873 if !self.is_set(AppSettings
::ArgsNegateSubcommands
) {
875 suggestions
::did_you_mean(&*arg_os
.to_string_lossy(),
878 .map(|s
| &s
.p
.meta
.name
)) {
879 return Err(Error
::invalid_subcommand(arg_os
.to_string_lossy().into_owned(),
884 .unwrap_or(&self.meta
.name
),
885 &*self.create_current_usage(matcher
, None
),
891 let low_index_mults
= self.is_set(AppSettings
::LowIndexMultiplePositional
) &&
892 !self.positionals
.is_empty() &&
893 pos_counter
== (self.positionals
.len() - 1);
894 let missing_pos
= self.is_set(AppSettings
::AllowMissingPositional
) &&
895 !self.positionals
.is_empty() &&
896 pos_counter
== (self.positionals
.len() - 1);
897 debugln
!("Parser::get_matches_with: Low index multiples...{:?}", low_index_mults
);
898 debugln
!("Parser::get_matches_with: Positional counter...{}", pos_counter
);
899 if low_index_mults
|| missing_pos
{
900 if let Some(na
) = it
.peek() {
901 let n
= (*na
).clone().into();
902 needs_val_of
= if needs_val_of
.is_none() {
903 if let Some(p
) = self.positionals
.get(pos_counter
) {
911 if self.is_new_arg(&n
, needs_val_of
) || self.possible_subcommand(&n
) ||
912 suggestions
::did_you_mean(&n
.to_string_lossy(),
915 .map(|s
| &s
.p
.meta
.name
))
917 debugln
!("Parser::get_matches_with: Bumping the positional counter...");
921 debugln
!("Parser::get_matches_with: Bumping the positional counter...");
925 if let Some(p
) = self.positionals
.get(pos_counter
) {
926 parse_positional
!(self, p
, arg_os
, pos_counter
, matcher
);
927 self.valid_arg
= true;
928 } else if self.settings
.is_set(AppSettings
::AllowExternalSubcommands
) {
929 // Get external subcommand name
930 let sc_name
= match arg_os
.to_str() {
931 Some(s
) => s
.to_string(),
933 if !self.settings
.is_set(AppSettings
::StrictUtf8
) {
934 return Err(Error
::invalid_utf8(&*self.create_current_usage(matcher
, None
),
937 arg_os
.to_string_lossy().into_owned()
941 // Collect the external subcommand args
942 let mut sc_m
= ArgMatcher
::new();
943 while let Some(v
) = it
.next() {
945 if a
.to_str().is_none() && !self.settings
.is_set(AppSettings
::StrictUtf8
) {
946 return Err(Error
::invalid_utf8(&*self.create_current_usage(matcher
, None
),
949 sc_m
.add_val_to("", &a
);
952 matcher
.subcommand(SubCommand
{
954 matches
: sc_m
.into(),
956 } else if !(self.is_set(AppSettings
::AllowLeadingHyphen
) ||
957 self.is_set(AppSettings
::AllowNegativeNumbers
)) {
958 return Err(Error
::unknown_argument(&*arg_os
.to_string_lossy(),
960 &*self.create_current_usage(matcher
, None
),
965 if let Some(ref pos_sc_name
) = subcmd_name
{
966 // is this is a real subcommand, or an alias
967 if self.subcommands
.iter().any(|sc
| &sc
.p
.meta
.name
== pos_sc_name
) {
968 try
!(self.parse_subcommand(&*pos_sc_name
, matcher
, it
));
970 let sc_name
= &*self.subcommands
972 .filter(|sc
| sc
.p
.meta
.aliases
.is_some())
978 .expect(INTERNAL_ERROR_MSG
)
980 .any(|&(a
, _
)| &a
== &&*pos_sc_name
)
982 .map(|sc
| sc
.p
.meta
.name
.clone())
984 .expect(INTERNAL_ERROR_MSG
);
985 try
!(self.parse_subcommand(sc_name
, matcher
, it
));
987 } else if self.is_set(AppSettings
::SubcommandRequired
) {
988 let bn
= self.meta
.bin_name
.as_ref().unwrap_or(&self.meta
.name
);
989 return Err(Error
::missing_subcommand(bn
,
990 &self.create_current_usage(matcher
, None
),
992 } else if self.is_set(AppSettings
::SubcommandRequiredElseHelp
) {
993 debugln
!("parser::get_matches_with: SubcommandRequiredElseHelp=true");
994 let mut out
= vec
![];
995 try
!(self.write_help_err(&mut out
));
997 message
: String
::from_utf8_lossy(&*out
).into_owned(),
998 kind
: ErrorKind
::MissingArgumentOrSubcommand
,
1003 self.validate(needs_val_of
, subcmd_name
, matcher
)
1006 fn validate(&mut self,
1007 needs_val_of
: Option
<&'a
str>,
1008 subcmd_name
: Option
<String
>,
1009 matcher
: &mut ArgMatcher
<'a
>)
1011 debugln
!("Parser::validate;");
1012 let mut reqs_validated
= false;
1013 try
!(self.add_defaults(matcher
));
1014 if let Some(a
) = needs_val_of
{
1015 debugln
!("Parser::validate: needs_val_of={:?}", a
);
1016 if let Some(o
) = find_by_name
!(self, &a
, opts
, iter
) {
1017 try
!(self.validate_required(matcher
));
1018 reqs_validated
= true;
1019 let should_err
= if let Some(v
) = matcher
.0.args
.get(&*o
.b
.name
) {
1020 v
.vals
.is_empty() && !(o
.v
.min_vals
.is_some() && o
.v
.min_vals
.unwrap() == 0)
1025 return Err(Error
::empty_value(o
,
1026 &*self.create_current_usage(matcher
, None
),
1032 try
!(self.validate_blacklist(matcher
));
1033 if !(self.settings
.is_set(AppSettings
::SubcommandsNegateReqs
) && subcmd_name
.is_some()) &&
1035 try
!(self.validate_required(matcher
));
1037 try
!(self.validate_matched_args(matcher
));
1038 matcher
.usage(self.create_usage(&[]));
1040 if matcher
.is_empty() && matcher
.subcommand_name().is_none() &&
1041 self.is_set(AppSettings
::ArgRequiredElseHelp
) {
1042 let mut out
= vec
![];
1043 try
!(self.write_help_err(&mut out
));
1045 message
: String
::from_utf8_lossy(&*out
).into_owned(),
1046 kind
: ErrorKind
::MissingArgumentOrSubcommand
,
1053 fn propogate_help_version(&mut self) {
1054 debugln
!("Parser::propogate_help_version;");
1055 self.create_help_and_version();
1056 for sc
in &mut self.subcommands
{
1057 sc
.p
.propogate_help_version();
1061 fn build_bin_names(&mut self) {
1062 debugln
!("Parser::build_bin_names;");
1063 for sc
in &mut self.subcommands
{
1064 debug
!("Parser::build_bin_names:iter: bin_name set...");
1065 if sc
.p
.meta
.bin_name
.is_none() {
1067 let bin_name
= format
!("{}{}{}",
1071 .unwrap_or(&self.meta
.name
.clone()),
1072 if self.meta
.bin_name
.is_some() {
1078 debugln
!("Parser::build_bin_names:iter: Setting bin_name of {} to {}", self.meta
.name
, bin_name
);
1079 sc
.p
.meta
.bin_name
= Some(bin_name
);
1081 sdebugln
!("yes ({:?})", sc
.p
.meta
.bin_name
);
1083 debugln
!("Parser::build_bin_names:iter: Calling build_bin_names from...{}", sc
.p
.meta
.name
);
1084 sc
.p
.build_bin_names();
1088 fn parse_subcommand
<I
, T
>(&mut self,
1090 matcher
: &mut ArgMatcher
<'a
>,
1091 it
: &mut Peekable
<I
>)
1093 where I
: Iterator
<Item
= T
>,
1094 T
: Into
<OsString
> + Clone
1096 use std
::fmt
::Write
;
1097 debugln
!("Parser::parse_subcommand;");
1098 let mut mid_string
= String
::new();
1099 if !self.settings
.is_set(AppSettings
::SubcommandsNegateReqs
) {
1100 let mut hs
: Vec
<&str> = self.required
.iter().map(|n
| &**n
).collect();
1101 for k
in matcher
.arg_names() {
1104 let reqs
= self.get_required_from(&hs
, Some(matcher
), None
);
1107 write
!(&mut mid_string
, " {}", s
).expect(INTERNAL_ERROR_MSG
);
1110 mid_string
.push_str(" ");
1111 if let Some(ref mut sc
) = self.subcommands
1113 .find(|s
| &s
.p
.meta
.name
== &sc_name
) {
1114 let mut sc_matcher
= ArgMatcher
::new();
1115 // bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by
1117 sc
.p
.meta
.usage
= Some(format
!("{}{}{}",
1118 self.meta
.bin_name
.as_ref().unwrap_or(&String
::new()),
1119 if self.meta
.bin_name
.is_some() {
1125 sc
.p
.meta
.bin_name
= Some(format
!("{}{}{}",
1129 .unwrap_or(&String
::new()),
1130 if self.meta
.bin_name
.is_some() {
1136 debugln
!("Parser::parse_subcommand: About to parse sc={}", sc
.p
.meta
.name
);
1137 debugln
!("Parser::parse_subcommand: sc settings={:#?}", sc
.p
.settings
);
1138 try
!(sc
.p
.get_matches_with(&mut sc_matcher
, it
));
1139 matcher
.subcommand(SubCommand
{
1140 name
: sc
.p
.meta
.name
.clone(),
1141 matches
: sc_matcher
.into(),
1148 fn groups_for_arg(&self, name
: &str) -> Option
<Vec
<&'a
str>> {
1149 debugln
!("Parser::groups_for_arg: name={}", name
);
1151 if self.groups
.is_empty() {
1152 debugln
!("Parser::groups_for_arg: No groups defined");
1155 let mut res
= vec
![];
1156 debugln
!("Parser::groups_for_arg: Searching through groups...");
1157 for (gn
, grp
) in &self.groups
{
1158 for a
in &grp
.args
{
1160 sdebugln
!("\tFound '{}'", gn
);
1172 fn args_in_group(&self, group
: &str) -> Vec
<String
> {
1173 let mut g_vec
= vec
![];
1174 let mut args
= vec
![];
1176 for n
in &self.groups
[group
].args
{
1177 if let Some(f
) = self.flags
.iter().find(|f
| &f
.b
.name
== n
) {
1178 args
.push(f
.to_string());
1179 } else if let Some(f
) = self.opts
.iter().find(|o
| &o
.b
.name
== n
) {
1180 args
.push(f
.to_string());
1181 } else if self.groups
.contains_key(&**n
) {
1183 } else if let Some(p
) = self.positionals
1185 .find(|p
| &p
.b
.name
== n
) {
1186 args
.push(p
.b
.name
.to_owned());
1190 for av
in g_vec
.iter().map(|g
| self.args_in_group(g
)) {
1194 args
.iter().map(ToOwned
::to_owned
).collect()
1197 fn arg_names_in_group(&self, group
: &str) -> Vec
<&'a
str> {
1198 let mut g_vec
= vec
![];
1199 let mut args
= vec
![];
1201 for n
in &self.groups
[group
].args
{
1202 if self.groups
.contains_key(&*n
) {
1209 for av
in g_vec
.iter().map(|g
| self.arg_names_in_group(g
)) {
1213 args
.iter().map(|s
| *s
).collect()
1216 pub fn create_help_and_version(&mut self) {
1217 debugln
!("Parser::create_help_and_version;");
1218 // name is "hclap_help" because flags are sorted by name
1219 if self.is_set(AppSettings
::NeedsLongHelp
) {
1220 debugln
!("Parser::create_help_and_version: Building --help");
1221 if self.help_short
.is_none() && !self.short_list
.contains(&'h'
) {
1222 self.help_short
= Some('h'
);
1224 let id
= self.flags
.len();
1225 let arg
= FlagBuilder
{
1228 help
: Some("Prints help information"),
1230 ..Default
::default()
1233 short
: self.help_short
,
1235 ..Default
::default()
1238 if let Some(h
) = self.help_short
{
1239 self.short_list
.push(h
);
1241 self.long_list
.push("help");
1242 self.flags
.insert(id
, arg
);
1244 if !self.settings
.is_set(AppSettings
::DisableVersion
) &&
1245 self.is_set(AppSettings
::NeedsLongVersion
) {
1246 debugln
!("Parser::create_help_and_version: Building --version");
1247 if self.version_short
.is_none() && !self.short_list
.contains(&'V'
) {
1248 self.version_short
= Some('V'
);
1250 let id
= self.flags
.len();
1251 // name is "vclap_version" because flags are sorted by name
1252 let arg
= FlagBuilder
{
1254 name
: "vclap_version",
1255 help
: Some("Prints version information"),
1257 ..Default
::default()
1260 short
: self.version_short
,
1261 long
: Some("version"),
1262 ..Default
::default()
1265 if let Some(v
) = self.version_short
{
1266 self.short_list
.push(v
);
1268 self.long_list
.push("version");
1269 self.flags
.insert(id
, arg
);
1271 if !self.subcommands
.is_empty() && !self.is_set(AppSettings
::DisableHelpSubcommand
) &&
1272 self.is_set(AppSettings
::NeedsSubcommandHelp
) {
1273 debugln
!("Parser::create_help_and_version: Building help");
1275 .push(App
::new("help")
1276 .about("Prints this message or the help of the given subcommand(s)"));
1280 // Retrieves the names of all args the user has supplied thus far, except required ones
1281 // because those will be listed in self.required
1282 pub fn create_current_usage(&self, matcher
: &'b ArgMatcher
<'a
>, extra
: Option
<&str>) -> String
{
1283 let mut args
: Vec
<_
> = matcher
.arg_names()
1286 if let Some(o
) = find_by_name
!(self, *n
, opts
, iter
) {
1287 !o
.b
.settings
.is_set(ArgSettings
::Required
)
1288 } else if let Some(p
) = find_by_name
!(self, *n
, positionals
, values
) {
1289 !p
.b
.settings
.is_set(ArgSettings
::Required
)
1291 true // flags can't be required, so they're always true
1296 if let Some(r
) = extra
{
1299 self.create_usage(&*args
)
1302 fn check_for_help_and_version_str(&self, arg
: &OsStr
) -> ClapResult
<()> {
1303 debugln
!("Parser::check_for_help_and_version_str;");
1304 debug
!("Parser::check_for_help_and_version_str: Checking if --{} is help or version...",
1305 arg
.to_str().unwrap());
1306 if arg
== "help" && self.settings
.is_set(AppSettings
::NeedsLongHelp
) {
1310 if arg
== "version" && self.settings
.is_set(AppSettings
::NeedsLongVersion
) {
1311 sdebugln
!("Version");
1312 try
!(self._version());
1314 sdebugln
!("Neither");
1319 fn check_for_help_and_version_char(&self, arg
: char) -> ClapResult
<()> {
1320 debugln
!("Parser::check_for_help_and_version_char;");
1321 debug
!("Parser::check_for_help_and_version_char: Checking if -{} is help or version...", arg
);
1322 if let Some(h
) = self.help_short
{
1323 if arg
== h
&& self.settings
.is_set(AppSettings
::NeedsLongHelp
) {
1328 if let Some(v
) = self.version_short
{
1329 if arg
== v
&& self.settings
.is_set(AppSettings
::NeedsLongVersion
) {
1330 sdebugln
!("Version");
1331 try
!(self._version());
1334 sdebugln
!("Neither");
1338 fn _help(&self) -> ClapResult
<()> {
1339 let mut buf
= vec
![];
1340 try
!(Help
::write_parser_help(&mut buf
, self));
1342 message
: unsafe { String::from_utf8_unchecked(buf) }
,
1343 kind
: ErrorKind
::HelpDisplayed
,
1348 fn _version(&self) -> ClapResult
<()> {
1349 let out
= io
::stdout();
1350 let mut buf_w
= BufWriter
::new(out
.lock());
1351 try
!(self.print_version(&mut buf_w
));
1353 message
: String
::new(),
1354 kind
: ErrorKind
::VersionDisplayed
,
1359 fn parse_long_arg(&mut self,
1360 matcher
: &mut ArgMatcher
<'a
>,
1362 -> ClapResult
<Option
<&'a
str>> {
1363 // maybe here lifetime should be 'a
1364 debugln
!("Parser::parse_long_arg;");
1366 debug
!("Parser::parse_long_arg: Does it contain '='...");
1367 let arg
= if full_arg
.contains_byte(b'
='
) {
1368 let (p0
, p1
) = full_arg
.trim_left_matches(b'
-'
).split_at_byte(b'
='
);
1369 sdebugln
!("Yes '{:?}'", p1
);
1374 full_arg
.trim_left_matches(b'
-'
)
1377 if let Some(opt
) = find_by_long
!(self, &arg
, opts
) {
1378 debugln
!("Parser::parse_long_arg: Found valid opt '{}'", opt
.to_string());
1379 self.valid_arg
= true;
1380 let ret
= try
!(self.parse_opt(val
, opt
, matcher
));
1381 arg_post_processing
!(self, opt
, matcher
);
1384 } else if let Some(flag
) = find_by_long
!(self, &arg
, flags
) {
1385 debugln
!("Parser::parse_long_arg: Found valid flag '{}'", flag
.to_string());
1386 self.valid_arg
= true;
1387 // Only flags could be help or version, and we need to check the raw long
1388 // so this is the first point to check
1389 try
!(self.check_for_help_and_version_str(arg
));
1391 try
!(self.parse_flag(flag
, matcher
));
1393 // Handle conflicts, requirements, etc.
1394 arg_post_processing
!(self, flag
, matcher
);
1397 } else if self.is_set(AppSettings
::AllowLeadingHyphen
) {
1399 } else if self.valid_neg_num
{
1403 debugln
!("Parser::parse_long_arg: Didn't match anything");
1404 self.did_you_mean_error(arg
.to_str().expect(INVALID_UTF8
), matcher
).map(|_
| None
)
1407 fn parse_short_arg(&mut self,
1408 matcher
: &mut ArgMatcher
<'a
>,
1410 -> ClapResult
<Option
<&'a
str>> {
1411 debugln
!("Parser::parse_short_arg;");
1412 // let mut utf8 = true;
1413 let arg_os
= full_arg
.trim_left_matches(b'
-'
);
1414 let arg
= arg_os
.to_string_lossy();
1416 // If AllowLeadingHyphen is set, we want to ensure `-val` gets parsed as `-val` and not `-v` `-a` `-l` assuming
1417 // `v` `a` and `l` are all, or mostly, valid shorts.
1418 if self.is_set(AppSettings
::AllowLeadingHyphen
) {
1419 let mut good
= true;
1420 for c
in arg
.chars() {
1421 good
= self.short_list
.contains(&c
);
1426 } else if self.valid_neg_num
{
1427 // TODO: Add docs about having AllowNegativeNumbers and `-2` as a valid short
1428 // May be better to move this to *after* not finding a valid flag/opt?
1429 debugln
!("Parser::parse_short_arg: Valid negative num...");
1433 for c
in arg
.chars() {
1434 debugln
!("Parser::parse_short_arg:iter: short={}", c
);
1435 // Check for matching short options, and return the name if there is no trailing
1436 // concatenated value: -oval
1439 if let Some(opt
) = self.opts
1441 .find(|&o
| o
.s
.short
.is_some() && o
.s
.short
.unwrap() == c
) {
1442 debugln
!("Parser::parse_short_arg:iter: Found valid short opt -{} in '{}'", c
, arg
);
1443 self.valid_arg
= true;
1444 // Check for trailing concatenated value
1445 let p
: Vec
<_
> = arg
.splitn(2, c
).collect();
1446 debugln
!("Parser::parse_short_arg:iter: arg: {:?}, arg_os: {:?}, full_arg: {:?}",
1450 debugln
!("Parser::parse_short_arg:iter: p[0]: {:?}, p[1]: {:?}", p
[0].as_bytes(), p
[1].as_bytes());
1451 let i
= p
[0].as_bytes().len() + 1;
1452 let val
= if p
[1].as_bytes().len() > 0 {
1453 debugln
!("Parser::parse_short_arg:iter: setting val: {:?} (bytes), {:?} (ascii)",
1454 arg_os
.split_at(i
).1.as_bytes(),
1455 arg_os
.split_at(i
).1);
1456 Some(arg_os
.split_at(i
).1)
1461 // Default to "we're expecting a value later"
1462 let ret
= try
!(self.parse_opt(val
, opt
, matcher
));
1464 arg_post_processing
!(self, opt
, matcher
);
1467 } else if let Some(flag
) = self.flags
1469 .find(|&f
| f
.s
.short
.is_some() && f
.s
.short
.unwrap() == c
) {
1470 debugln
!("Parser::parse_short_arg:iter: Found valid short flag -{}", c
);
1471 self.valid_arg
= true;
1472 // Only flags can be help or version
1473 try
!(self.check_for_help_and_version_char(c
));
1474 try
!(self.parse_flag(flag
, matcher
));
1475 // Handle conflicts, requirements, overrides, etc.
1476 // Must be called here due to mutablilty
1477 arg_post_processing
!(self, flag
, matcher
);
1479 let mut arg
= String
::new();
1482 return Err(Error
::unknown_argument(&*arg
,
1484 &*self.create_current_usage(matcher
, None
),
1492 val
: Option
<&OsStr
>,
1493 opt
: &OptBuilder
<'a
, 'b
>,
1494 matcher
: &mut ArgMatcher
<'a
>)
1495 -> ClapResult
<Option
<&'a
str>> {
1496 debugln
!("Parser::parse_opt;");
1497 validate_multiples
!(self, opt
, matcher
);
1498 let mut has_eq
= false;
1500 debug
!("Parser::parse_optChecking for val...");
1501 if let Some(fv
) = val
{
1502 has_eq
= fv
.starts_with(&[b'
='
]);
1503 let v
= fv
.trim_left_matches(b'
='
);
1504 if !opt
.is_set(ArgSettings
::EmptyValues
) && v
.len_() == 0 {
1505 sdebugln
!("Found Empty - Error");
1506 return Err(Error
::empty_value(opt
,
1507 &*self.create_current_usage(matcher
, None
),
1510 sdebugln
!("Found - {:?}, len: {}", v
, v
.len_());
1511 debugln
!("Parser::parse_opt: {:?} contains '='...{:?}", fv
, fv
.starts_with(&[b'
='
]));
1512 try
!(self.add_val_to_arg(opt
, v
, matcher
));
1517 matcher
.inc_occurrence_of(opt
.b
.name
);
1518 // Increment or create the group "args"
1519 self.groups_for_arg(opt
.b
.name
).and_then(|vec
| Some(matcher
.inc_occurrences_of(&*vec
)));
1523 (opt
.is_set(ArgSettings
::Multiple
) && !opt
.is_set(ArgSettings
::RequireDelimiter
) &&
1524 matcher
.needs_more_vals(opt
)) {
1525 debugln
!("Parser::parse_opt: More arg vals required...");
1526 return Ok(Some(opt
.b
.name
));
1528 debugln
!("Parser::parse_opt: More arg vals not required...");
1532 fn add_val_to_arg
<A
>(&self,
1535 matcher
: &mut ArgMatcher
<'a
>)
1536 -> ClapResult
<Option
<&'a
str>>
1537 where A
: AnyArg
<'a
, 'b
> + Display
1539 debugln
!("Parser::add_val_to_arg;");
1541 if !(self.trailing_vals
&& self.is_set(AppSettings
::DontDelimitTrailingValues
)) {
1542 if let Some(delim
) = arg
.val_delim() {
1543 if val
.is_empty_() {
1544 ret
= try
!(self.add_single_val_to_arg(arg
, val
, matcher
));
1546 for v
in val
.split(delim
as u32 as u8) {
1547 ret
= try
!(self.add_single_val_to_arg(arg
, v
, matcher
));
1549 // If there was a delimiter used, we're not looking for more values
1550 if val
.contains_byte(delim
as u32 as u8) ||
1551 arg
.is_set(ArgSettings
::RequireDelimiter
) {
1556 ret
= try
!(self.add_single_val_to_arg(arg
, val
, matcher
));
1559 ret
= try
!(self.add_single_val_to_arg(arg
, val
, matcher
));
1564 fn add_single_val_to_arg
<A
>(&self,
1567 matcher
: &mut ArgMatcher
<'a
>)
1568 -> ClapResult
<Option
<&'a
str>>
1569 where A
: AnyArg
<'a
, 'b
> + Display
1571 debugln
!("Parser::add_single_val_to_arg;");
1572 debugln
!("Parser::add_single_val_to_arg: adding val...{:?}", v
);
1573 if let Some(t
) = arg
.val_terminator() {
1578 matcher
.add_val_to(arg
.name(), v
);
1580 // Increment or create the group "args"
1581 if let Some(grps
) = self.groups_for_arg(arg
.name()) {
1583 matcher
.add_val_to(&*grp
, v
);
1587 // The validation must come AFTER inserting into 'matcher' or the usage string
1589 self.validate_value(arg
, v
, matcher
)
1592 fn validate_value
<A
>(&self,
1595 matcher
: &ArgMatcher
<'a
>)
1596 -> ClapResult
<Option
<&'a
str>>
1597 where A
: AnyArg
<'a
, 'b
> + Display
1599 debugln
!("Parser::validate_value: val={:?}", val
);
1600 if self.is_set(AppSettings
::StrictUtf8
) && val
.to_str().is_none() {
1601 return Err(Error
::invalid_utf8(&*self.create_current_usage(matcher
, None
), self.color()));
1603 if let Some(p_vals
) = arg
.possible_vals() {
1604 let val_str
= val
.to_string_lossy();
1605 if !p_vals
.contains(&&*val_str
) {
1606 return Err(Error
::invalid_value(val_str
,
1609 &*self.create_current_usage(matcher
, None
),
1613 if !arg
.is_set(ArgSettings
::EmptyValues
) && val
.is_empty_() &&
1614 matcher
.contains(&*arg
.name()) {
1615 return Err(Error
::empty_value(arg
, &*self.create_current_usage(matcher
, None
), self.color()));
1617 if let Some(vtor
) = arg
.validator() {
1618 if let Err(e
) = vtor(val
.to_string_lossy().into_owned()) {
1619 return Err(Error
::value_validation(Some(arg
), e
, self.color()));
1622 if let Some(vtor
) = arg
.validator_os() {
1623 if let Err(e
) = vtor(val
) {
1624 return Err(Error
::value_validation(Some(arg
),
1625 (*e
).to_string_lossy().to_string(),
1629 if matcher
.needs_more_vals(arg
) {
1630 return Ok(Some(arg
.name()));
1635 fn parse_flag(&self,
1636 flag
: &FlagBuilder
<'a
, 'b
>,
1637 matcher
: &mut ArgMatcher
<'a
>)
1639 debugln
!("Parser::parse_flag;");
1640 validate_multiples
!(self, flag
, matcher
);
1642 matcher
.inc_occurrence_of(flag
.b
.name
);
1643 // Increment or create the group "args"
1644 self.groups_for_arg(flag
.b
.name
).and_then(|vec
| Some(matcher
.inc_occurrences_of(&*vec
)));
1649 fn validate_blacklist(&self, matcher
: &mut ArgMatcher
) -> ClapResult
<()> {
1650 debugln
!("Parser::validate_blacklist: blacklist={:?}", self.blacklist
);
1651 macro_rules
! build_err
{
1652 ($me
:ident
, $name
:expr
, $matcher
:ident
) => ({
1653 debugln
!("build_err!: name={}", $name
);
1654 let mut c_with
= find_from
!($me
, $name
, blacklist
, &$matcher
);
1656 $me
.find_any_arg($name
).map_or(None
, |aa
| aa
.blacklist())
1657 .map_or(None
, |bl
| bl
.iter().find(|arg
| $matcher
.contains(arg
)))
1658 .map_or(None
, |an
| $me
.find_any_arg(an
))
1659 .map_or(None
, |aa
| Some(format
!("{}", aa
)))
1661 debugln
!("build_err!: '{:?}' conflicts with '{}'", c_with
, $name
);
1662 $matcher
.remove($name
);
1663 let usg
= $me
.create_current_usage($matcher
, None
);
1664 if let Some(f
) = find_by_name
!($me
, $name
, flags
, iter
) {
1665 debugln
!("build_err!: It was a flag...");
1666 Error
::argument_conflict(f
, c_with
, &*usg
, self.color())
1667 } else if let Some(o
) = find_by_name
!($me
, $name
, opts
, iter
) {
1668 debugln
!("build_err!: It was an option...");
1669 Error
::argument_conflict(o
, c_with
, &*usg
, self.color())
1671 match find_by_name
!($me
, $name
, positionals
, values
) {
1673 debugln
!("build_err!: It was a positional...");
1674 Error
::argument_conflict(p
, c_with
, &*usg
, self.color())
1676 None
=> panic
!(INTERNAL_ERROR_MSG
)
1682 for name
in &self.blacklist
{
1683 debugln
!("Parser::validate_blacklist:iter: Checking blacklisted name: {}", name
);
1684 if self.groups
.contains_key(name
) {
1685 debugln
!("Parser::validate_blacklist:iter: groups contains it...");
1686 for n
in self.arg_names_in_group(name
) {
1687 debugln
!("Parser::validate_blacklist:iter:iter: Checking arg '{}' in group...", n
);
1688 if matcher
.contains(n
) {
1689 debugln
!("Parser::validate_blacklist:iter:iter: matcher contains it...");
1690 return Err(build_err
!(self, &n
, matcher
));
1693 } else if matcher
.contains(name
) {
1694 debugln
!("Parser::validate_blacklist:iter: matcher contains it...");
1695 return Err(build_err
!(self, name
, matcher
));
1701 fn validate_matched_args(&self, matcher
: &mut ArgMatcher
) -> ClapResult
<()> {
1702 debugln
!("Parser::validate_matched_args;");
1703 for (name
, ma
) in matcher
.iter() {
1704 debugln
!("Parser::validate_matched_args:iter: name={}", name
);
1705 if let Some(opt
) = find_by_name
!(self, name
, opts
, iter
) {
1706 try
!(self.validate_arg_num_vals(opt
, ma
, matcher
));
1707 try
!(self.validate_arg_requires(opt
, ma
, matcher
));
1708 } else if let Some(flag
) = find_by_name
!(self, name
, flags
, iter
) {
1710 try
!(self.validate_arg_requires(flag
, ma
, matcher
));
1711 } else if let Some(pos
) = find_by_name
!(self, name
, positionals
, values
) {
1712 try
!(self.validate_arg_num_vals(pos
, ma
, matcher
));
1713 try
!(self.validate_arg_requires(pos
, ma
, matcher
));
1714 } else if let Some(grp
) = self.groups
.get(name
) {
1715 if let Some(ref g_reqs
) = grp
.requires
{
1716 if g_reqs
.iter().any(|&n
| !matcher
.contains(n
)) {
1717 return self.missing_required_error(matcher
, None
);
1725 fn validate_arg_num_vals
<A
>(&self,
1728 matcher
: &ArgMatcher
)
1730 where A
: AnyArg
<'a
, 'b
> + Display
1732 debugln
!("Parser::validate_arg_num_vals;");
1733 if let Some(num
) = a
.num_vals() {
1734 debugln
!("Parser::validate_arg_num_vals: num_vals set...{}", num
);
1735 let should_err
= if a
.is_set(ArgSettings
::Multiple
) {
1736 ((ma
.vals
.len() as u64) % num
) != 0
1738 num
!= (ma
.vals
.len() as u64)
1741 debugln
!("Parser::validate_arg_num_vals: Sending error WrongNumberOfValues");
1742 return Err(Error
::wrong_number_of_values(a
,
1744 if a
.is_set(ArgSettings
::Multiple
) {
1745 (ma
.vals
.len() % num
as usize)
1749 if ma
.vals
.len() == 1 ||
1750 (a
.is_set(ArgSettings
::Multiple
) &&
1751 (ma
.vals
.len() % num
as usize) ==
1757 &*self.create_current_usage(matcher
, None
),
1761 if let Some(num
) = a
.max_vals() {
1762 debugln
!("Parser::validate_arg_num_vals: max_vals set...{}", num
);
1763 if (ma
.vals
.len() as u64) > num
{
1764 debugln
!("Parser::validate_arg_num_vals: Sending error TooManyValues");
1765 return Err(Error
::too_many_values(ma
.vals
1769 .expect(INTERNAL_ERROR_MSG
))
1770 .expect(INTERNAL_ERROR_MSG
)
1772 .expect(INVALID_UTF8
),
1774 &*self.create_current_usage(matcher
, None
),
1778 if let Some(num
) = a
.min_vals() {
1779 debugln
!("Parser::validate_arg_num_vals: min_vals set: {}", num
);
1780 if (ma
.vals
.len() as u64) < num
{
1781 debugln
!("Parser::validate_arg_num_vals: Sending error TooFewValues");
1782 return Err(Error
::too_few_values(a
,
1785 &*self.create_current_usage(matcher
, None
),
1789 // Issue 665 (https://github.com/kbknapp/clap-rs/issues/665)
1790 if a
.takes_value() && !a
.is_set(ArgSettings
::EmptyValues
) && ma
.vals
.is_empty() {
1791 return Err(Error
::empty_value(a
, &*self.create_current_usage(matcher
, None
), self.color()));
1796 fn validate_arg_requires
<A
>(&self,
1799 matcher
: &ArgMatcher
)
1801 where A
: AnyArg
<'a
, 'b
> + Display
1803 debugln
!("Parser::validate_arg_requires;");
1804 if let Some(a_reqs
) = a
.requires() {
1805 for &(val
, name
) in a_reqs
.iter().filter(|&&(val
, _
)| val
.is_some()) {
1808 .any(|v
| v
== val
.expect(INTERNAL_ERROR_MSG
) && !matcher
.contains(name
)) {
1809 return self.missing_required_error(matcher
, None
);
1817 fn missing_required_error(&self, matcher
: &ArgMatcher
, extra
: Option
<&str>) -> ClapResult
<()> {
1818 debugln
!("Parser::missing_required_error: extra={:?}", extra
);
1823 let mut reqs
= self.required
.iter().map(|&r
| &*r
).collect
::<Vec
<_
>>();
1824 if let Some(r
) = extra
{
1827 reqs
.retain(|n
| !matcher
.contains(n
));
1829 debugln
!("Parser::missing_required_error: reqs={:#?}", reqs
);
1830 Err(Error
::missing_required_argument(&*self.get_required_from(&reqs
[..],
1834 .fold(String
::new(), |acc
, s
| {
1835 acc
+ &format
!("\n {}", c
.error(s
))[..]
1837 &*self.create_current_usage(matcher
, extra
),
1841 fn validate_required(&self, matcher
: &ArgMatcher
) -> ClapResult
<()> {
1842 debugln
!("Parser::validate_required: required={:?};", self.required
);
1843 'outer
: for name
in &self.required
{
1844 debugln
!("Parser::validate_required:iter: name={}", name
);
1845 if matcher
.contains(name
) {
1848 if let Some(grp
) = self.groups
.get(name
) {
1849 for arg
in &grp
.args
{
1850 if matcher
.contains(arg
) {
1855 if self.groups
.values().any(|g
| g
.args
.contains(name
)) {
1858 if let Some(a
) = find_by_name
!(self, name
, flags
, iter
) {
1859 if self.is_missing_required_ok(a
, matcher
) {
1862 } else if let Some(a
) = find_by_name
!(self, name
, opts
, iter
) {
1863 if self.is_missing_required_ok(a
, matcher
) {
1866 } else if let Some(a
) = find_by_name
!(self, name
, positionals
, values
) {
1867 if self.is_missing_required_ok(a
, matcher
) {
1871 return self.missing_required_error(matcher
, None
);
1874 // Validate the conditionally required args
1875 for &(a
, v
, r
) in &self.r_ifs
{
1876 if let Some(ma
) = matcher
.get(a
) {
1877 for val
in ma
.vals
.values() {
1878 if v
== val
&& matcher
.get(r
).is_none() {
1879 return self.missing_required_error(matcher
, Some(r
));
1887 fn is_missing_required_ok
<A
>(&self, a
: &A
, matcher
: &ArgMatcher
) -> bool
1888 where A
: AnyArg
<'a
, 'b
>
1890 debugln
!("Parser::is_missing_required_ok: a={}", a
.name());
1891 if let Some(bl
) = a
.blacklist() {
1892 debugln
!("Parser::is_missing_required_ok: Conflicts found...{:?}", bl
);
1893 for n
in bl
.iter() {
1894 debugln
!("Parser::is_missing_required_ok:iter: conflict={}", n
);
1895 if matcher
.contains(n
) ||
1898 .map_or(false, |g
| g
.args
.iter().any(|an
| matcher
.contains(an
))) {
1903 if let Some(ru
) = a
.required_unless() {
1904 debugln
!("Parser::is_missing_required_ok: Required unless found...{:?}", ru
);
1905 let mut found_any
= false;
1906 for n
in ru
.iter() {
1907 debugln
!("Parser::is_missing_required_ok:iter: ru={}", n
);
1908 if matcher
.contains(n
) ||
1911 .map_or(false, |g
| g
.args
.iter().any(|an
| matcher
.contains(an
))) {
1912 if !a
.is_set(ArgSettings
::RequiredUnlessAll
) {
1913 debugln
!("Parser::is_missing_required_ok:iter: Doesn't require all...returning true");
1916 debugln
!("Parser::is_missing_required_ok:iter: Requires all...next");
1918 } else if a
.is_set(ArgSettings
::RequiredUnlessAll
) {
1919 debugln
!("Parser::is_missing_required_ok:iter: Not in matcher, or group and requires all...returning false");
1928 fn did_you_mean_error(&self, arg
: &str, matcher
: &mut ArgMatcher
<'a
>) -> ClapResult
<()> {
1929 // Didn't match a flag or option...maybe it was a typo and close to one
1931 suggestions
::did_you_mean_suffix(arg
,
1932 self.long_list
.iter(),
1933 suggestions
::DidYouMeanMessageStyle
::LongFlag
);
1935 // Add the arg to the matches to build a proper usage string
1936 if let Some(name
) = suffix
.1 {
1937 if let Some(opt
) = find_by_long
!(self, &name
, opts
) {
1938 self.groups_for_arg(&*opt
.b
.name
)
1939 .and_then(|grps
| Some(matcher
.inc_occurrences_of(&*grps
)));
1940 matcher
.insert(&*opt
.b
.name
);
1941 } else if let Some(flg
) = find_by_long
!(self, &name
, flags
) {
1942 self.groups_for_arg(&*flg
.b
.name
)
1943 .and_then(|grps
| Some(matcher
.inc_occurrences_of(&*grps
)));
1944 matcher
.insert(&*flg
.b
.name
);
1948 let used_arg
= format
!("--{}", arg
);
1949 Err(Error
::unknown_argument(&*used_arg
,
1951 &*self.create_current_usage(matcher
, None
),
1955 // Creates a usage string if one was not provided by the user manually. This happens just
1956 // after all arguments were parsed, but before any subcommands have been parsed
1957 // (so as to give subcommands their own usage recursively)
1958 pub fn create_usage(&self, used
: &[&str]) -> String
{
1959 debugln
!("Parser::create_usage;");
1960 let mut usage
= String
::with_capacity(75);
1961 usage
.push_str("USAGE:\n ");
1962 usage
.push_str(&self.create_usage_no_title(used
));
1966 // Creates a usage string (*without title*) if one was not provided by the user
1967 // manually. This happens just
1968 // after all arguments were parsed, but before any subcommands have been parsed
1969 // (so as to give subcommands their own usage recursively)
1970 pub fn create_usage_no_title(&self, used
: &[&str]) -> String
{
1971 debugln
!("Parser::create_usage_no_title;");
1972 let mut usage
= String
::with_capacity(75);
1973 if let Some(u
) = self.meta
.usage_str
{
1974 usage
.push_str(&*u
);
1975 } else if used
.is_empty() {
1976 usage
.push_str(&*self.meta
1979 .unwrap_or_else(|| self.meta
1982 .unwrap_or(&self.meta
.name
)));
1983 let mut reqs
: Vec
<&str> = self.required().map(|r
| &**r
).collect();
1985 let req_string
= self.get_required_from(&reqs
, None
, None
)
1987 .fold(String
::new(), |a
, s
| a
+ &format
!(" {}", s
)[..]);
1989 let flags
= self.needs_flags_tag();
1990 if flags
&& !self.is_set(AppSettings
::UnifiedHelpMessage
) {
1991 usage
.push_str(" [FLAGS]");
1993 usage
.push_str(" [OPTIONS]");
1995 if !self.is_set(AppSettings
::UnifiedHelpMessage
) && self.has_opts() &&
1996 self.opts
.iter().any(|o
| !o
.b
.settings
.is_set(ArgSettings
::Required
)) {
1997 usage
.push_str(" [OPTIONS]");
2000 usage
.push_str(&req_string
[..]);
2002 // places a '--' in the usage string if there are args and options
2003 // supporting multiple values
2004 if self.has_positionals() &&
2005 self.opts
.iter().any(|o
| o
.b
.settings
.is_set(ArgSettings
::Multiple
)) &&
2006 self.positionals
.values().any(|p
| !p
.b
.settings
.is_set(ArgSettings
::Required
)) &&
2007 !self.has_subcommands() {
2008 usage
.push_str(" [--]")
2010 if self.has_positionals() &&
2011 self.positionals
.values().any(|p
| !p
.b
.settings
.is_set(ArgSettings
::Required
)) {
2012 if let Some(args_tag
) = self.get_args_tag() {
2013 usage
.push_str(&*args_tag
);
2015 usage
.push_str(" [ARGS]");
2020 if self.has_subcommands() && !self.is_set(AppSettings
::SubcommandRequired
) {
2021 usage
.push_str(" [SUBCOMMAND]");
2022 } else if self.is_set(AppSettings
::SubcommandRequired
) && self.has_subcommands() {
2023 usage
.push_str(" <SUBCOMMAND>");
2026 self.smart_usage(&mut usage
, used
);
2029 usage
.shrink_to_fit();
2033 // Creates a context aware usage string, or "smart usage" from currently used
2034 // args, and requirements
2035 fn smart_usage(&self, usage
: &mut String
, used
: &[&str]) {
2036 debugln
!("Parser::smart_usage;");
2037 let mut hs
: Vec
<&str> = self.required().map(|s
| &**s
).collect();
2038 hs
.extend_from_slice(used
);
2040 let r_string
= self.get_required_from(&hs
, None
, None
)
2042 .fold(String
::new(), |acc
, s
| acc
+ &format
!(" {}", s
)[..]);
2044 usage
.push_str(&self.meta
2047 .unwrap_or_else(|| self.meta
2050 .unwrap_or(&self.meta
2052 usage
.push_str(&*r_string
);
2053 if self.is_set(AppSettings
::SubcommandRequired
) {
2054 usage
.push_str(" <SUBCOMMAND>");
2058 // Prints the version to the user and exits if quit=true
2059 fn print_version
<W
: Write
>(&self, w
: &mut W
) -> ClapResult
<()> {
2060 try
!(self.write_version(w
));
2061 w
.flush().map_err(Error
::from
)
2064 pub fn write_version
<W
: Write
>(&self, w
: &mut W
) -> io
::Result
<()> {
2065 if let Some(bn
) = self.meta
.bin_name
.as_ref() {
2066 if bn
.contains(' '
) {
2067 // Incase we're dealing with subcommands i.e. git mv is translated to git-mv
2070 bn
.replace(" ", "-"),
2071 self.meta
.version
.unwrap_or("".into()))
2075 &self.meta
.name
[..],
2076 self.meta
.version
.unwrap_or("".into()))
2081 &self.meta
.name
[..],
2082 self.meta
.version
.unwrap_or("".into()))
2086 pub fn print_help(&self) -> ClapResult
<()> {
2087 let out
= io
::stdout();
2088 let mut buf_w
= BufWriter
::new(out
.lock());
2089 self.write_help(&mut buf_w
)
2092 pub fn write_help
<W
: Write
>(&self, w
: &mut W
) -> ClapResult
<()> {
2093 Help
::write_parser_help(w
, self)
2096 pub fn write_help_err
<W
: Write
>(&self, w
: &mut W
) -> ClapResult
<()> {
2097 Help
::write_parser_help_to_stderr(w
, self)
2100 fn add_defaults(&mut self, matcher
: &mut ArgMatcher
<'a
>) -> ClapResult
<()> {
2101 macro_rules
! add_val
{
2102 (@
default $_self
:ident
, $a
:ident
, $m
:ident
) => {
2103 if let Some(ref val
) = $a
.v
.default_val
{
2104 if $m
.get($a
.b
.name
).is_none() {
2105 try
!($_self
.add_val_to_arg($a
, OsStr
::new(val
), $m
));
2106 arg_post_processing
!($_self
, $a
, $m
);
2110 ($_self
:ident
, $a
:ident
, $m
:ident
) => {
2111 if let Some(ref vm
) = $a
.v
.default_vals_ifs
{
2112 let mut done
= false;
2113 if $m
.get($a
.b
.name
).is_none() {
2114 for &(arg
, val
, default) in vm
.values() {
2115 let add
= if let Some(a
) = $m
.get(arg
) {
2116 if let Some(v
) = val
{
2117 a
.vals
.values().any(|value
| v
== value
)
2125 try
!($_self
.add_val_to_arg($a
, OsStr
::new(default), $m
));
2126 arg_post_processing
!($_self
, $a
, $m
);
2134 continue; // outer loop (outside macro)
2137 add_val
!(@
default $_self
, $a
, $m
)
2141 for o
in &self.opts
{
2142 add_val
!(self, o
, matcher
);
2144 for p
in self.positionals
.values() {
2145 add_val
!(self, p
, matcher
);
2150 pub fn flags(&self) -> Iter
<FlagBuilder
<'a
, 'b
>> { self.flags.iter() }
2152 pub fn opts(&self) -> Iter
<OptBuilder
<'a
, 'b
>> { self.opts.iter() }
2154 pub fn positionals(&self) -> vec_map
::Values
<PosBuilder
<'a
, 'b
>> { self.positionals.values() }
2156 pub fn subcommands(&self) -> Iter
<App
> { self.subcommands.iter() }
2158 // Should we color the output? None=determined by output location, true=yes, false=no
2160 pub fn color(&self) -> ColorWhen
{
2161 debugln
!("Parser::color;");
2162 debug
!("Parser::color: Color setting...");
2163 if self.is_set(AppSettings
::ColorNever
) {
2166 } else if self.is_set(AppSettings
::ColorAlways
) {
2167 sdebugln
!("Always");
2175 pub fn find_any_arg(&self, name
: &str) -> Option
<&AnyArg
> {
2176 if let Some(f
) = find_by_name
!(self, &name
, flags
, iter
) {
2179 if let Some(o
) = find_by_name
!(self, &name
, opts
, iter
) {
2182 if let Some(p
) = find_by_name
!(self, &name
, positionals
, values
) {
2188 #[cfg_attr(feature = "lints", allow(explicit_iter_loop))]
2189 pub fn find_subcommand(&'b
self, sc
: &str) -> Option
<&'b App
<'a
, 'b
>> {
2190 debugln
!("Parser::find_subcommand: sc={}", sc
);
2191 debugln
!("Parser::find_subcommand: Currently in Parser...{}", self.meta
.bin_name
.as_ref().unwrap());
2192 for s
in self.subcommands
.iter() {
2193 if s
.p
.meta
.bin_name
.as_ref().unwrap_or(&String
::new()) == sc
||
2194 (s
.p
.meta
.aliases
.is_some() &&
2201 .any(|&(s
, _
)| s
== sc
.split(' '
).rev().next().expect(INTERNAL_ERROR_MSG
))) {
2204 if let Some(app
) = s
.p
.find_subcommand(sc
) {
2212 impl<'a
, 'b
> Clone
for Parser
<'a
, 'b
>
2215 fn clone(&self) -> Self {
2217 propogated
: self.propogated
,
2218 required
: self.required
.clone(),
2219 short_list
: self.short_list
.clone(),
2220 long_list
: self.long_list
.clone(),
2221 blacklist
: self.blacklist
.clone(),
2222 flags
: self.flags
.clone(),
2223 opts
: self.opts
.clone(),
2224 positionals
: self.positionals
.clone(),
2225 subcommands
: self.subcommands
.clone(),
2226 groups
: self.groups
.clone(),
2227 global_args
: self.global_args
.clone(),
2228 overrides
: self.overrides
.clone(),
2229 help_short
: self.help_short
,
2230 version_short
: self.version_short
,
2231 settings
: self.settings
,
2232 g_settings
: self.g_settings
,
2233 meta
: self.meta
.clone(),
2234 trailing_vals
: self.trailing_vals
,
2236 valid_neg_num
: self.valid_neg_num
,
2237 r_ifs
: self.r_ifs
.clone(),
2238 valid_arg
: self.valid_arg
,