mirror of
https://github.com/clap-rs/clap
synced 2025-01-05 17:28:42 +00:00
style: rustfmt run
This commit is contained in:
parent
c6219ec5ed
commit
07e6e8ea31
18 changed files with 564 additions and 413 deletions
112
src/app/help.rs
112
src/app/help.rs
|
@ -1,21 +1,24 @@
|
||||||
use std::io::{self, Cursor, Read, Write};
|
// Std
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::cmp;
|
|
||||||
use std::usize;
|
|
||||||
|
|
||||||
use vec_map::VecMap;
|
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
|
||||||
|
|
||||||
use errors::{Error, Result as ClapResult};
|
// Internal
|
||||||
|
|
||||||
use args::{AnyArg, ArgSettings, DispOrder};
|
|
||||||
use app::{App, AppSettings};
|
use app::{App, AppSettings};
|
||||||
use app::parser::Parser;
|
use app::parser::Parser;
|
||||||
|
use args::{AnyArg, ArgSettings, DispOrder};
|
||||||
|
use errors::{Error, Result as ClapResult};
|
||||||
use fmt::{Format, Colorizer};
|
use fmt::{Format, Colorizer};
|
||||||
|
use std::cmp;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::io::{self, Cursor, Read, Write};
|
||||||
|
use std::usize;
|
||||||
|
|
||||||
#[cfg(feature = "wrap_help")]
|
#[cfg(feature = "wrap_help")]
|
||||||
use term_size;
|
use term_size;
|
||||||
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
|
use vec_map::VecMap;
|
||||||
#[cfg(not(feature = "wrap_help"))]
|
#[cfg(not(feature = "wrap_help"))]
|
||||||
mod term_size {
|
mod term_size {
|
||||||
pub fn dimensions() -> Option<(usize, usize)> {
|
pub fn dimensions() -> Option<(usize, usize)> {
|
||||||
|
@ -90,19 +93,21 @@ pub struct Help<'a> {
|
||||||
// Public Functions
|
// Public Functions
|
||||||
impl<'a> Help<'a> {
|
impl<'a> Help<'a> {
|
||||||
/// Create a new `Help` instance.
|
/// Create a new `Help` instance.
|
||||||
pub fn new(w: &'a mut Write, next_line_help: bool, hide_pv: bool, color: bool, cizer: Colorizer, term_w: Option<usize>) -> Self {
|
pub fn new(w: &'a mut Write,
|
||||||
|
next_line_help: bool,
|
||||||
|
hide_pv: bool,
|
||||||
|
color: bool,
|
||||||
|
cizer: Colorizer,
|
||||||
|
term_w: Option<usize>)
|
||||||
|
-> Self {
|
||||||
debugln!("fn=Help::new;");
|
debugln!("fn=Help::new;");
|
||||||
Help {
|
Help {
|
||||||
writer: w,
|
writer: w,
|
||||||
next_line_help: next_line_help,
|
next_line_help: next_line_help,
|
||||||
hide_pv: hide_pv,
|
hide_pv: hide_pv,
|
||||||
term_w: match term_w {
|
term_w: match term_w {
|
||||||
Some(width) => if width == 0 {
|
Some(width) => if width == 0 { usize::MAX } else { width },
|
||||||
usize::MAX
|
None => term_size::dimensions().map_or(120, |(w, _)| w),
|
||||||
} else {
|
|
||||||
width
|
|
||||||
},
|
|
||||||
None => term_size::dimensions().map_or(120, |(w, _)| w),
|
|
||||||
},
|
},
|
||||||
color: color,
|
color: color,
|
||||||
cizer: cizer,
|
cizer: cizer,
|
||||||
|
@ -312,7 +317,8 @@ impl<'a> Help<'a> {
|
||||||
let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp);
|
let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp);
|
||||||
let width = self.term_w;
|
let width = self.term_w;
|
||||||
let taken = (longest + 12) + str_width(&*spec_vals);
|
let taken = (longest + 12) + str_width(&*spec_vals);
|
||||||
let force_next_line = !nlh && width >= taken && str_width(h) > (width - taken) && (taken as f32 / width as f32) > 0.25;
|
let force_next_line = !nlh && width >= taken && str_width(h) > (width - taken) &&
|
||||||
|
(taken as f32 / width as f32) > 0.25;
|
||||||
|
|
||||||
if arg.has_switch() {
|
if arg.has_switch() {
|
||||||
if !(nlh || force_next_line) {
|
if !(nlh || force_next_line) {
|
||||||
|
@ -400,9 +406,13 @@ impl<'a> Help<'a> {
|
||||||
|
|
||||||
// We calculate with longest+12 since if it's already NLH we don't care
|
// We calculate with longest+12 since if it's already NLH we don't care
|
||||||
let taken = (longest + 12) + str_width(&*spec_vals);
|
let taken = (longest + 12) + str_width(&*spec_vals);
|
||||||
let force_next_line = !nlh && width >= taken && str_width(h) > (width - taken) && (taken as f32 / width as f32) > 0.25;
|
let force_next_line = !nlh && width >= taken && str_width(h) > (width - taken) &&
|
||||||
|
(taken as f32 / width as f32) > 0.25;
|
||||||
debugln!("Force Next Line...{:?}", force_next_line);
|
debugln!("Force Next Line...{:?}", force_next_line);
|
||||||
debugln!("Force Next Line math (help_len > (width - flags/opts/spcs))...{} > ({} - {})", str_width(h), width, taken);
|
debugln!("Force Next Line math (help_len > (width - flags/opts/spcs))...{} > ({} - {})",
|
||||||
|
str_width(h),
|
||||||
|
width,
|
||||||
|
taken);
|
||||||
|
|
||||||
let spcs = if nlh || force_next_line {
|
let spcs = if nlh || force_next_line {
|
||||||
8 // "tab" + "tab"
|
8 // "tab" + "tab"
|
||||||
|
@ -488,9 +498,9 @@ impl<'a> Help<'a> {
|
||||||
if self.color {
|
if self.color {
|
||||||
format!(" [values: {}]",
|
format!(" [values: {}]",
|
||||||
pv.iter()
|
pv.iter()
|
||||||
.map(|v| format!("{}", self.cizer.good(v)))
|
.map(|v| format!("{}", self.cizer.good(v)))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", "))
|
.join(", "))
|
||||||
} else {
|
} else {
|
||||||
format!(" [values: {}]", pv.join(", "))
|
format!(" [values: {}]", pv.join(", "))
|
||||||
}
|
}
|
||||||
|
@ -501,14 +511,14 @@ impl<'a> Help<'a> {
|
||||||
} else if let Some(ref aliases) = a.aliases() {
|
} else if let Some(ref aliases) = a.aliases() {
|
||||||
debugln!("Writing aliases");
|
debugln!("Writing aliases");
|
||||||
return format!(" [aliases: {}]",
|
return format!(" [aliases: {}]",
|
||||||
if self.color {
|
if self.color {
|
||||||
aliases.iter()
|
aliases.iter()
|
||||||
.map(|v| format!("{}", self.cizer.good(v)))
|
.map(|v| format!("{}", self.cizer.good(v)))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
} else {
|
} else {
|
||||||
aliases.join(", ")
|
aliases.join(", ")
|
||||||
});
|
});
|
||||||
} else if !self.hide_pv {
|
} else if !self.hide_pv {
|
||||||
debugln!("Writing values");
|
debugln!("Writing values");
|
||||||
if let Some(pv) = a.possible_vals() {
|
if let Some(pv) = a.possible_vals() {
|
||||||
|
@ -516,9 +526,9 @@ impl<'a> Help<'a> {
|
||||||
return if self.color {
|
return if self.color {
|
||||||
format!(" [values: {}]",
|
format!(" [values: {}]",
|
||||||
pv.iter()
|
pv.iter()
|
||||||
.map(|v| format!("{}", self.cizer.good(v)))
|
.map(|v| format!("{}", self.cizer.good(v)))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", "))
|
.join(", "))
|
||||||
} else {
|
} else {
|
||||||
format!(" [values: {}]", pv.join(", "))
|
format!(" [values: {}]", pv.join(", "))
|
||||||
};
|
};
|
||||||
|
@ -547,8 +557,8 @@ impl<'a> Help<'a> {
|
||||||
|
|
||||||
if unified_help && (flags || opts) {
|
if unified_help && (flags || opts) {
|
||||||
let opts_flags = parser.iter_flags()
|
let opts_flags = parser.iter_flags()
|
||||||
.map(as_arg_trait)
|
.map(as_arg_trait)
|
||||||
.chain(parser.iter_opts().map(as_arg_trait));
|
.chain(parser.iter_opts().map(as_arg_trait));
|
||||||
try!(color!(self, "OPTIONS:\n", warning));
|
try!(color!(self, "OPTIONS:\n", warning));
|
||||||
try!(self.write_args(opts_flags));
|
try!(self.write_args(opts_flags));
|
||||||
first = false;
|
first = false;
|
||||||
|
@ -556,7 +566,7 @@ impl<'a> Help<'a> {
|
||||||
if flags {
|
if flags {
|
||||||
try!(color!(self, "FLAGS:\n", warning));
|
try!(color!(self, "FLAGS:\n", warning));
|
||||||
try!(self.write_args(parser.iter_flags()
|
try!(self.write_args(parser.iter_flags()
|
||||||
.map(as_arg_trait)));
|
.map(as_arg_trait)));
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
if opts {
|
if opts {
|
||||||
|
@ -826,11 +836,11 @@ impl<'a> Help<'a> {
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
debugln!("iter;tag_buf={};", unsafe {
|
debugln!("iter;tag_buf={};", unsafe {
|
||||||
String::from_utf8_unchecked(tag_buf.get_ref()[0..tag_length]
|
String::from_utf8_unchecked(tag_buf.get_ref()[0..tag_length]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&i|i)
|
.map(|&i| i)
|
||||||
.collect::<Vec<_>>())
|
.collect::<Vec<_>>())
|
||||||
});
|
});
|
||||||
match &tag_buf.get_ref()[0..tag_length] {
|
match &tag_buf.get_ref()[0..tag_length] {
|
||||||
b"?" => {
|
b"?" => {
|
||||||
|
@ -862,21 +872,21 @@ impl<'a> Help<'a> {
|
||||||
}
|
}
|
||||||
b"unified" => {
|
b"unified" => {
|
||||||
let opts_flags = parser.iter_flags()
|
let opts_flags = parser.iter_flags()
|
||||||
.map(as_arg_trait)
|
.map(as_arg_trait)
|
||||||
.chain(parser.iter_opts().map(as_arg_trait));
|
.chain(parser.iter_opts().map(as_arg_trait));
|
||||||
try!(self.write_args(opts_flags));
|
try!(self.write_args(opts_flags));
|
||||||
}
|
}
|
||||||
b"flags" => {
|
b"flags" => {
|
||||||
try!(self.write_args(parser.iter_flags()
|
try!(self.write_args(parser.iter_flags()
|
||||||
.map(as_arg_trait)));
|
.map(as_arg_trait)));
|
||||||
}
|
}
|
||||||
b"options" => {
|
b"options" => {
|
||||||
try!(self.write_args(parser.iter_opts()
|
try!(self.write_args(parser.iter_opts()
|
||||||
.map(as_arg_trait)));
|
.map(as_arg_trait)));
|
||||||
}
|
}
|
||||||
b"positionals" => {
|
b"positionals" => {
|
||||||
try!(self.write_args(parser.iter_positionals()
|
try!(self.write_args(parser.iter_positionals()
|
||||||
.map(as_arg_trait)));
|
.map(as_arg_trait)));
|
||||||
}
|
}
|
||||||
b"subcommands" => {
|
b"subcommands" => {
|
||||||
try!(self.write_subcommands(&parser));
|
try!(self.write_subcommands(&parser));
|
||||||
|
@ -904,7 +914,9 @@ impl<'a> Help<'a> {
|
||||||
|
|
||||||
#[cfg_attr(feature = "lints", allow(explicit_counter_loop))]
|
#[cfg_attr(feature = "lints", allow(explicit_counter_loop))]
|
||||||
fn wrap_help(help: &mut String, longest_w: usize, avail_chars: usize) {
|
fn wrap_help(help: &mut String, longest_w: usize, avail_chars: usize) {
|
||||||
debugln!("fn=wrap_help;longest_w={},avail_chars={}", longest_w, avail_chars);
|
debugln!("fn=wrap_help;longest_w={},avail_chars={}",
|
||||||
|
longest_w,
|
||||||
|
avail_chars);
|
||||||
debug!("Enough space to wrap...");
|
debug!("Enough space to wrap...");
|
||||||
if longest_w < avail_chars {
|
if longest_w < avail_chars {
|
||||||
sdebugln!("Yes");
|
sdebugln!("Yes");
|
||||||
|
@ -913,9 +925,11 @@ fn wrap_help(help: &mut String, longest_w: usize, avail_chars: usize) {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for (idx, g) in (&*help.clone()).grapheme_indices(true) {
|
for (idx, g) in (&*help.clone()).grapheme_indices(true) {
|
||||||
debugln!("iter;idx={},g={}", idx, g);
|
debugln!("iter;idx={},g={}", idx, g);
|
||||||
if g != " " { continue; }
|
if g != " " {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if str_width(&help[j..idx + (2 * i)]) < avail_chars {
|
if str_width(&help[j..idx + (2 * i)]) < avail_chars {
|
||||||
debugln!("Still enough space...");
|
debugln!("Still enough space...");
|
||||||
prev_space = idx;
|
prev_space = idx;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,8 +104,10 @@ macro_rules! validate_multiples {
|
||||||
($_self:ident, $a:ident, $m:ident) => {
|
($_self:ident, $a:ident, $m:ident) => {
|
||||||
debugln!("macro=validate_multiples!;");
|
debugln!("macro=validate_multiples!;");
|
||||||
if $m.contains(&$a.name) && !$a.settings.is_set(ArgSettings::Multiple) {
|
if $m.contains(&$a.name) && !$a.settings.is_set(ArgSettings::Multiple) {
|
||||||
// Not the first time, and we don't allow multiples
|
// Not the first time, and we don't allow multiples
|
||||||
return Err(Error::unexpected_multiple_usage($a, &*$_self.create_current_usage($m), $_self.color()))
|
return Err(Error::unexpected_multiple_usage($a,
|
||||||
|
&*$_self.create_current_usage($m),
|
||||||
|
$_self.color()))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,28 +6,31 @@ pub mod parser;
|
||||||
mod meta;
|
mod meta;
|
||||||
mod help;
|
mod help;
|
||||||
|
|
||||||
pub use self::settings::AppSettings;
|
// Std
|
||||||
|
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
use app::help::Help;
|
||||||
|
use app::parser::Parser;
|
||||||
|
use args::{AnyArg, Arg, ArgGroup, ArgMatcher, ArgMatches, ArgSettings};
|
||||||
|
use errors::Error;
|
||||||
|
use errors::Result as ClapResult;
|
||||||
|
pub use self::settings::AppSettings;
|
||||||
|
use shell::Shell;
|
||||||
|
use std::borrow::Borrow;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::fmt;
|
||||||
use std::io::{self, BufRead, BufWriter, Write};
|
use std::io::{self, BufRead, BufWriter, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::ffi::OsString;
|
|
||||||
use std::borrow::Borrow;
|
|
||||||
use std::result::Result as StdResult;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::fmt;
|
use std::result::Result as StdResult;
|
||||||
|
|
||||||
|
// Third Party
|
||||||
|
use vec_map::VecMap;
|
||||||
#[cfg(feature = "yaml")]
|
#[cfg(feature = "yaml")]
|
||||||
use yaml_rust::Yaml;
|
use yaml_rust::Yaml;
|
||||||
use vec_map::VecMap;
|
|
||||||
|
|
||||||
use args::{AnyArg, Arg, ArgGroup, ArgMatcher, ArgMatches, ArgSettings};
|
|
||||||
use app::parser::Parser;
|
|
||||||
use app::help::Help;
|
|
||||||
use errors::Error;
|
|
||||||
use errors::Result as ClapResult;
|
|
||||||
use shell::Shell;
|
|
||||||
|
|
||||||
/// Used to create a representation of a command line program and all possible command line
|
/// Used to create a representation of a command line program and all possible command line
|
||||||
/// arguments. Application settings are set using the "builder pattern" with the
|
/// arguments. Application settings are set using the "builder pattern" with the
|
||||||
|
@ -1086,7 +1089,10 @@ impl<'a, 'b> App<'a, 'b> {
|
||||||
/// `<project>/target/debug/build/myapp-<hash>/out/myapp.bash-completion`.
|
/// `<project>/target/debug/build/myapp-<hash>/out/myapp.bash-completion`.
|
||||||
///
|
///
|
||||||
/// Fish shell completions will use the file format `{bin_name}.fish`
|
/// Fish shell completions will use the file format `{bin_name}.fish`
|
||||||
pub fn gen_completions<T: Into<OsString>, S: Into<String>>(&mut self, bin_name: S, for_shell: Shell, out_dir: T) {
|
pub fn gen_completions<T: Into<OsString>, S: Into<String>>(&mut self,
|
||||||
|
bin_name: S,
|
||||||
|
for_shell: Shell,
|
||||||
|
out_dir: T) {
|
||||||
self.p.meta.bin_name = Some(bin_name.into());
|
self.p.meta.bin_name = Some(bin_name.into());
|
||||||
self.p.gen_completions(for_shell, out_dir.into());
|
self.p.gen_completions(for_shell, out_dir.into());
|
||||||
}
|
}
|
||||||
|
@ -1124,7 +1130,10 @@ impl<'a, 'b> App<'a, 'b> {
|
||||||
/// ```shell
|
/// ```shell
|
||||||
/// $ myapp generate-bash-completions > /etc/bash_completion.d/myapp
|
/// $ myapp generate-bash-completions > /etc/bash_completion.d/myapp
|
||||||
/// ```
|
/// ```
|
||||||
pub fn gen_completions_to<W: Write, S: Into<String>>(&mut self, bin_name: S, for_shell: Shell, buf: &mut W) {
|
pub fn gen_completions_to<W: Write, S: Into<String>>(&mut self,
|
||||||
|
bin_name: S,
|
||||||
|
for_shell: Shell,
|
||||||
|
buf: &mut W) {
|
||||||
self.p.meta.bin_name = Some(bin_name.into());
|
self.p.meta.bin_name = Some(bin_name.into());
|
||||||
self.p.gen_completions_to(for_shell, buf);
|
self.p.gen_completions_to(for_shell, buf);
|
||||||
}
|
}
|
||||||
|
@ -1342,11 +1351,7 @@ impl<'a> From<&'a Yaml> for App<'a, 'a> {
|
||||||
is_sc = Some(yaml_hash.get(sc_key).unwrap());
|
is_sc = Some(yaml_hash.get(sc_key).unwrap());
|
||||||
App::new(sc_key.as_str().unwrap())
|
App::new(sc_key.as_str().unwrap())
|
||||||
};
|
};
|
||||||
yaml = if let Some(sc) = is_sc {
|
yaml = if let Some(sc) = is_sc { sc } else { yaml };
|
||||||
sc
|
|
||||||
} else {
|
|
||||||
yaml
|
|
||||||
};
|
|
||||||
|
|
||||||
macro_rules! yaml_str {
|
macro_rules! yaml_str {
|
||||||
($a:ident, $y:ident, $i:ident) => {
|
($a:ident, $y:ident, $i:ident) => {
|
||||||
|
@ -1402,7 +1407,9 @@ impl<'a> From<&'a Yaml> for App<'a, 'a> {
|
||||||
if let Some(v) = yaml["global_settings"].as_vec() {
|
if let Some(v) = yaml["global_settings"].as_vec() {
|
||||||
for ys in v {
|
for ys in v {
|
||||||
if let Some(s) = ys.as_str() {
|
if let Some(s) = ys.as_str() {
|
||||||
a = a.global_setting(s.parse().ok().expect("unknown AppSetting found in YAML file"));
|
a = a.global_setting(s.parse()
|
||||||
|
.ok()
|
||||||
|
.expect("unknown AppSetting found in YAML file"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1531,7 +1538,8 @@ impl<'n, 'e> AnyArg<'n, 'e> for App<'n, 'e> {
|
||||||
}
|
}
|
||||||
fn aliases(&self) -> Option<Vec<&'e str>> {
|
fn aliases(&self) -> Option<Vec<&'e str>> {
|
||||||
if let Some(ref aliases) = self.p.meta.aliases {
|
if let Some(ref aliases) = self.p.meta.aliases {
|
||||||
let vis_aliases: Vec<_> = aliases.iter().filter_map(|&(n,v)| if v { Some(n) } else {None}).collect();
|
let vis_aliases: Vec<_> =
|
||||||
|
aliases.iter().filter_map(|&(n, v)| if v { Some(n) } else { None }).collect();
|
||||||
if vis_aliases.is_empty() {
|
if vis_aliases.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,33 +1,38 @@
|
||||||
use std::collections::{BTreeMap, HashMap, VecDeque};
|
// Std
|
||||||
use std::slice::Iter;
|
|
||||||
use std::io::{self, BufWriter, Write};
|
|
||||||
use std::ffi::{OsStr, OsString};
|
|
||||||
use std::fmt::Display;
|
|
||||||
#[cfg(feature = "debug")]
|
|
||||||
use std::os::unix::ffi::OsStrExt;
|
|
||||||
|
|
||||||
use vec_map::{self, VecMap};
|
|
||||||
|
|
||||||
use app::help::Help;
|
// Internal
|
||||||
|
|
||||||
|
use INTERNAL_ERROR_MSG;
|
||||||
|
use INVALID_UTF8;
|
||||||
|
use SubCommand;
|
||||||
use app::App;
|
use app::App;
|
||||||
use args::{Arg, ArgGroup, FlagBuilder, OptBuilder, PosBuilder};
|
use app::help::Help;
|
||||||
|
use app::meta::AppMeta;
|
||||||
use app::settings::{AppFlags, AppSettings};
|
use app::settings::{AppFlags, AppSettings};
|
||||||
use args::{AnyArg, ArgMatcher};
|
use args::{AnyArg, ArgMatcher};
|
||||||
|
use args::{Arg, ArgGroup, FlagBuilder, OptBuilder, PosBuilder};
|
||||||
|
use args::MatchedArg;
|
||||||
use args::settings::ArgSettings;
|
use args::settings::ArgSettings;
|
||||||
|
use completions::ComplGen;
|
||||||
use errors::{Error, ErrorKind};
|
use errors::{Error, ErrorKind};
|
||||||
use errors::Result as ClapResult;
|
use errors::Result as ClapResult;
|
||||||
use INVALID_UTF8;
|
|
||||||
use suggestions;
|
|
||||||
use INTERNAL_ERROR_MSG;
|
|
||||||
use SubCommand;
|
|
||||||
use fmt::{Format, ColorWhen};
|
use fmt::{Format, ColorWhen};
|
||||||
use osstringext::OsStrExt2;
|
use osstringext::OsStrExt2;
|
||||||
use app::meta::AppMeta;
|
|
||||||
use args::MatchedArg;
|
|
||||||
use shell::Shell;
|
use shell::Shell;
|
||||||
use completions::ComplGen;
|
use std::collections::{BTreeMap, HashMap, VecDeque};
|
||||||
|
use std::ffi::{OsStr, OsString};
|
||||||
|
use std::fmt::Display;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::io::{self, BufWriter, Write};
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::slice::Iter;
|
||||||
|
use suggestions;
|
||||||
|
|
||||||
|
// Third Party
|
||||||
|
use vec_map::{self, VecMap};
|
||||||
|
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -91,14 +96,14 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
|
|
||||||
pub fn help_short(&mut self, s: &str) {
|
pub fn help_short(&mut self, s: &str) {
|
||||||
self.help_short = s.trim_left_matches(|c| c == '-')
|
self.help_short = s.trim_left_matches(|c| c == '-')
|
||||||
.chars()
|
.chars()
|
||||||
.nth(0);
|
.nth(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn version_short(&mut self, s: &str) {
|
pub fn version_short(&mut self, s: &str) {
|
||||||
self.version_short = s.trim_left_matches(|c| c == '-')
|
self.version_short = s.trim_left_matches(|c| c == '-')
|
||||||
.chars()
|
.chars()
|
||||||
.nth(0);
|
.nth(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_completions_to<W: Write>(&mut self, for_shell: Shell, buf: &mut W) {
|
pub fn gen_completions_to<W: Write>(&mut self, for_shell: Shell, buf: &mut W) {
|
||||||
|
@ -134,8 +139,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
format!("Non-unique argument name: {} is already in use", a.name));
|
format!("Non-unique argument name: {} is already in use", a.name));
|
||||||
if let Some(ref grps) = a.group {
|
if let Some(ref grps) = a.group {
|
||||||
for g in grps {
|
for g in grps {
|
||||||
let ag = self.groups.entry(g).or_insert_with(|| ArgGroup::with_name(g));
|
let ag = self.groups.entry(g).or_insert_with(|| ArgGroup::with_name(g));
|
||||||
ag.args.push(a.name);
|
ag.args.push(a.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(s) = a.short {
|
if let Some(s) = a.short {
|
||||||
|
@ -248,7 +253,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
self.meta.version.is_some() {
|
self.meta.version.is_some() {
|
||||||
sdebugln!("Yes");
|
sdebugln!("Yes");
|
||||||
subcmd = subcmd.setting(AppSettings::GlobalVersion)
|
subcmd = subcmd.setting(AppSettings::GlobalVersion)
|
||||||
.version(self.meta.version.unwrap());
|
.version(self.meta.version.unwrap());
|
||||||
} else {
|
} else {
|
||||||
sdebugln!("No");
|
sdebugln!("No");
|
||||||
}
|
}
|
||||||
|
@ -365,7 +370,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
debugln!("args_in_groups={:?}", args_in_groups);
|
debugln!("args_in_groups={:?}", args_in_groups);
|
||||||
for (_, s) in pmap {
|
for (_, s) in pmap {
|
||||||
if (!args_in_groups.is_empty()) && (args_in_groups.contains(&&*s)) {
|
if (!args_in_groups.is_empty()) && (args_in_groups.contains(&&*s)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret_val.push_back(s);
|
ret_val.push_back(s);
|
||||||
|
@ -385,7 +390,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
let mut g_vec = vec![];
|
let mut g_vec = vec![];
|
||||||
for g in grps.into_iter() {
|
for g in grps.into_iter() {
|
||||||
let g_string = self.args_in_group(g)
|
let g_string = self.args_in_group(g)
|
||||||
.join("|");
|
.join("|");
|
||||||
g_vec.push(format!("<{}>", &g_string[..g_string.len()]));
|
g_vec.push(format!("<{}>", &g_string[..g_string.len()]));
|
||||||
}
|
}
|
||||||
g_vec.dedup();
|
g_vec.dedup();
|
||||||
|
@ -413,10 +418,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debugln!("Arg not required...");
|
debugln!("Arg not required...");
|
||||||
count +=1;
|
count += 1;
|
||||||
} else {
|
} else {
|
||||||
debugln!("Arg not required...");
|
debugln!("Arg not required...");
|
||||||
count +=1;
|
count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if count > 1 || self.positionals.len() > 1 {
|
if count > 1 || self.positionals.len() > 1 {
|
||||||
|
@ -578,14 +583,18 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
if !self.trailing_vals {
|
if !self.trailing_vals {
|
||||||
// Does the arg match a subcommand name, or any of it's aliases (if defined)
|
// Does the arg match a subcommand name, or any of it's aliases (if defined)
|
||||||
let pos_sc = self.subcommands
|
let pos_sc = self.subcommands
|
||||||
.iter()
|
.iter()
|
||||||
.any(|s| &s.p.meta.name[..] == &*arg_os ||
|
.any(|s| {
|
||||||
(s.p.meta.aliases.is_some() &&
|
&s.p.meta.name[..] == &*arg_os ||
|
||||||
s.p.meta.aliases
|
(s.p.meta.aliases.is_some() &&
|
||||||
.as_ref()
|
s.p
|
||||||
.unwrap()
|
.meta
|
||||||
.iter()
|
.aliases
|
||||||
.any(|&(a, _)| a == &*arg_os)));
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.any(|&(a, _)| a == &*arg_os))
|
||||||
|
});
|
||||||
if (!starts_new_arg || self.is_set(AppSettings::AllowLeadingHyphen)) && !pos_sc {
|
if (!starts_new_arg || self.is_set(AppSettings::AllowLeadingHyphen)) && !pos_sc {
|
||||||
// Check to see if parsing a value from an option
|
// Check to see if parsing a value from an option
|
||||||
if let Some(nvo) = needs_val_of {
|
if let Some(nvo) = needs_val_of {
|
||||||
|
@ -622,36 +631,36 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
let cmds: Vec<OsString> = it.map(|c| c.into()).collect();
|
let cmds: Vec<OsString> = it.map(|c| c.into()).collect();
|
||||||
let mut help_help = false;
|
let mut help_help = false;
|
||||||
let mut bin_name = self.meta
|
let mut bin_name = self.meta
|
||||||
.bin_name
|
.bin_name
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap_or(&self.meta.name).clone();
|
.unwrap_or(&self.meta.name)
|
||||||
|
.clone();
|
||||||
let mut sc = {
|
let mut sc = {
|
||||||
let mut sc: &Parser = self;
|
let mut sc: &Parser = self;
|
||||||
for (i, cmd) in cmds.iter().enumerate() {
|
for (i, cmd) in cmds.iter().enumerate() {
|
||||||
if &*cmd.to_string_lossy() == "help" { // cmd help help
|
if &*cmd.to_string_lossy() == "help" {
|
||||||
|
// cmd help help
|
||||||
help_help = true;
|
help_help = true;
|
||||||
}
|
}
|
||||||
if let Some(c) = sc.subcommands
|
if let Some(c) = sc.subcommands
|
||||||
.iter()
|
.iter()
|
||||||
.find(|s| &*s.p.meta.name == cmd)
|
.find(|s| &*s.p.meta.name == cmd)
|
||||||
.map(|sc| &sc.p) {
|
.map(|sc| &sc.p) {
|
||||||
sc = c;
|
sc = c;
|
||||||
if i == cmds.len() - 1 {
|
if i == cmds.len() - 1 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if let Some(c) = sc.subcommands
|
} else if let Some(c) = sc.subcommands
|
||||||
.iter()
|
.iter()
|
||||||
.find(|s|
|
.find(|s| if let Some(ref als) = s.p
|
||||||
if let Some(ref als) = s.p
|
.meta
|
||||||
.meta
|
.aliases {
|
||||||
.aliases {
|
als.iter()
|
||||||
als.iter()
|
.any(|&(a, _)| &a == &&*cmd.to_string_lossy())
|
||||||
.any(|&(a, _)| &a == &&*cmd.to_string_lossy())
|
} else {
|
||||||
} else {
|
false
|
||||||
false
|
})
|
||||||
}
|
.map(|sc| &sc.p) {
|
||||||
)
|
|
||||||
.map(|sc| &sc.p) {
|
|
||||||
sc = c;
|
sc = c;
|
||||||
if i == cmds.len() - 1 {
|
if i == cmds.len() - 1 {
|
||||||
break;
|
break;
|
||||||
|
@ -691,9 +700,11 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
subcmd_name = Some(arg_os.to_str().expect(INVALID_UTF8).to_owned());
|
subcmd_name = Some(arg_os.to_str().expect(INVALID_UTF8).to_owned());
|
||||||
break;
|
break;
|
||||||
} else if let Some(cdate) = suggestions::did_you_mean(&*arg_os.to_string_lossy(),
|
} else if let Some(cdate) = suggestions::did_you_mean(&*arg_os.to_string_lossy(),
|
||||||
self.subcommands
|
self.subcommands
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| &s.p.meta.name)) {
|
.map(|s| {
|
||||||
|
&s.p.meta.name
|
||||||
|
})) {
|
||||||
return Err(Error::invalid_subcommand(arg_os.to_string_lossy().into_owned(),
|
return Err(Error::invalid_subcommand(arg_os.to_string_lossy().into_owned(),
|
||||||
cdate,
|
cdate,
|
||||||
self.meta
|
self.meta
|
||||||
|
@ -713,9 +724,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
Some(s) => s.to_string(),
|
Some(s) => s.to_string(),
|
||||||
None => {
|
None => {
|
||||||
if !self.settings.is_set(AppSettings::StrictUtf8) {
|
if !self.settings.is_set(AppSettings::StrictUtf8) {
|
||||||
return Err(
|
return Err(Error::invalid_utf8(&*self.create_current_usage(matcher),
|
||||||
Error::invalid_utf8(&*self.create_current_usage(matcher), self.color())
|
self.color()));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
arg_os.to_string_lossy().into_owned()
|
arg_os.to_string_lossy().into_owned()
|
||||||
}
|
}
|
||||||
|
@ -727,9 +737,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
let a = v.into();
|
let a = v.into();
|
||||||
if let None = a.to_str() {
|
if let None = a.to_str() {
|
||||||
if !self.settings.is_set(AppSettings::StrictUtf8) {
|
if !self.settings.is_set(AppSettings::StrictUtf8) {
|
||||||
return Err(
|
return Err(Error::invalid_utf8(&*self.create_current_usage(matcher),
|
||||||
Error::invalid_utf8(&*self.create_current_usage(matcher), self.color())
|
self.color()));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sc_m.add_val_to("", &a);
|
sc_m.add_val_to("", &a);
|
||||||
|
@ -758,7 +767,9 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
if should_err {
|
if should_err {
|
||||||
return Err(Error::empty_value(o, &*self.create_current_usage(matcher), self.color()));
|
return Err(Error::empty_value(o,
|
||||||
|
&*self.create_current_usage(matcher),
|
||||||
|
self.color()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::empty_value(self.positionals
|
return Err(Error::empty_value(self.positionals
|
||||||
|
@ -787,22 +798,26 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
self.subcommands
|
self.subcommands
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|sc| sc.p.meta.aliases.is_some())
|
.filter(|sc| sc.p.meta.aliases.is_some())
|
||||||
.filter_map(|sc| if sc.p.meta.aliases
|
.filter_map(|sc| if sc.p
|
||||||
.as_ref()
|
.meta
|
||||||
.unwrap()
|
.aliases
|
||||||
.iter()
|
.as_ref()
|
||||||
.any(|&(a, _)| &a == &&*pos_sc_name) {
|
.unwrap()
|
||||||
Some(sc.p.meta.name.clone())
|
.iter()
|
||||||
} else {
|
.any(|&(a, _)| &a == &&*pos_sc_name) {
|
||||||
None
|
Some(sc.p.meta.name.clone())
|
||||||
})
|
} else {
|
||||||
|
None
|
||||||
|
})
|
||||||
.next()
|
.next()
|
||||||
.expect(INTERNAL_ERROR_MSG)
|
.expect(INTERNAL_ERROR_MSG)
|
||||||
};
|
};
|
||||||
try!(self.parse_subcommand(sc_name, matcher, it));
|
try!(self.parse_subcommand(sc_name, matcher, it));
|
||||||
} else if self.is_set(AppSettings::SubcommandRequired) {
|
} else if self.is_set(AppSettings::SubcommandRequired) {
|
||||||
let bn = self.meta.bin_name.as_ref().unwrap_or(&self.meta.name);
|
let bn = self.meta.bin_name.as_ref().unwrap_or(&self.meta.name);
|
||||||
return Err(Error::missing_subcommand(bn, &self.create_current_usage(matcher), self.color()));
|
return Err(Error::missing_subcommand(bn,
|
||||||
|
&self.create_current_usage(matcher),
|
||||||
|
self.color()));
|
||||||
} else if self.is_set(AppSettings::SubcommandRequiredElseHelp) {
|
} else if self.is_set(AppSettings::SubcommandRequiredElseHelp) {
|
||||||
let mut out = vec![];
|
let mut out = vec![];
|
||||||
try!(self.write_help_err(&mut out));
|
try!(self.write_help_err(&mut out));
|
||||||
|
@ -884,8 +899,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
}
|
}
|
||||||
mid_string.push_str(" ");
|
mid_string.push_str(" ");
|
||||||
if let Some(ref mut sc) = self.subcommands
|
if let Some(ref mut sc) = self.subcommands
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|s| &s.p.meta.name == &sc_name) {
|
.find(|s| &s.p.meta.name == &sc_name) {
|
||||||
let mut sc_matcher = ArgMatcher::new();
|
let mut sc_matcher = ArgMatcher::new();
|
||||||
// bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by
|
// bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by
|
||||||
// a space
|
// a space
|
||||||
|
@ -1007,8 +1022,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
} else if self.groups.contains_key(&**n) {
|
} else if self.groups.contains_key(&**n) {
|
||||||
g_vec.push(*n);
|
g_vec.push(*n);
|
||||||
} else if let Some(p) = self.positionals
|
} else if let Some(p) = self.positionals
|
||||||
.values()
|
.values()
|
||||||
.find(|p| &p.name == n) {
|
.find(|p| &p.name == n) {
|
||||||
args.push(p.name.to_owned());
|
args.push(p.name.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1061,7 +1076,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
self.flags.push(arg);
|
self.flags.push(arg);
|
||||||
}
|
}
|
||||||
if !self.settings.is_set(AppSettings::DisableVersion) &&
|
if !self.settings.is_set(AppSettings::DisableVersion) &&
|
||||||
self.is_set(AppSettings::NeedsLongVersion) {
|
self.is_set(AppSettings::NeedsLongVersion) {
|
||||||
debugln!("Building --version");
|
debugln!("Building --version");
|
||||||
if self.version_short.is_none() && !self.short_list.contains(&'V') {
|
if self.version_short.is_none() && !self.short_list.contains(&'V') {
|
||||||
self.version_short = Some('V');
|
self.version_short = Some('V');
|
||||||
|
@ -1084,7 +1099,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
debugln!("Building help");
|
debugln!("Building help");
|
||||||
self.subcommands
|
self.subcommands
|
||||||
.push(App::new("help")
|
.push(App::new("help")
|
||||||
.about("Prints this message or the help of the given subcommand(s)"));
|
.about("Prints this message or the help of the given subcommand(s)"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,22 +1107,22 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
// because those will be listed in self.required
|
// because those will be listed in self.required
|
||||||
pub fn create_current_usage(&self, matcher: &'b ArgMatcher<'a>) -> String {
|
pub fn create_current_usage(&self, matcher: &'b ArgMatcher<'a>) -> String {
|
||||||
self.create_usage(&*matcher.arg_names()
|
self.create_usage(&*matcher.arg_names()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|n| {
|
.filter(|n| {
|
||||||
if let Some(o) = self.opts
|
if let Some(o) = self.opts
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&o| &&o.name == n) {
|
.find(|&o| &&o.name == n) {
|
||||||
!o.settings.is_set(ArgSettings::Required)
|
!o.settings.is_set(ArgSettings::Required)
|
||||||
} else if let Some(p) = self.positionals
|
} else if let Some(p) = self.positionals
|
||||||
.values()
|
.values()
|
||||||
.find(|&p| &&p.name == n) {
|
.find(|&p| &&p.name == n) {
|
||||||
!p.settings.is_set(ArgSettings::Required)
|
!p.settings.is_set(ArgSettings::Required)
|
||||||
} else {
|
} else {
|
||||||
true // flags can't be required, so they're always true
|
true // flags can't be required, so they're always true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(|&n| n)
|
.map(|&n| n)
|
||||||
.collect::<Vec<_>>())
|
.collect::<Vec<_>>())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_help_and_version_str(&self, arg: &OsStr) -> ClapResult<()> {
|
fn check_for_help_and_version_str(&self, arg: &OsStr) -> ClapResult<()> {
|
||||||
|
@ -1187,16 +1202,16 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(opt) = self.opts
|
if let Some(opt) = self.opts
|
||||||
.iter()
|
.iter()
|
||||||
.find(|v| v.long.is_some() && &*v.long.unwrap() == arg) {
|
.find(|v| v.long.is_some() && &*v.long.unwrap() == arg) {
|
||||||
debugln!("Found valid opt '{}'", opt.to_string());
|
debugln!("Found valid opt '{}'", opt.to_string());
|
||||||
let ret = try!(self.parse_opt(val, opt, matcher));
|
let ret = try!(self.parse_opt(val, opt, matcher));
|
||||||
arg_post_processing!(self, opt, matcher);
|
arg_post_processing!(self, opt, matcher);
|
||||||
|
|
||||||
return Ok(ret);
|
return Ok(ret);
|
||||||
} else if let Some(flag) = self.flags
|
} else if let Some(flag) = self.flags
|
||||||
.iter()
|
.iter()
|
||||||
.find(|v| v.long.is_some() && &*v.long.unwrap() == arg) {
|
.find(|v| v.long.is_some() && &*v.long.unwrap() == arg) {
|
||||||
debugln!("Found valid flag '{}'", flag.to_string());
|
debugln!("Found valid flag '{}'", flag.to_string());
|
||||||
// Only flags could be help or version, and we need to check the raw long
|
// Only flags could be help or version, and we need to check the raw long
|
||||||
// so this is the first point to check
|
// so this is the first point to check
|
||||||
|
@ -1231,8 +1246,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
// Option: -o
|
// Option: -o
|
||||||
// Value: val
|
// Value: val
|
||||||
if let Some(opt) = self.opts
|
if let Some(opt) = self.opts
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&v| v.short.is_some() && v.short.unwrap() == c) {
|
.find(|&v| v.short.is_some() && v.short.unwrap() == c) {
|
||||||
debugln!("Found valid short opt -{} in '{}'", c, arg);
|
debugln!("Found valid short opt -{} in '{}'", c, arg);
|
||||||
// Check for trailing concatenated value
|
// Check for trailing concatenated value
|
||||||
let p: Vec<_> = arg.splitn(2, c).collect();
|
let p: Vec<_> = arg.splitn(2, c).collect();
|
||||||
|
@ -1258,8 +1273,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
|
|
||||||
return Ok(ret);
|
return Ok(ret);
|
||||||
} else if let Some(flag) = self.flags
|
} else if let Some(flag) = self.flags
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&v| v.short.is_some() && v.short.unwrap() == c) {
|
.find(|&v| v.short.is_some() && v.short.unwrap() == c) {
|
||||||
debugln!("Found valid short flag -{}", c);
|
debugln!("Found valid short flag -{}", c);
|
||||||
// Only flags can be help or version
|
// Only flags can be help or version
|
||||||
try!(self.check_for_help_and_version_char(c));
|
try!(self.check_for_help_and_version_char(c));
|
||||||
|
@ -1295,7 +1310,9 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
let v = fv.trim_left_matches(b'=');
|
let v = fv.trim_left_matches(b'=');
|
||||||
if !opt.is_set(ArgSettings::EmptyValues) && v.len_() == 0 {
|
if !opt.is_set(ArgSettings::EmptyValues) && v.len_() == 0 {
|
||||||
sdebugln!("Found Empty - Error");
|
sdebugln!("Found Empty - Error");
|
||||||
return Err(Error::empty_value(opt, &*self.create_current_usage(matcher), self.color()));
|
return Err(Error::empty_value(opt,
|
||||||
|
&*self.create_current_usage(matcher),
|
||||||
|
self.color()));
|
||||||
}
|
}
|
||||||
sdebugln!("Found - {:?}, len: {}", v, v.len_());
|
sdebugln!("Found - {:?}, len: {}", v, v.len_());
|
||||||
debugln!("{:?} contains '='...{:?}", fv, fv.starts_with(&[b'=']));
|
debugln!("{:?} contains '='...{:?}", fv, fv.starts_with(&[b'=']));
|
||||||
|
@ -1308,7 +1325,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
// Increment or create the group "args"
|
// Increment or create the group "args"
|
||||||
self.groups_for_arg(opt.name).and_then(|vec| Some(matcher.inc_occurrences_of(&*vec)));
|
self.groups_for_arg(opt.name).and_then(|vec| Some(matcher.inc_occurrences_of(&*vec)));
|
||||||
|
|
||||||
if val.is_none() || !has_eq && (opt.is_set(ArgSettings::Multiple) && matcher.needs_more_vals(opt)) {
|
if val.is_none() ||
|
||||||
|
!has_eq && (opt.is_set(ArgSettings::Multiple) && matcher.needs_more_vals(opt)) {
|
||||||
return Ok(Some(opt.name));
|
return Ok(Some(opt.name));
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
@ -1332,7 +1350,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
ret = try!(self.add_single_val_to_arg(arg, v, matcher));
|
ret = try!(self.add_single_val_to_arg(arg, v, matcher));
|
||||||
}
|
}
|
||||||
// If there was a delimiter used, we're not looking for more values
|
// If there was a delimiter used, we're not looking for more values
|
||||||
if val.contains_byte(delim as u32 as u8) || arg.is_set(ArgSettings::RequireDelimiter) {
|
if val.contains_byte(delim as u32 as u8) ||
|
||||||
|
arg.is_set(ArgSettings::RequireDelimiter) {
|
||||||
ret = None;
|
ret = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1472,12 +1491,12 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
if self.groups.contains_key(&**name) {
|
if self.groups.contains_key(&**name) {
|
||||||
continue;
|
continue;
|
||||||
} else if let Some(opt) = self.opts
|
} else if let Some(opt) = self.opts
|
||||||
.iter()
|
.iter()
|
||||||
.find(|o| &o.name == name) {
|
.find(|o| &o.name == name) {
|
||||||
try!(self._validate_num_vals(opt, ma, matcher));
|
try!(self._validate_num_vals(opt, ma, matcher));
|
||||||
} else if let Some(pos) = self.positionals
|
} else if let Some(pos) = self.positionals
|
||||||
.values()
|
.values()
|
||||||
.find(|p| &p.name == name) {
|
.find(|p| &p.name == name) {
|
||||||
try!(self._validate_num_vals(pos, ma, matcher));
|
try!(self._validate_num_vals(pos, ma, matcher));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1521,13 +1540,13 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
if (ma.vals.len() as u64) > num {
|
if (ma.vals.len() as u64) > num {
|
||||||
debugln!("Sending error TooManyValues");
|
debugln!("Sending error TooManyValues");
|
||||||
return Err(Error::too_many_values(ma.vals
|
return Err(Error::too_many_values(ma.vals
|
||||||
.get(ma.vals
|
.get(ma.vals
|
||||||
.keys()
|
.keys()
|
||||||
.last()
|
.last()
|
||||||
.expect(INTERNAL_ERROR_MSG))
|
.expect(INTERNAL_ERROR_MSG))
|
||||||
.expect(INTERNAL_ERROR_MSG)
|
.expect(INTERNAL_ERROR_MSG)
|
||||||
.to_str()
|
.to_str()
|
||||||
.expect(INVALID_UTF8),
|
.expect(INVALID_UTF8),
|
||||||
a,
|
a,
|
||||||
&*self.create_current_usage(matcher),
|
&*self.create_current_usage(matcher),
|
||||||
self.color()));
|
self.color()));
|
||||||
|
@ -1575,21 +1594,21 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
continue 'outer;
|
continue 'outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let err = if self.settings.is_set(AppSettings::ArgRequiredElseHelp) &&
|
let err =
|
||||||
matcher.is_empty() {
|
if self.settings.is_set(AppSettings::ArgRequiredElseHelp) && matcher.is_empty() {
|
||||||
self._help().unwrap_err()
|
self._help().unwrap_err()
|
||||||
} else {
|
} else {
|
||||||
let mut reqs = self.required.iter().map(|&r| &*r).collect::<Vec<_>>();
|
let mut reqs = self.required.iter().map(|&r| &*r).collect::<Vec<_>>();
|
||||||
reqs.retain(|n| !matcher.contains(n));
|
reqs.retain(|n| !matcher.contains(n));
|
||||||
reqs.dedup();
|
reqs.dedup();
|
||||||
Error::missing_required_argument(
|
Error::missing_required_argument(
|
||||||
&*self.get_required_from(&*reqs, Some(matcher))
|
&*self.get_required_from(&*reqs, Some(matcher))
|
||||||
.iter()
|
.iter()
|
||||||
.fold(String::new(),
|
.fold(String::new(),
|
||||||
|acc, s| acc + &format!("\n {}", Format::Error(s))[..]),
|
|acc, s| acc + &format!("\n {}", Format::Error(s))[..]),
|
||||||
&*self.create_current_usage(matcher),
|
&*self.create_current_usage(matcher),
|
||||||
self.color())
|
self.color())
|
||||||
};
|
};
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1602,8 +1621,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
for n in bl.iter() {
|
for n in bl.iter() {
|
||||||
if matcher.contains(n) ||
|
if matcher.contains(n) ||
|
||||||
self.groups
|
self.groups
|
||||||
.get(n)
|
.get(n)
|
||||||
.map_or(false, |g| g.args.iter().any(|an| matcher.contains(an))) {
|
.map_or(false, |g| g.args.iter().any(|an| matcher.contains(an))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1612,15 +1631,15 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
for n in ru.iter() {
|
for n in ru.iter() {
|
||||||
if matcher.contains(n) ||
|
if matcher.contains(n) ||
|
||||||
self.groups
|
self.groups
|
||||||
.get(n)
|
.get(n)
|
||||||
.map_or(false, |g| g.args.iter().any(|an| matcher.contains(an))) {
|
.map_or(false, |g| g.args.iter().any(|an| matcher.contains(an))) {
|
||||||
if !a.is_set(ArgSettings::RequiredUnlessAll) {
|
if !a.is_set(ArgSettings::RequiredUnlessAll) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
found_any = true;
|
found_any = true;
|
||||||
} else if a.is_set(ArgSettings::RequiredUnlessAll) {
|
} else if a.is_set(ArgSettings::RequiredUnlessAll) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return found_any;
|
return found_any;
|
||||||
}
|
}
|
||||||
|
@ -1637,14 +1656,14 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
// Add the arg to the matches to build a proper usage string
|
// Add the arg to the matches to build a proper usage string
|
||||||
if let Some(name) = suffix.1 {
|
if let Some(name) = suffix.1 {
|
||||||
if let Some(opt) = self.opts
|
if let Some(opt) = self.opts
|
||||||
.iter()
|
.iter()
|
||||||
.find(|o| o.long.is_some() && o.long.unwrap() == name) {
|
.find(|o| o.long.is_some() && o.long.unwrap() == name) {
|
||||||
self.groups_for_arg(&*opt.name)
|
self.groups_for_arg(&*opt.name)
|
||||||
.and_then(|grps| Some(matcher.inc_occurrences_of(&*grps)));
|
.and_then(|grps| Some(matcher.inc_occurrences_of(&*grps)));
|
||||||
matcher.insert(&*opt.name);
|
matcher.insert(&*opt.name);
|
||||||
} else if let Some(flg) = self.flags
|
} else if let Some(flg) = self.flags
|
||||||
.iter()
|
.iter()
|
||||||
.find(|f| f.long.is_some() && f.long.unwrap() == name) {
|
.find(|f| f.long.is_some() && f.long.unwrap() == name) {
|
||||||
self.groups_for_arg(&*flg.name)
|
self.groups_for_arg(&*flg.name)
|
||||||
.and_then(|grps| Some(matcher.inc_occurrences_of(&*grps)));
|
.and_then(|grps| Some(matcher.inc_occurrences_of(&*grps)));
|
||||||
matcher.insert(&*flg.name);
|
matcher.insert(&*flg.name);
|
||||||
|
@ -1652,7 +1671,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
}
|
}
|
||||||
|
|
||||||
let used_arg = format!("--{}", arg);
|
let used_arg = format!("--{}", arg);
|
||||||
Err(Error::unknown_argument(&*used_arg, &*suffix.0, &*self.create_current_usage(matcher), self.color()))
|
Err(Error::unknown_argument(&*used_arg,
|
||||||
|
&*suffix.0,
|
||||||
|
&*self.create_current_usage(matcher),
|
||||||
|
self.color()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a usage string if one was not provided by the user manually. This happens just
|
// Creates a usage string if one was not provided by the user manually. This happens just
|
||||||
|
@ -1677,17 +1699,17 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
usage.push_str(&*u);
|
usage.push_str(&*u);
|
||||||
} else if used.is_empty() {
|
} else if used.is_empty() {
|
||||||
usage.push_str(&*self.meta
|
usage.push_str(&*self.meta
|
||||||
.usage
|
.usage
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap_or(self.meta
|
.unwrap_or(self.meta
|
||||||
.bin_name
|
.bin_name
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap_or(&self.meta.name)));
|
.unwrap_or(&self.meta.name)));
|
||||||
let mut reqs: Vec<&str> = self.required().map(|r| &**r).collect();
|
let mut reqs: Vec<&str> = self.required().map(|r| &**r).collect();
|
||||||
reqs.dedup();
|
reqs.dedup();
|
||||||
let req_string = self.get_required_from(&reqs, None)
|
let req_string = self.get_required_from(&reqs, None)
|
||||||
.iter()
|
.iter()
|
||||||
.fold(String::new(), |a, s| a + &format!(" {}", s)[..]);
|
.fold(String::new(), |a, s| a + &format!(" {}", s)[..]);
|
||||||
|
|
||||||
let flags = self.needs_flags_tag();
|
let flags = self.needs_flags_tag();
|
||||||
if flags && !self.is_set(AppSettings::UnifiedHelpMessage) {
|
if flags && !self.is_set(AppSettings::UnifiedHelpMessage) {
|
||||||
|
@ -1741,17 +1763,17 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
hs.extend_from_slice(used);
|
hs.extend_from_slice(used);
|
||||||
|
|
||||||
let r_string = self.get_required_from(&hs, None)
|
let r_string = self.get_required_from(&hs, None)
|
||||||
.iter()
|
.iter()
|
||||||
.fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]);
|
.fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]);
|
||||||
|
|
||||||
usage.push_str(&self.meta
|
usage.push_str(&self.meta
|
||||||
.usage
|
.usage
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap_or(self.meta
|
.unwrap_or(self.meta
|
||||||
.bin_name
|
.bin_name
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap_or(&self.meta
|
.unwrap_or(&self.meta
|
||||||
.name))[..]);
|
.name))[..]);
|
||||||
usage.push_str(&*r_string);
|
usage.push_str(&*r_string);
|
||||||
if self.is_set(AppSettings::SubcommandRequired) {
|
if self.is_set(AppSettings::SubcommandRequired) {
|
||||||
usage.push_str(" <SUBCOMMAND>");
|
usage.push_str(" <SUBCOMMAND>");
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::str::FromStr;
|
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
flags Flags: u32 {
|
flags Flags: u32 {
|
||||||
|
@ -655,7 +656,7 @@ mod test {
|
||||||
assert_eq!("hidden".parse::<AppSettings>().unwrap(),
|
assert_eq!("hidden".parse::<AppSettings>().unwrap(),
|
||||||
AppSettings::Hidden);
|
AppSettings::Hidden);
|
||||||
assert_eq!("dontdelimittrailingvalues".parse::<AppSettings>().unwrap(),
|
assert_eq!("dontdelimittrailingvalues".parse::<AppSettings>().unwrap(),
|
||||||
AppSettings::DontDelimitTrailingValues);
|
AppSettings::DontDelimitTrailingValues);
|
||||||
assert!("hahahaha".parse::<AppSettings>().is_err());
|
assert!("hahahaha".parse::<AppSettings>().is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
use std::rc::Rc;
|
// Third Party
|
||||||
|
|
||||||
use vec_map::VecMap;
|
|
||||||
|
// Internal
|
||||||
|
|
||||||
use args::settings::ArgSettings;
|
use args::settings::ArgSettings;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use vec_map::VecMap;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub trait AnyArg<'n, 'e> {
|
pub trait AnyArg<'n, 'e> {
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
// use std::collections::HashSet;
|
// Std
|
||||||
use std::fmt::{Display, Formatter, Result};
|
|
||||||
use std::convert::From;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::result::Result as StdResult;
|
|
||||||
|
|
||||||
use vec_map::VecMap;
|
|
||||||
|
// Internal
|
||||||
|
|
||||||
use Arg;
|
use Arg;
|
||||||
use args::{AnyArg, DispOrder};
|
use args::{AnyArg, DispOrder};
|
||||||
use args::settings::{ArgFlags, ArgSettings};
|
use args::settings::{ArgFlags, ArgSettings};
|
||||||
|
use std::convert::From;
|
||||||
|
use std::fmt::{Display, Formatter, Result};
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::result::Result as StdResult;
|
||||||
|
|
||||||
|
// Third Party
|
||||||
|
use vec_map::VecMap;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -179,8 +183,8 @@ impl<'n, 'e> DispOrder for FlagBuilder<'n, 'e> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::FlagBuilder;
|
|
||||||
use args::settings::ArgSettings;
|
use args::settings::ArgSettings;
|
||||||
|
use super::FlagBuilder;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn flagbuilder_display() {
|
fn flagbuilder_display() {
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
use std::rc::Rc;
|
// Std
|
||||||
use std::fmt::{Display, Formatter, Result};
|
|
||||||
use std::result::Result as StdResult;
|
|
||||||
|
|
||||||
use vec_map::VecMap;
|
|
||||||
|
// Internal
|
||||||
|
|
||||||
use args::{AnyArg, Arg, DispOrder};
|
use args::{AnyArg, Arg, DispOrder};
|
||||||
use args::settings::{ArgFlags, ArgSettings};
|
use args::settings::{ArgFlags, ArgSettings};
|
||||||
|
use std::fmt::{Display, Formatter, Result};
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::result::Result as StdResult;
|
||||||
|
|
||||||
|
// Third Party
|
||||||
|
use vec_map::VecMap;
|
||||||
|
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -261,9 +266,9 @@ impl<'n, 'e> DispOrder for OptBuilder<'n, 'e> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use args::settings::ArgSettings;
|
||||||
use super::OptBuilder;
|
use super::OptBuilder;
|
||||||
use vec_map::VecMap;
|
use vec_map::VecMap;
|
||||||
use args::settings::ArgSettings;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn optbuilder_display1() {
|
fn optbuilder_display1() {
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
use std::fmt::{Display, Formatter, Result};
|
// Std
|
||||||
use std::result::Result as StdResult;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
use vec_map::VecMap;
|
|
||||||
|
// Internal
|
||||||
|
|
||||||
use Arg;
|
use Arg;
|
||||||
use args::{AnyArg, DispOrder};
|
use args::{AnyArg, DispOrder};
|
||||||
use args::settings::{ArgFlags, ArgSettings};
|
use args::settings::{ArgFlags, ArgSettings};
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::fmt::{Display, Formatter, Result};
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::result::Result as StdResult;
|
||||||
|
|
||||||
|
// Third Party
|
||||||
|
use vec_map::VecMap;
|
||||||
|
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -110,7 +115,7 @@ impl<'n, 'e> PosBuilder<'n, 'e> {
|
||||||
pb
|
pb
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn multiple_str(&self) -> &str {
|
pub fn multiple_str(&self) -> &str {
|
||||||
if self.settings.is_set(ArgSettings::Multiple) && self.val_names.is_none() {
|
if self.settings.is_set(ArgSettings::Multiple) && self.val_names.is_none() {
|
||||||
"..."
|
"..."
|
||||||
} else {
|
} else {
|
||||||
|
@ -121,9 +126,9 @@ impl<'n, 'e> PosBuilder<'n, 'e> {
|
||||||
pub fn name_no_brackets(&self) -> Cow<str> {
|
pub fn name_no_brackets(&self) -> Cow<str> {
|
||||||
if let Some(ref names) = self.val_names {
|
if let Some(ref names) = self.val_names {
|
||||||
Cow::Owned(names.values()
|
Cow::Owned(names.values()
|
||||||
.map(|n| format!("<{}>", n))
|
.map(|n| format!("<{}>", n))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(" "))
|
.join(" "))
|
||||||
} else {
|
} else {
|
||||||
Cow::Borrowed(self.name)
|
Cow::Borrowed(self.name)
|
||||||
}
|
}
|
||||||
|
@ -136,9 +141,9 @@ impl<'n, 'e> Display for PosBuilder<'n, 'e> {
|
||||||
try!(write!(f,
|
try!(write!(f,
|
||||||
"{}",
|
"{}",
|
||||||
names.values()
|
names.values()
|
||||||
.map(|n| format!("<{}>", n))
|
.map(|n| format!("<{}>", n))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(" ")));
|
.join(" ")));
|
||||||
} else {
|
} else {
|
||||||
try!(write!(f, "<{}>", self.name));
|
try!(write!(f, "<{}>", self.name));
|
||||||
}
|
}
|
||||||
|
@ -251,8 +256,8 @@ impl<'n, 'e> DispOrder for PosBuilder<'n, 'e> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::PosBuilder;
|
|
||||||
use args::settings::ArgSettings;
|
use args::settings::ArgSettings;
|
||||||
|
use super::PosBuilder;
|
||||||
use vec_map::VecMap;
|
use vec_map::VecMap;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
use std::ffi::OsStr;
|
// Std
|
||||||
use std::collections::hash_map::{Entry, Iter};
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
use vec_map::VecMap;
|
|
||||||
|
// Internal
|
||||||
|
|
||||||
use args::{ArgMatches, MatchedArg, SubCommand};
|
use args::{ArgMatches, MatchedArg, SubCommand};
|
||||||
use args::settings::ArgSettings;
|
|
||||||
use args::AnyArg;
|
use args::AnyArg;
|
||||||
|
use args::settings::ArgSettings;
|
||||||
|
use std::collections::hash_map::{Entry, Iter};
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
// Third Party
|
||||||
|
use vec_map::VecMap;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
use std::ffi::{OsStr, OsString};
|
// Std
|
||||||
|
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
|
||||||
|
use INVALID_UTF8;
|
||||||
|
use args::MatchedArg;
|
||||||
|
use args::SubCommand;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::ffi::{OsStr, OsString};
|
||||||
use std::iter::Map;
|
use std::iter::Map;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
|
// Third Party
|
||||||
use vec_map;
|
use vec_map;
|
||||||
|
|
||||||
use args::SubCommand;
|
|
||||||
use args::MatchedArg;
|
|
||||||
use INVALID_UTF8;
|
|
||||||
|
|
||||||
/// Used to get information about the arguments that where supplied to the program at runtime by
|
/// Used to get information about the arguments that where supplied to the program at runtime by
|
||||||
/// the user. New instances of this struct are obtained by using the [`App::get_matches`] family of
|
/// the user. New instances of this struct are obtained by using the [`App::get_matches`] family of
|
||||||
/// methods.
|
/// methods.
|
||||||
|
@ -242,9 +247,9 @@ impl<'a> ArgMatches<'a> {
|
||||||
pub fn values_of_lossy<S: AsRef<str>>(&'a self, name: S) -> Option<Vec<String>> {
|
pub fn values_of_lossy<S: AsRef<str>>(&'a self, name: S) -> Option<Vec<String>> {
|
||||||
if let Some(arg) = self.args.get(name.as_ref()) {
|
if let Some(arg) = self.args.get(name.as_ref()) {
|
||||||
return Some(arg.vals
|
return Some(arg.vals
|
||||||
.values()
|
.values()
|
||||||
.map(|v| v.to_string_lossy().into_owned())
|
.map(|v| v.to_string_lossy().into_owned())
|
||||||
.collect());
|
.collect());
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
pub use self::arg::Arg;
|
|
||||||
pub use self::arg_matches::{Values, OsValues, ArgMatches};
|
|
||||||
pub use self::arg_matcher::ArgMatcher;
|
|
||||||
pub use self::subcommand::SubCommand;
|
|
||||||
pub use self::arg_builder::{FlagBuilder, OptBuilder, PosBuilder};
|
|
||||||
pub use self::matched_arg::MatchedArg;
|
|
||||||
pub use self::group::ArgGroup;
|
|
||||||
pub use self::any_arg::{AnyArg, DispOrder};
|
pub use self::any_arg::{AnyArg, DispOrder};
|
||||||
|
pub use self::arg::Arg;
|
||||||
|
pub use self::arg_builder::{FlagBuilder, OptBuilder, PosBuilder};
|
||||||
|
pub use self::arg_matcher::ArgMatcher;
|
||||||
|
pub use self::arg_matches::{Values, OsValues, ArgMatches};
|
||||||
|
pub use self::group::ArgGroup;
|
||||||
|
pub use self::matched_arg::MatchedArg;
|
||||||
pub use self::settings::ArgSettings;
|
pub use self::settings::ArgSettings;
|
||||||
|
pub use self::subcommand::SubCommand;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::str::FromStr;
|
// Std
|
||||||
|
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
flags Flags: u16 {
|
flags Flags: u16 {
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
use std::io::Write;
|
// Std
|
||||||
|
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
|
||||||
use app::parser::Parser;
|
use app::parser::Parser;
|
||||||
use shell::Shell;
|
|
||||||
use args::{ArgSettings, OptBuilder};
|
use args::{ArgSettings, OptBuilder};
|
||||||
|
use shell::Shell;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
macro_rules! w {
|
macro_rules! w {
|
||||||
($buf:expr, $to_w:expr) => {
|
($buf:expr, $to_w:expr) => {
|
||||||
|
@ -13,15 +17,15 @@ macro_rules! w {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ComplGen<'a, 'b> where 'a: 'b {
|
pub struct ComplGen<'a, 'b>
|
||||||
|
where 'a: 'b
|
||||||
|
{
|
||||||
p: &'b Parser<'a, 'b>,
|
p: &'b Parser<'a, 'b>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> ComplGen<'a, 'b> {
|
impl<'a, 'b> ComplGen<'a, 'b> {
|
||||||
pub fn new(p: &'b Parser<'a, 'b>) -> Self {
|
pub fn new(p: &'b Parser<'a, 'b>) -> Self {
|
||||||
ComplGen {
|
ComplGen { p: p }
|
||||||
p: p,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate<W: Write>(&self, for_shell: Shell, buf: &mut W) {
|
pub fn generate<W: Write>(&self, for_shell: Shell, buf: &mut W) {
|
||||||
|
@ -32,8 +36,8 @@ impl<'a, 'b> ComplGen<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_bash<W: Write>(&self, buf: &mut W) {
|
fn gen_bash<W: Write>(&self, buf: &mut W) {
|
||||||
w!(buf, format!(
|
w!(buf,
|
||||||
"_{name}() {{
|
format!("_{name}() {{
|
||||||
local i cur prev opts cmds
|
local i cur prev opts cmds
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
cur=\"${{COMP_WORDS[COMP_CWORD]}}\"
|
cur=\"${{COMP_WORDS[COMP_CWORD]}}\"
|
||||||
|
@ -75,12 +79,13 @@ impl<'a, 'b> ComplGen<'a, 'b> {
|
||||||
|
|
||||||
complete -F _{name} {name}
|
complete -F _{name} {name}
|
||||||
",
|
",
|
||||||
name=self.p.meta.bin_name.as_ref().unwrap(),
|
name = self.p.meta.bin_name.as_ref().unwrap(),
|
||||||
name_opts=self.all_options_for_path(self.p.meta.bin_name.as_ref().unwrap()),
|
name_opts = self.all_options_for_path(self.p.meta.bin_name.as_ref().unwrap()),
|
||||||
name_opts_details=self.option_details_for_path(self.p.meta.bin_name.as_ref().unwrap()),
|
name_opts_details =
|
||||||
subcmds=self.all_subcommands(),
|
self.option_details_for_path(self.p.meta.bin_name.as_ref().unwrap()),
|
||||||
subcmd_details=self.subcommand_details()
|
subcmds = self.all_subcommands(),
|
||||||
).as_bytes());
|
subcmd_details = self.subcommand_details())
|
||||||
|
.as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn all_subcommands(&self) -> String {
|
fn all_subcommands(&self) -> String {
|
||||||
|
@ -88,13 +93,12 @@ complete -F _{name} {name}
|
||||||
let scs = get_all_subcommands(self.p);
|
let scs = get_all_subcommands(self.p);
|
||||||
|
|
||||||
for sc in &scs {
|
for sc in &scs {
|
||||||
subcmds = format!(
|
subcmds = format!("{}
|
||||||
"{}
|
|
||||||
{name})
|
{name})
|
||||||
cmd+=\"_{name}\"
|
cmd+=\"_{name}\"
|
||||||
;;",
|
;;",
|
||||||
subcmds,
|
subcmds,
|
||||||
name=sc.replace("-", "_"));
|
name = sc.replace("-", "_"));
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmds
|
subcmds
|
||||||
|
@ -107,8 +111,7 @@ complete -F _{name} {name}
|
||||||
scs.dedup();
|
scs.dedup();
|
||||||
|
|
||||||
for sc in &scs {
|
for sc in &scs {
|
||||||
subcmd_dets = format!(
|
subcmd_dets = format!("{}
|
||||||
"{}
|
|
||||||
{subcmd})
|
{subcmd})
|
||||||
opts=\"{sc_opts}\"
|
opts=\"{sc_opts}\"
|
||||||
if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq {level} ]] ; then
|
if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq {level} ]] ; then
|
||||||
|
@ -124,12 +127,11 @@ complete -F _{name} {name}
|
||||||
COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
|
COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
|
||||||
return 0
|
return 0
|
||||||
;;",
|
;;",
|
||||||
subcmd_dets,
|
subcmd_dets,
|
||||||
subcmd=sc.replace("-", "_"),
|
subcmd = sc.replace("-", "_"),
|
||||||
sc_opts=self.all_options_for_path(&*sc),
|
sc_opts = self.all_options_for_path(&*sc),
|
||||||
level=sc.split("_").map(|_|1).fold(0, |acc, n| acc + n),
|
level = sc.split("_").map(|_| 1).fold(0, |acc, n| acc + n),
|
||||||
opts_details=self.option_details_for_path(&*sc)
|
opts_details = self.option_details_for_path(&*sc));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmd_dets
|
subcmd_dets
|
||||||
|
@ -139,24 +141,45 @@ complete -F _{name} {name}
|
||||||
let mut p = self.p;
|
let mut p = self.p;
|
||||||
for sc in path.split('_').skip(1) {
|
for sc in path.split('_').skip(1) {
|
||||||
debugln!("iter;sc={}", sc);
|
debugln!("iter;sc={}", sc);
|
||||||
p = &p.subcommands.iter()
|
p = &p.subcommands
|
||||||
.find(|s| s.p.meta.name == sc
|
.iter()
|
||||||
|| (s.p.meta.aliases.is_some() && s.p.meta.aliases.as_ref()
|
.find(|s| {
|
||||||
.unwrap()
|
s.p.meta.name == sc ||
|
||||||
.iter()
|
(s.p.meta.aliases.is_some() &&
|
||||||
.any(|&(n,_)| n==sc )))
|
s.p
|
||||||
.unwrap().p;
|
.meta
|
||||||
|
.aliases
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.any(|&(n, _)| n == sc))
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.p;
|
||||||
}
|
}
|
||||||
let mut opts = p.short_list.iter().fold(String::new(), |acc, s| format!("{} -{}", acc, s));
|
let mut opts = p.short_list.iter().fold(String::new(), |acc, s| format!("{} -{}", acc, s));
|
||||||
opts = format!("{} {}", opts, p.long_list.iter()
|
opts = format!("{} {}",
|
||||||
.fold(String::new(), |acc, l| format!("{} --{}", acc, l)));
|
opts,
|
||||||
opts = format!("{} {}", opts, p.positionals.values()
|
p.long_list
|
||||||
.fold(String::new(), |acc, p| format!("{} {}", acc, p)));
|
.iter()
|
||||||
opts = format!("{} {}", opts, p.subcommands.iter()
|
.fold(String::new(), |acc, l| format!("{} --{}", acc, l)));
|
||||||
.fold(String::new(), |acc, s| format!("{} {}", acc, s.p.meta.name)));
|
opts = format!("{} {}",
|
||||||
|
opts,
|
||||||
|
p.positionals
|
||||||
|
.values()
|
||||||
|
.fold(String::new(), |acc, p| format!("{} {}", acc, p)));
|
||||||
|
opts = format!("{} {}",
|
||||||
|
opts,
|
||||||
|
p.subcommands
|
||||||
|
.iter()
|
||||||
|
.fold(String::new(), |acc, s| format!("{} {}", acc, s.p.meta.name)));
|
||||||
for sc in &p.subcommands {
|
for sc in &p.subcommands {
|
||||||
if let Some(ref aliases) = sc.p.meta.aliases {
|
if let Some(ref aliases) = sc.p.meta.aliases {
|
||||||
opts = format!("{} {}", opts, aliases.iter().map(|&(n,_)| n).fold(String::new(), |acc, a| format!("{} {}", acc, a)));
|
opts = format!("{} {}",
|
||||||
|
opts,
|
||||||
|
aliases.iter()
|
||||||
|
.map(|&(n, _)| n)
|
||||||
|
.fold(String::new(), |acc, a| format!("{} {}", acc, a)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opts
|
opts
|
||||||
|
@ -166,14 +189,21 @@ complete -F _{name} {name}
|
||||||
let mut p = self.p;
|
let mut p = self.p;
|
||||||
for sc in path.split('_').skip(1) {
|
for sc in path.split('_').skip(1) {
|
||||||
debugln!("iter;sc={}", sc);
|
debugln!("iter;sc={}", sc);
|
||||||
p = &p.subcommands.iter()
|
p = &p.subcommands
|
||||||
.find(|s| s.p.meta.name == sc ||
|
.iter()
|
||||||
(s.p.meta.aliases.is_some() &&
|
.find(|s| {
|
||||||
s.p.meta.aliases.as_ref()
|
s.p.meta.name == sc ||
|
||||||
.unwrap()
|
(s.p.meta.aliases.is_some() &&
|
||||||
.iter()
|
s.p
|
||||||
.any(|&(n,_)| n==sc )))
|
.meta
|
||||||
.unwrap().p;
|
.aliases
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.any(|&(n, _)| n == sc))
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.p;
|
||||||
}
|
}
|
||||||
let mut opts = String::new();
|
let mut opts = String::new();
|
||||||
for o in &p.opts {
|
for o in &p.opts {
|
||||||
|
@ -182,21 +212,27 @@ complete -F _{name} {name}
|
||||||
--{})
|
--{})
|
||||||
COMPREPLY=({})
|
COMPREPLY=({})
|
||||||
return 0
|
return 0
|
||||||
;;", opts, l, vals_for(o));
|
;;",
|
||||||
|
opts,
|
||||||
|
l,
|
||||||
|
vals_for(o));
|
||||||
}
|
}
|
||||||
if let Some(s) = o.short {
|
if let Some(s) = o.short {
|
||||||
opts = format!("{}
|
opts = format!("{}
|
||||||
-{})
|
-{})
|
||||||
COMPREPLY=({})
|
COMPREPLY=({})
|
||||||
return 0
|
return 0
|
||||||
;;", opts, s, vals_for(o));
|
;;",
|
||||||
|
opts,
|
||||||
|
s,
|
||||||
|
vals_for(o));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opts
|
opts
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_fish<W: Write>(&self, buf: &mut W) {
|
fn gen_fish<W: Write>(&self, buf: &mut W) {
|
||||||
let command = self.p.meta.bin_name.as_ref().unwrap();
|
let command = self.p.meta.bin_name.as_ref().unwrap();
|
||||||
let subcommands: Vec<_> = get_all_subcommands(self.p);
|
let subcommands: Vec<_> = get_all_subcommands(self.p);
|
||||||
let has_subcommands = subcommands.len() > 1;
|
let has_subcommands = subcommands.len() > 1;
|
||||||
|
|
||||||
|
@ -291,12 +327,10 @@ fn vals_for(o: &OptBuilder) -> String {
|
||||||
} else if let Some(vec) = o.val_names() {
|
} else if let Some(vec) = o.val_names() {
|
||||||
let mut it = vec.iter().peekable();
|
let mut it = vec.iter().peekable();
|
||||||
while let Some((_, val)) = it.next() {
|
while let Some((_, val)) = it.next() {
|
||||||
ret = format!("{}<{}>{}", ret, val,
|
ret = format!("{}<{}>{}",
|
||||||
if it.peek().is_some() {
|
ret,
|
||||||
" "
|
val,
|
||||||
} else {
|
if it.peek().is_some() { " " } else { "" });
|
||||||
""
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
let num = vec.len();
|
let num = vec.len();
|
||||||
if o.is_set(ArgSettings::Multiple) && num == 1 {
|
if o.is_set(ArgSettings::Multiple) && num == 1 {
|
||||||
|
@ -305,12 +339,10 @@ fn vals_for(o: &OptBuilder) -> String {
|
||||||
} else if let Some(num) = o.num_vals() {
|
} else if let Some(num) = o.num_vals() {
|
||||||
let mut it = (0..num).peekable();
|
let mut it = (0..num).peekable();
|
||||||
while let Some(_) = it.next() {
|
while let Some(_) = it.next() {
|
||||||
ret = format!("{}<{}>{}", ret, o.name(),
|
ret = format!("{}<{}>{}",
|
||||||
if it.peek().is_some() {
|
ret,
|
||||||
" "
|
o.name(),
|
||||||
} else {
|
if it.peek().is_some() { " " } else { "" });
|
||||||
""
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if o.is_set(ArgSettings::Multiple) && num == 1 {
|
if o.is_set(ArgSettings::Multiple) && num == 1 {
|
||||||
ret = format!("{}...", ret);
|
ret = format!("{}...", ret);
|
||||||
|
@ -350,11 +382,11 @@ fn gen_fish_inner(root_command: &str,
|
||||||
for option in &comp_gen.p.opts {
|
for option in &comp_gen.p.opts {
|
||||||
let mut template = format!("complete -c {}", root_command);
|
let mut template = format!("complete -c {}", root_command);
|
||||||
if !parent_cmds.is_empty() {
|
if !parent_cmds.is_empty() {
|
||||||
template.push_str(format!(" -n '__fish_seen_subcommand_from {}'",
|
template.push_str(format!(" -n '__fish_seen_subcommand_from {}'", command).as_str());
|
||||||
command).as_str());
|
|
||||||
} else if has_no_subcommand_fn {
|
} else if has_no_subcommand_fn {
|
||||||
template.push_str(format!(" -n '__fish_{}_no_subcommand'",
|
template.push_str(format!(" -n '__fish_{}_no_subcommand'",
|
||||||
comp_gen.p.meta.bin_name.as_ref().unwrap()).as_str());
|
comp_gen.p.meta.bin_name.as_ref().unwrap())
|
||||||
|
.as_str());
|
||||||
}
|
}
|
||||||
if let Some(data) = option.short {
|
if let Some(data) = option.short {
|
||||||
template.push_str(format!(" -s {}", data).as_str());
|
template.push_str(format!(" -s {}", data).as_str());
|
||||||
|
@ -375,11 +407,11 @@ fn gen_fish_inner(root_command: &str,
|
||||||
for flag in &comp_gen.p.flags {
|
for flag in &comp_gen.p.flags {
|
||||||
let mut template = format!("complete -c {}", root_command);
|
let mut template = format!("complete -c {}", root_command);
|
||||||
if !parent_cmds.is_empty() {
|
if !parent_cmds.is_empty() {
|
||||||
template.push_str(format!(" -n '__fish_seen_subcommand_from {}'",
|
template.push_str(format!(" -n '__fish_seen_subcommand_from {}'", command).as_str());
|
||||||
command).as_str());
|
|
||||||
} else if has_no_subcommand_fn {
|
} else if has_no_subcommand_fn {
|
||||||
template.push_str(format!(" -n '__fish_{}_no_subcommand'",
|
template.push_str(format!(" -n '__fish_{}_no_subcommand'",
|
||||||
comp_gen.p.meta.bin_name.as_ref().unwrap()).as_str());
|
comp_gen.p.meta.bin_name.as_ref().unwrap())
|
||||||
|
.as_str());
|
||||||
}
|
}
|
||||||
if let Some(data) = flag.short {
|
if let Some(data) = flag.short {
|
||||||
template.push_str(format!(" -s {}", data).as_str());
|
template.push_str(format!(" -s {}", data).as_str());
|
||||||
|
@ -399,10 +431,12 @@ fn gen_fish_inner(root_command: &str,
|
||||||
let mut template = format!("complete -c {}", root_command);
|
let mut template = format!("complete -c {}", root_command);
|
||||||
if !parent_cmds.is_empty() {
|
if !parent_cmds.is_empty() {
|
||||||
template.push_str(format!(" -n '__fish_seen_subcommand_from {}'",
|
template.push_str(format!(" -n '__fish_seen_subcommand_from {}'",
|
||||||
subcommand).as_str());
|
subcommand)
|
||||||
|
.as_str());
|
||||||
} else if has_no_subcommand_fn {
|
} else if has_no_subcommand_fn {
|
||||||
template.push_str(format!(" -n '__fish_{}_no_subcommand'",
|
template.push_str(format!(" -n '__fish_{}_no_subcommand'",
|
||||||
comp_gen.p.meta.bin_name.as_ref().unwrap()).as_str());
|
comp_gen.p.meta.bin_name.as_ref().unwrap())
|
||||||
|
.as_str());
|
||||||
}
|
}
|
||||||
template.push_str(" -f");
|
template.push_str(" -f");
|
||||||
template.push_str(format!(" -a '{}'", subcommand).as_str());
|
template.push_str(format!(" -a '{}'", subcommand).as_str());
|
||||||
|
|
102
src/errors.rs
102
src/errors.rs
|
@ -1,14 +1,17 @@
|
||||||
use std::process;
|
// Std
|
||||||
|
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
use args::any_arg::AnyArg;
|
||||||
|
use fmt;
|
||||||
|
use std::convert::From;
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
use std::fmt as std_fmt;
|
use std::fmt as std_fmt;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::convert::From;
|
use std::process;
|
||||||
use std::result::Result as StdResult;
|
use std::result::Result as StdResult;
|
||||||
|
|
||||||
use fmt;
|
|
||||||
use suggestions;
|
use suggestions;
|
||||||
use args::any_arg::AnyArg;
|
|
||||||
|
|
||||||
/// Short hand for [`Result`] type
|
/// Short hand for [`Result`] type
|
||||||
/// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
|
/// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
|
||||||
|
@ -383,7 +386,11 @@ impl Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn argument_conflict<'a, 'b, A, O, U>(arg: &A, other: Option<O>, usage: U, color: fmt::ColorWhen) -> Self
|
pub fn argument_conflict<'a, 'b, A, O, U>(arg: &A,
|
||||||
|
other: Option<O>,
|
||||||
|
usage: U,
|
||||||
|
color: fmt::ColorWhen)
|
||||||
|
-> Self
|
||||||
where A: AnyArg<'a, 'b> + Display,
|
where A: AnyArg<'a, 'b> + Display,
|
||||||
O: Into<String>,
|
O: Into<String>,
|
||||||
U: Display
|
U: Display
|
||||||
|
@ -391,7 +398,7 @@ impl Error {
|
||||||
let mut v = vec![arg.name().to_owned()];
|
let mut v = vec![arg.name().to_owned()];
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} The argument '{}' cannot be used with {}\n\n\
|
message: format!("{} The argument '{}' cannot be used with {}\n\n\
|
||||||
|
@ -405,12 +412,15 @@ impl Error {
|
||||||
v.push(n.clone());
|
v.push(n.clone());
|
||||||
c.warning(format!("'{}'", n))
|
c.warning(format!("'{}'", n))
|
||||||
}
|
}
|
||||||
None => c.none("one or more of the other specified arguments".to_owned()),
|
None => {
|
||||||
|
c.none("one or more of the other specified arguments"
|
||||||
|
.to_owned())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
usage,
|
usage,
|
||||||
c.good("--help")),
|
c.good("--help")),
|
||||||
kind: ErrorKind::ArgumentConflict,
|
kind: ErrorKind::ArgumentConflict,
|
||||||
info: Some(v)
|
info: Some(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,7 +431,7 @@ impl Error {
|
||||||
{
|
{
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} The argument '{}' requires a value but none was supplied\
|
message: format!("{} The argument '{}' requires a value but none was supplied\
|
||||||
|
@ -438,7 +448,12 @@ impl Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn invalid_value<'a, 'b, B, G, A, U>(bad_val: B, good_vals: &[G], arg: &A, usage: U, color: fmt::ColorWhen) -> Self
|
pub fn invalid_value<'a, 'b, B, G, A, U>(bad_val: B,
|
||||||
|
good_vals: &[G],
|
||||||
|
arg: &A,
|
||||||
|
usage: U,
|
||||||
|
color: fmt::ColorWhen)
|
||||||
|
-> Self
|
||||||
where B: AsRef<str>,
|
where B: AsRef<str>,
|
||||||
G: AsRef<str> + Display,
|
G: AsRef<str> + Display,
|
||||||
A: AnyArg<'a, 'b> + Display,
|
A: AnyArg<'a, 'b> + Display,
|
||||||
|
@ -446,7 +461,7 @@ impl Error {
|
||||||
{
|
{
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
let suffix =
|
let suffix =
|
||||||
suggestions::did_you_mean_suffix(bad_val.as_ref(),
|
suggestions::did_you_mean_suffix(bad_val.as_ref(),
|
||||||
|
@ -479,7 +494,12 @@ impl Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn invalid_subcommand<S, D, N, U>(subcmd: S, did_you_mean: D, name: N, usage: U, color: fmt::ColorWhen) -> Self
|
pub fn invalid_subcommand<S, D, N, U>(subcmd: S,
|
||||||
|
did_you_mean: D,
|
||||||
|
name: N,
|
||||||
|
usage: U,
|
||||||
|
color: fmt::ColorWhen)
|
||||||
|
-> Self
|
||||||
where S: Into<String>,
|
where S: Into<String>,
|
||||||
D: AsRef<str> + Display,
|
D: AsRef<str> + Display,
|
||||||
N: Display,
|
N: Display,
|
||||||
|
@ -488,7 +508,7 @@ impl Error {
|
||||||
let s = subcmd.into();
|
let s = subcmd.into();
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} The subcommand '{}' wasn't recognized\n\t\
|
message: format!("{} The subcommand '{}' wasn't recognized\n\t\
|
||||||
|
@ -518,7 +538,7 @@ impl Error {
|
||||||
let s = subcmd.into();
|
let s = subcmd.into();
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} The subcommand '{}' wasn't recognized\n\n\
|
message: format!("{} The subcommand '{}' wasn't recognized\n\n\
|
||||||
|
@ -542,7 +562,7 @@ impl Error {
|
||||||
{
|
{
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} The following required arguments were not provided:{}\n\n\
|
message: format!("{} The following required arguments were not provided:{}\n\n\
|
||||||
|
@ -564,7 +584,7 @@ impl Error {
|
||||||
{
|
{
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} '{}' requires a subcommand, but one was not provided\n\n\
|
message: format!("{} '{}' requires a subcommand, but one was not provided\n\n\
|
||||||
|
@ -586,7 +606,7 @@ impl Error {
|
||||||
{
|
{
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} Invalid UTF-8 was detected in one or more arguments\n\n\
|
message: format!("{} Invalid UTF-8 was detected in one or more arguments\n\n\
|
||||||
|
@ -601,7 +621,11 @@ impl Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn too_many_values<'a, 'b, V, A, U>(val: V, arg: &A, usage: U, color: fmt::ColorWhen) -> Self
|
pub fn too_many_values<'a, 'b, V, A, U>(val: V,
|
||||||
|
arg: &A,
|
||||||
|
usage: U,
|
||||||
|
color: fmt::ColorWhen)
|
||||||
|
-> Self
|
||||||
where V: AsRef<str> + Display + ToOwned,
|
where V: AsRef<str> + Display + ToOwned,
|
||||||
A: AnyArg<'a, 'b> + Display,
|
A: AnyArg<'a, 'b> + Display,
|
||||||
U: Display
|
U: Display
|
||||||
|
@ -609,7 +633,7 @@ impl Error {
|
||||||
let v = val.as_ref();
|
let v = val.as_ref();
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} The value '{}' was provided to '{}', but it wasn't expecting \
|
message: format!("{} The value '{}' was provided to '{}', but it wasn't expecting \
|
||||||
|
@ -627,13 +651,18 @@ impl Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn too_few_values<'a, 'b, A, U>(arg: &A, min_vals: u64, curr_vals: usize, usage: U, color: fmt::ColorWhen) -> Self
|
pub fn too_few_values<'a, 'b, A, U>(arg: &A,
|
||||||
|
min_vals: u64,
|
||||||
|
curr_vals: usize,
|
||||||
|
usage: U,
|
||||||
|
color: fmt::ColorWhen)
|
||||||
|
-> Self
|
||||||
where A: AnyArg<'a, 'b> + Display,
|
where A: AnyArg<'a, 'b> + Display,
|
||||||
U: Display
|
U: Display
|
||||||
{
|
{
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} The argument '{}' requires at least {} values, but only {} w{} \
|
message: format!("{} The argument '{}' requires at least {} values, but only {} w{} \
|
||||||
|
@ -644,11 +673,7 @@ impl Error {
|
||||||
c.warning(arg.to_string()),
|
c.warning(arg.to_string()),
|
||||||
c.warning(min_vals.to_string()),
|
c.warning(min_vals.to_string()),
|
||||||
c.warning(curr_vals.to_string()),
|
c.warning(curr_vals.to_string()),
|
||||||
if curr_vals > 1 {
|
if curr_vals > 1 { "ere" } else { "as" },
|
||||||
"ere"
|
|
||||||
} else {
|
|
||||||
"as"
|
|
||||||
},
|
|
||||||
usage,
|
usage,
|
||||||
c.good("--help")),
|
c.good("--help")),
|
||||||
kind: ErrorKind::TooFewValues,
|
kind: ErrorKind::TooFewValues,
|
||||||
|
@ -660,7 +685,7 @@ impl Error {
|
||||||
pub fn value_validation(err: String, color: fmt::ColorWhen) -> Self {
|
pub fn value_validation(err: String, color: fmt::ColorWhen) -> Self {
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} {}", c.error("error:"), err),
|
message: format!("{} {}", c.error("error:"), err),
|
||||||
|
@ -679,7 +704,8 @@ impl Error {
|
||||||
num_vals: u64,
|
num_vals: u64,
|
||||||
curr_vals: usize,
|
curr_vals: usize,
|
||||||
suffix: S,
|
suffix: S,
|
||||||
usage: U, color: fmt::ColorWhen)
|
usage: U,
|
||||||
|
color: fmt::ColorWhen)
|
||||||
-> Self
|
-> Self
|
||||||
where A: AnyArg<'a, 'b> + Display,
|
where A: AnyArg<'a, 'b> + Display,
|
||||||
S: Display,
|
S: Display,
|
||||||
|
@ -687,7 +713,7 @@ impl Error {
|
||||||
{
|
{
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} The argument '{}' requires {} values, but {} w{} \
|
message: format!("{} The argument '{}' requires {} values, but {} w{} \
|
||||||
|
@ -713,7 +739,7 @@ impl Error {
|
||||||
{
|
{
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} The argument '{}' was provided more than once, but cannot \
|
message: format!("{} The argument '{}' was provided more than once, but cannot \
|
||||||
|
@ -730,14 +756,18 @@ impl Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn unknown_argument<A, U>(arg: A, did_you_mean: &str, usage: U, color: fmt::ColorWhen) -> Self
|
pub fn unknown_argument<A, U>(arg: A,
|
||||||
|
did_you_mean: &str,
|
||||||
|
usage: U,
|
||||||
|
color: fmt::ColorWhen)
|
||||||
|
-> Self
|
||||||
where A: Into<String>,
|
where A: Into<String>,
|
||||||
U: Display
|
U: Display
|
||||||
{
|
{
|
||||||
let a = arg.into();
|
let a = arg.into();
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} Found argument '{}' which wasn't expected, or isn't valid in \
|
message: format!("{} Found argument '{}' which wasn't expected, or isn't valid in \
|
||||||
|
@ -762,7 +792,7 @@ impl Error {
|
||||||
pub fn io_error(e: &Error, color: fmt::ColorWhen) -> Self {
|
pub fn io_error(e: &Error, color: fmt::ColorWhen) -> Self {
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: color
|
when: color,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} {}", c.error("error:"), e.description()),
|
message: format!("{} {}", c.error("error:"), e.description()),
|
||||||
|
@ -778,7 +808,7 @@ impl Error {
|
||||||
let a = arg.into();
|
let a = arg.into();
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: fmt::ColorWhen::Auto
|
when: fmt::ColorWhen::Auto,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} The argument '{}' wasn't found",
|
message: format!("{} The argument '{}' wasn't found",
|
||||||
|
@ -796,7 +826,7 @@ impl Error {
|
||||||
pub fn with_description(description: &str, kind: ErrorKind) -> Self {
|
pub fn with_description(description: &str, kind: ErrorKind) -> Self {
|
||||||
let c = fmt::Colorizer {
|
let c = fmt::Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: fmt::ColorWhen::Auto
|
when: fmt::ColorWhen::Auto,
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{} {}", c.error("error:"), description),
|
message: format!("{} {}", c.error("error:"), description),
|
||||||
|
|
38
src/fmt.rs
38
src/fmt.rs
|
@ -1,12 +1,11 @@
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
|
||||||
use ansi_term::Colour::{Green, Red, Yellow};
|
|
||||||
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
||||||
use ansi_term::ANSIString;
|
use ansi_term::ANSIString;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
||||||
|
use ansi_term::Colour::{Green, Red, Yellow};
|
||||||
|
|
||||||
#[cfg(feature = "color")]
|
#[cfg(feature = "color")]
|
||||||
use libc;
|
use libc;use std::fmt;
|
||||||
|
|
||||||
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
||||||
const STDERR: i32 = libc::STDERR_FILENO;
|
const STDERR: i32 = libc::STDERR_FILENO;
|
||||||
|
@ -23,7 +22,7 @@ const STDOUT: i32 = 0;
|
||||||
pub enum ColorWhen {
|
pub enum ColorWhen {
|
||||||
Auto,
|
Auto,
|
||||||
Always,
|
Always,
|
||||||
Never
|
Never,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "color")]
|
#[cfg(feature = "color")]
|
||||||
|
@ -43,7 +42,7 @@ pub fn is_a_tty(_: bool) -> bool {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct Colorizer {
|
pub struct Colorizer {
|
||||||
pub use_stderr: bool,
|
pub use_stderr: bool,
|
||||||
pub when: ColorWhen
|
pub when: ColorWhen,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! color {
|
macro_rules! color {
|
||||||
|
@ -61,22 +60,30 @@ macro_rules! color {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Colorizer {
|
impl Colorizer {
|
||||||
pub fn good<T>(&self, msg: T) -> Format<T> where T: fmt::Display + AsRef<str> {
|
pub fn good<T>(&self, msg: T) -> Format<T>
|
||||||
|
where T: fmt::Display + AsRef<str>
|
||||||
|
{
|
||||||
debugln!("exec=good;");
|
debugln!("exec=good;");
|
||||||
color!(self, Good, msg)
|
color!(self, Good, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn warning<T>(&self, msg: T) -> Format<T> where T: fmt::Display + AsRef<str> {
|
pub fn warning<T>(&self, msg: T) -> Format<T>
|
||||||
|
where T: fmt::Display + AsRef<str>
|
||||||
|
{
|
||||||
debugln!("exec=warning;");
|
debugln!("exec=warning;");
|
||||||
color!(self, Warning, msg)
|
color!(self, Warning, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error<T>(&self, msg: T) -> Format<T> where T: fmt::Display + AsRef<str> {
|
pub fn error<T>(&self, msg: T) -> Format<T>
|
||||||
|
where T: fmt::Display + AsRef<str>
|
||||||
|
{
|
||||||
debugln!("exec=error;");
|
debugln!("exec=error;");
|
||||||
color!(self, Error, msg)
|
color!(self, Error, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn none<T>(&self, msg: T) -> Format<T> where T: fmt::Display + AsRef<str> {
|
pub fn none<T>(&self, msg: T) -> Format<T>
|
||||||
|
where T: fmt::Display + AsRef<str>
|
||||||
|
{
|
||||||
debugln!("exec=none;");
|
debugln!("exec=none;");
|
||||||
Format::None(msg)
|
Format::None(msg)
|
||||||
}
|
}
|
||||||
|
@ -86,7 +93,7 @@ impl Default for Colorizer {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Colorizer {
|
Colorizer {
|
||||||
use_stderr: true,
|
use_stderr: true,
|
||||||
when: ColorWhen::Auto
|
when: ColorWhen::Auto,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,9 +154,9 @@ impl<T: fmt::Display> fmt::Display for Format<T> {
|
||||||
|
|
||||||
#[cfg(all(test, feature = "color", not(target_os = "windows")))]
|
#[cfg(all(test, feature = "color", not(target_os = "windows")))]
|
||||||
mod test {
|
mod test {
|
||||||
use super::Format;
|
|
||||||
use ansi_term::Colour::{Green, Red, Yellow};
|
|
||||||
use ansi_term::ANSIString;
|
use ansi_term::ANSIString;
|
||||||
|
use ansi_term::Colour::{Green, Red, Yellow};
|
||||||
|
use super::Format;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn colored_output() {
|
fn colored_output() {
|
||||||
|
@ -161,6 +168,7 @@ mod test {
|
||||||
let warn = Format::Warning("warn");
|
let warn = Format::Warning("warn");
|
||||||
assert_eq!(&*format!("{}", warn), &*format!("{}", Yellow.paint("warn")));
|
assert_eq!(&*format!("{}", warn), &*format!("{}", Yellow.paint("warn")));
|
||||||
let none = Format::None("none");
|
let none = Format::None("none");
|
||||||
assert_eq!(&*format!("{}", none), &*format!("{}", ANSIString::from("none")));
|
assert_eq!(&*format!("{}", none),
|
||||||
|
&*format!("{}", ANSIString::from("none")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
use std::ffi::OsStr;
|
#[cfg(target_os = "windows")]
|
||||||
|
use INVALID_UTF8;use std::ffi::OsStr;
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
use INVALID_UTF8;
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
trait OsStrExt3 {
|
trait OsStrExt3 {
|
||||||
fn from_bytes(b: &[u8]) -> &Self;
|
fn from_bytes(b: &[u8]) -> &Self;
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
use vec_map::VecMap;
|
// Third Party
|
||||||
|
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
|
||||||
|
use INTERNAL_ERROR_MSG;
|
||||||
use args::Arg;
|
use args::Arg;
|
||||||
use args::settings::ArgSettings;
|
use args::settings::ArgSettings;
|
||||||
use INTERNAL_ERROR_MSG;
|
use vec_map::VecMap;
|
||||||
|
|
||||||
type ParseResult = Result<(), ()>;
|
type ParseResult = Result<(), ()>;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue