Revert "Auto merge of #737 - kbknapp:questionmark, r=kbknapp"

This reverts commit f24a3760e4, reversing
changes made to 087cee7404.
This commit is contained in:
Kevin K 2016-11-12 12:12:05 -05:00
parent f24a3760e4
commit 7cb44abc09
No known key found for this signature in database
GPG key ID: 17218E4B3692F01A
20 changed files with 352 additions and 371 deletions

View file

@ -2,7 +2,7 @@ sudo: true
language: rust language: rust
rust: rust:
- nightly - nightly
- nightly-2016-11-06 - nightly-2016-10-21
- beta - beta
- stable - stable
matrix: matrix:

View file

@ -1,7 +1,7 @@
[package] [package]
name = "clap" name = "clap"
version = "2.19.0" version = "2.18.0"
authors = ["Kevin K. <kbknapp@gmail.com>"] authors = ["Kevin K. <kbknapp@gmail.com>"]
exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"] exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"]
repository = "https://github.com/kbknapp/clap-rs.git" repository = "https://github.com/kbknapp/clap-rs.git"
@ -24,7 +24,7 @@ ansi_term = { version = "~0.9.0", optional = true }
term_size = { version = "~0.2.0", optional = true } term_size = { version = "~0.2.0", optional = true }
libc = { version = "~0.2.9", optional = true } libc = { version = "~0.2.9", optional = true }
yaml-rust = { version = "~0.3.2", optional = true } yaml-rust = { version = "~0.3.2", optional = true }
clippy = { version = "~0.0.98", optional = true } clippy = { version = "~0.0.96", optional = true }
[dev-dependencies] [dev-dependencies]
regex = "~0.1.69" regex = "~0.1.69"

View file

@ -7,13 +7,3 @@ update-contributors:
@echo "" >> CONTRIBUTORS.md @echo "" >> CONTRIBUTORS.md
@githubcontrib --owner kbknapp --repo clap-rs --sha master --cols 6 --format md --showlogin true --sortBy login >> CONTRIBUTORS.md @githubcontrib --owner kbknapp --repo clap-rs --sha master --cols 6 --format md --showlogin true --sortBy login >> CONTRIBUTORS.md
@rm CONTRIBUTORS.md.bak @rm CONTRIBUTORS.md.bak
run-test TEST:
cargo test --test {{TEST}}
run-tests:
cargo test --features "yaml unstable"
lint:
rustup override add nightly
cargo build --features lints && rustup override remove

View file

@ -106,13 +106,10 @@ impl<'a> Help<'a> {
hide_pv: hide_pv, hide_pv: hide_pv,
term_w: match term_w { term_w: match term_w {
Some(width) => if width == 0 { usize::MAX } else { width }, Some(width) => if width == 0 { usize::MAX } else { width },
None => { None => cmp::min(term_size::dimensions().map_or(120, |(w, _)| w), match max_w {
cmp::min(term_size::dimensions().map_or(120, |(w, _)| w), None | Some(0) => usize::MAX,
match max_w { Some(mw) => mw,
None | Some(0) => usize::MAX, }),
Some(mw) => mw,
})
}
}, },
color: color, color: color,
cizer: cizer, cizer: cizer,
@ -153,25 +150,18 @@ impl<'a> Help<'a> {
use_stderr: stderr, use_stderr: stderr,
when: parser.color(), when: parser.color(),
}; };
Self::new(w, Self::new(w, nlh, hide_v, color, cizer, parser.meta.term_w, parser.meta.max_w).write_help(parser)
nlh,
hide_v,
color,
cizer,
parser.meta.term_w,
parser.meta.max_w)
.write_help(parser)
} }
/// Writes the parser help to the wrapped stream. /// Writes the parser help to the wrapped stream.
pub fn write_help(&mut self, parser: &Parser) -> ClapResult<()> { pub fn write_help(&mut self, parser: &Parser) -> ClapResult<()> {
debugln!("fn=Help::write_help;"); debugln!("fn=Help::write_help;");
if let Some(h) = parser.meta.help_str { if let Some(h) = parser.meta.help_str {
write!(self.writer, "{}", h).map_err(Error::from)?; try!(write!(self.writer, "{}", h).map_err(Error::from));
} else if let Some(tmpl) = parser.meta.template { } else if let Some(tmpl) = parser.meta.template {
self.write_templated_help(parser, tmpl)?; try!(self.write_templated_help(&parser, tmpl));
} else { } else {
self.write_default_help(parser)?; try!(self.write_default_help(&parser));
} }
Ok(()) Ok(())
} }
@ -201,9 +191,9 @@ impl<'a> Help<'a> {
if first { if first {
first = false; first = false;
} else { } else {
self.writer.write(b"\n")?; try!(self.writer.write(b"\n"));
} }
self.write_arg(arg.as_base())?; try!(self.write_arg(arg.as_base()));
} }
Ok(()) Ok(())
} }
@ -218,8 +208,8 @@ impl<'a> Help<'a> {
let mut ord_m = VecMap::new(); let mut ord_m = VecMap::new();
// Determine the longest // Determine the longest
for arg in args.filter(|arg| { for arg in args.filter(|arg| {
// If it's NextLineHelp, but we don't care to compute how long because it may be // If it's NextLineHelp, but we don't care to compute how long because it may be
// NextLineHelp on purpose *because* it's so long and would throw off all other // NextLineHelp on purpose *because* it's so long and would throw off all other
// args alignment // args alignment
!arg.is_set(ArgSettings::Hidden) || arg.is_set(ArgSettings::NextLineHelp) !arg.is_set(ArgSettings::Hidden) || arg.is_set(ArgSettings::NextLineHelp)
}) { }) {
@ -237,28 +227,30 @@ impl<'a> Help<'a> {
if first { if first {
first = false; first = false;
} else { } else {
self.writer.write(b"\n")?; try!(self.writer.write(b"\n"));
} }
self.write_arg(arg.as_base())?; try!(self.write_arg(arg.as_base()));
} }
} }
Ok(()) Ok(())
} }
/// Writes help for an argument to the wrapped stream. /// Writes help for an argument to the wrapped stream.
fn write_arg<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> { fn write_arg<'b, 'c>(&mut self,
arg: &ArgWithDisplay<'b, 'c>)
-> io::Result<()> {
debugln!("fn=write_arg;"); debugln!("fn=write_arg;");
self.short(arg)?; try!(self.short(arg));
self.long(arg)?; try!(self.long(arg));
let spec_vals = self.val(arg)?; let spec_vals = try!(self.val(arg));
self.help(arg, &*spec_vals)?; try!(self.help(arg, &*spec_vals));
Ok(()) Ok(())
} }
/// Writes argument's short command to the wrapped stream. /// Writes argument's short command to the wrapped stream.
fn short<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> { fn short<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> {
debugln!("fn=short;"); debugln!("fn=short;");
write!(self.writer, "{}", TAB)?; try!(write!(self.writer, "{}", TAB));
if let Some(s) = arg.short() { if let Some(s) = arg.short() {
color!(self, "-{}", s, good) color!(self, "-{}", s, good)
} else if arg.has_switch() { } else if arg.has_switch() {
@ -277,16 +269,16 @@ impl<'a> Help<'a> {
if arg.takes_value() { if arg.takes_value() {
if let Some(l) = arg.long() { if let Some(l) = arg.long() {
if arg.short().is_some() { if arg.short().is_some() {
write!(self.writer, ", ")?; try!(write!(self.writer, ", "));
} }
color!(self, "--{}", l, good)? try!(color!(self, "--{}", l, good))
} }
write!(self.writer, " ")?; try!(write!(self.writer, " "));
} else if let Some(l) = arg.long() { } else if let Some(l) = arg.long() {
if arg.short().is_some() { if arg.short().is_some() {
write!(self.writer, ", ")?; try!(write!(self.writer, ", "));
} }
color!(self, "--{}", l, good)?; try!(color!(self, "--{}", l, good));
} }
Ok(()) Ok(())
} }
@ -298,33 +290,33 @@ impl<'a> Help<'a> {
if let Some(vec) = arg.val_names() { if let Some(vec) = arg.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() {
color!(self, "<{}>", val, good)?; try!(color!(self, "<{}>", val, good));
if it.peek().is_some() { if it.peek().is_some() {
write!(self.writer, " ")?; try!(write!(self.writer, " "));
} }
} }
let num = vec.len(); let num = vec.len();
if arg.is_set(ArgSettings::Multiple) && num == 1 { if arg.is_set(ArgSettings::Multiple) && num == 1 {
color!(self, "...", good)?; try!(color!(self, "...", good));
} }
} else if let Some(num) = arg.num_vals() { } else if let Some(num) = arg.num_vals() {
let mut it = (0..num).peekable(); let mut it = (0..num).peekable();
while let Some(_) = it.next() { while let Some(_) = it.next() {
color!(self, "<{}>", arg.name(), good)?; try!(color!(self, "<{}>", arg.name(), good));
if it.peek().is_some() { if it.peek().is_some() {
write!(self.writer, " ")?; try!(write!(self.writer, " "));
} }
} }
if arg.is_set(ArgSettings::Multiple) && num == 1 { if arg.is_set(ArgSettings::Multiple) && num == 1 {
color!(self, "...", good)?; try!(color!(self, "...", good));
} }
} else if arg.has_switch() { } else if arg.has_switch() {
color!(self, "<{}>", arg.name(), good)?; try!(color!(self, "<{}>", arg.name(), good));
if arg.is_set(ArgSettings::Multiple) { if arg.is_set(ArgSettings::Multiple) {
color!(self, "...", good)?; try!(color!(self, "...", good));
} }
} else { } else {
color!(self, "{}", arg, good)?; try!(color!(self, "{}", arg, good));
} }
} }
@ -334,8 +326,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 taken = self.longest + 12; let taken = self.longest + 12;
self.force_next_line = !nlh && self.term_w >= taken && self.force_next_line = !nlh && self.term_w >= taken &&
(taken as f32 / self.term_w as f32) > 0.40 && (taken as f32 / self.term_w as f32) > 0.40 &&
h_w > (self.term_w - taken); h_w > (self.term_w - taken);
debug!("Has switch..."); debug!("Has switch...");
if arg.has_switch() { if arg.has_switch() {
@ -343,10 +335,7 @@ impl<'a> Help<'a> {
debugln!("force_next_line...{:?}", self.force_next_line); debugln!("force_next_line...{:?}", self.force_next_line);
debugln!("nlh...{:?}", nlh); debugln!("nlh...{:?}", nlh);
debugln!("taken...{}", taken); debugln!("taken...{}", taken);
debugln!("help_width > (width - taken)...{} > ({} - {})", debugln!("help_width > (width - taken)...{} > ({} - {})", h_w, self.term_w, taken);
h_w,
self.term_w,
taken);
debugln!("longest...{}", self.longest); debugln!("longest...{}", self.longest);
debug!("next_line..."); debug!("next_line...");
if !(nlh || self.force_next_line) { if !(nlh || self.force_next_line) {
@ -414,13 +403,13 @@ impl<'a> Help<'a> {
}; };
if help.contains('\n') { if help.contains('\n') {
if let Some(part) = help.lines().next() { if let Some(part) = help.lines().next() {
write!(self.writer, "{}", part)?; try!(write!(self.writer, "{}", part));
} }
for part in help.lines().skip(1) { for part in help.lines().skip(1) {
write!(self.writer, "\n{}", part)?; try!(write!(self.writer, "\n{}", part));
} }
} else { } else {
write!(self.writer, "{}", help)?; try!(write!(self.writer, "{}", help));
} }
Ok(()) Ok(())
} }
@ -443,7 +432,7 @@ impl<'a> Help<'a> {
// Is help on next line, if so then indent // Is help on next line, if so then indent
if nlh || self.force_next_line { if nlh || self.force_next_line {
write!(self.writer, "\n{}{}{}", TAB, TAB, TAB)?; try!(write!(self.writer, "\n{}{}{}", TAB, TAB, TAB));
} }
debug!("Too long..."); debug!("Too long...");
@ -481,21 +470,21 @@ impl<'a> Help<'a> {
}; };
if help.contains('\n') { if help.contains('\n') {
if let Some(part) = help.lines().next() { if let Some(part) = help.lines().next() {
write!(self.writer, "{}", part)?; try!(write!(self.writer, "{}", part));
} }
for part in help.lines().skip(1) { for part in help.lines().skip(1) {
write!(self.writer, "\n")?; try!(write!(self.writer, "\n"));
if nlh || self.force_next_line { if nlh || self.force_next_line {
write!(self.writer, "{}{}{}", TAB, TAB, TAB)?; try!(write!(self.writer, "{}{}{}", TAB, TAB, TAB));
} else if arg.has_switch() { } else if arg.has_switch() {
write_nspaces!(self.writer, self.longest + 12); write_nspaces!(self.writer, self.longest + 12);
} else { } else {
write_nspaces!(self.writer, self.longest + 8); write_nspaces!(self.writer, self.longest + 8);
} }
write!(self.writer, "{}", part)?; try!(write!(self.writer, "{}", part));
} }
} else { } else {
write!(self.writer, "{}", help)?; try!(write!(self.writer, "{}", help));
} }
Ok(()) Ok(())
} }
@ -506,24 +495,24 @@ impl<'a> Help<'a> {
if let Some(pv) = a.default_val() { if let Some(pv) = a.default_val() {
debugln!("Found default value...[{}]", pv); debugln!("Found default value...[{}]", pv);
spec_vals.push(format!(" [default: {}]", spec_vals.push(format!(" [default: {}]",
if self.color { if self.color {
self.cizer.good(pv) self.cizer.good(pv)
} else { } else {
Format::None(pv) Format::None(pv)
})); }));
} }
if let Some(ref aliases) = a.aliases() { if let Some(ref aliases) = a.aliases() {
debugln!("Found aliases...{:?}", aliases); debugln!("Found aliases...{:?}", aliases);
spec_vals.push(format!(" [aliases: {}]", spec_vals.push(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(", ")
})); }));
} }
if !self.hide_pv && !a.is_set(ArgSettings::HidePossibleValues) { if !self.hide_pv && !a.is_set(ArgSettings::HidePossibleValues) {
if let Some(pv) = a.possible_vals() { if let Some(pv) = a.possible_vals() {
debugln!("Found possible vals...{:?}", pv); debugln!("Found possible vals...{:?}", pv);
@ -563,40 +552,41 @@ impl<'a> Help<'a> {
let opts_flags = parser.flags() let opts_flags = parser.flags()
.map(as_arg_trait) .map(as_arg_trait)
.chain(parser.opts().map(as_arg_trait)); .chain(parser.opts().map(as_arg_trait));
color!(self, "OPTIONS:\n", warning)?; try!(color!(self, "OPTIONS:\n", warning));
self.write_args(opts_flags)?; try!(self.write_args(opts_flags));
first = false; first = false;
} else { } else {
if flags { if flags {
color!(self, "FLAGS:\n", warning)?; try!(color!(self, "FLAGS:\n", warning));
self.write_args(parser.flags().map(as_arg_trait))?; try!(self.write_args(parser.flags()
.map(as_arg_trait)));
first = false; first = false;
} }
if opts { if opts {
if !first { if !first {
self.writer.write(b"\n\n")?; try!(self.writer.write(b"\n\n"));
} }
color!(self, "OPTIONS:\n", warning)?; try!(color!(self, "OPTIONS:\n", warning));
self.write_args(parser.opts().map(as_arg_trait))?; try!(self.write_args(parser.opts().map(as_arg_trait)));
first = false; first = false;
} }
} }
if pos { if pos {
if !first { if !first {
self.writer.write(b"\n\n")?; try!(self.writer.write(b"\n\n"));
} }
color!(self, "ARGS:\n", warning)?; try!(color!(self, "ARGS:\n", warning));
self.write_args_unsorted(parser.positionals().map(as_arg_trait))?; try!(self.write_args_unsorted(parser.positionals().map(as_arg_trait)));
first = false; first = false;
} }
if subcmds { if subcmds {
if !first { if !first {
self.writer.write(b"\n\n")?; try!(self.writer.write(b"\n\n"));
} }
color!(self, "SUBCOMMANDS:\n", warning)?; try!(color!(self, "SUBCOMMANDS:\n", warning));
self.write_subcommands(parser)?; try!(self.write_subcommands(&parser));
} }
Ok(()) Ok(())
@ -620,9 +610,9 @@ impl<'a> Help<'a> {
if first { if first {
first = false; first = false;
} else { } else {
self.writer.write(b"\n")?; try!(self.writer.write(b"\n"));
} }
self.write_arg(sc)?; try!(self.write_arg(sc));
} }
} }
Ok(()) Ok(())
@ -630,7 +620,7 @@ impl<'a> Help<'a> {
/// Writes version of a Parser Object to the wrapped stream. /// Writes version of a Parser Object to the wrapped stream.
fn write_version(&mut self, parser: &Parser) -> io::Result<()> { fn write_version(&mut self, parser: &Parser) -> io::Result<()> {
write!(self.writer, "{}", parser.meta.version.unwrap_or("".into()))?; try!(write!(self.writer, "{}", parser.meta.version.unwrap_or("".into())));
Ok(()) Ok(())
} }
@ -639,12 +629,12 @@ impl<'a> Help<'a> {
if let Some(bn) = parser.meta.bin_name.as_ref() { if let Some(bn) = parser.meta.bin_name.as_ref() {
if bn.contains(' ') { if bn.contains(' ') {
// Incase we're dealing with subcommands i.e. git mv is translated to git-mv // Incase we're dealing with subcommands i.e. git mv is translated to git-mv
color!(self, bn.replace(" ", "-"), good)? try!(color!(self, bn.replace(" ", "-"), good))
} else { } else {
color!(self, &parser.meta.name[..], good)? try!(color!(self, &parser.meta.name[..], good))
} }
} else { } else {
color!(self, &parser.meta.name[..], good)? try!(color!(self, &parser.meta.name[..], good))
} }
Ok(()) Ok(())
} }
@ -653,27 +643,27 @@ impl<'a> Help<'a> {
pub fn write_default_help(&mut self, parser: &Parser) -> ClapResult<()> { pub fn write_default_help(&mut self, parser: &Parser) -> ClapResult<()> {
debugln!("fn=write_default_help;"); debugln!("fn=write_default_help;");
if let Some(h) = parser.meta.pre_help { if let Some(h) = parser.meta.pre_help {
self.write_before_after_help(h)?; try!(self.write_before_after_help(h));
self.writer.write(b"\n\n")?; try!(self.writer.write(b"\n\n"));
} }
// Print the version // Print the version
self.write_bin_name(parser)?; try!(self.write_bin_name(&parser));
self.writer.write(b" ")?; try!(self.writer.write(b" "));
self.write_version(parser)?; try!(self.write_version(&parser));
self.writer.write(b"\n")?; try!(self.writer.write(b"\n"));
if let Some(author) = parser.meta.author { if let Some(author) = parser.meta.author {
write!(self.writer, "{}\n", author)?; try!(write!(self.writer, "{}\n", author));
} }
if let Some(about) = parser.meta.about { if let Some(about) = parser.meta.about {
write!(self.writer, "{}\n", about)?; try!(write!(self.writer, "{}\n", about));
} }
color!(self, "\nUSAGE:", warning)?; try!(color!(self, "\nUSAGE:", warning));
write!(self.writer, try!(write!(self.writer,
"\n{}{}\n\n", "\n{}{}\n\n",
TAB, TAB,
parser.create_usage_no_title(&[]))?; parser.create_usage_no_title(&[])));
let flags = parser.has_flags(); let flags = parser.has_flags();
let pos = parser.has_positionals(); let pos = parser.has_positionals();
@ -681,14 +671,14 @@ impl<'a> Help<'a> {
let subcmds = parser.has_subcommands(); let subcmds = parser.has_subcommands();
if flags || opts || pos || subcmds { if flags || opts || pos || subcmds {
self.write_all_args(parser)?; try!(self.write_all_args(&parser));
} }
if let Some(h) = parser.meta.more_help { if let Some(h) = parser.meta.more_help {
if flags || opts || pos || subcmds { if flags || opts || pos || subcmds {
self.writer.write(b"\n\n")?; try!(self.writer.write(b"\n\n"));
} }
self.write_before_after_help(h)?; try!(self.write_before_after_help(h));
} }
self.writer.flush().map_err(Error::from) self.writer.flush().map_err(Error::from)
@ -847,65 +837,68 @@ impl<'a> Help<'a> {
}); });
match &tag_buf.get_ref()[0..tag_length] { match &tag_buf.get_ref()[0..tag_length] {
b"?" => { b"?" => {
self.writer.write(b"Could not decode tag name")?; try!(self.writer.write(b"Could not decode tag name"));
} }
b"bin" => { b"bin" => {
self.write_bin_name(parser)?; try!(self.write_bin_name(&parser));
} }
b"version" => { b"version" => {
write!(self.writer, try!(write!(self.writer,
"{}", "{}",
parser.meta.version.unwrap_or("unknown version"))?; parser.meta.version.unwrap_or("unknown version")));
} }
b"author" => { b"author" => {
write!(self.writer, try!(write!(self.writer,
"{}", "{}",
parser.meta.author.unwrap_or("unknown author"))?; parser.meta.author.unwrap_or("unknown author")));
} }
b"about" => { b"about" => {
write!(self.writer, try!(write!(self.writer,
"{}", "{}",
parser.meta.about.unwrap_or("unknown about"))?; parser.meta.about.unwrap_or("unknown about")));
} }
b"usage" => { b"usage" => {
write!(self.writer, "{}", parser.create_usage_no_title(&[]))?; try!(write!(self.writer, "{}", parser.create_usage_no_title(&[])));
} }
b"all-args" => { b"all-args" => {
self.write_all_args(parser)?; try!(self.write_all_args(&parser));
} }
b"unified" => { b"unified" => {
let opts_flags = parser.flags() let opts_flags = parser.flags()
.map(as_arg_trait) .map(as_arg_trait)
.chain(parser.opts().map(as_arg_trait)); .chain(parser.opts().map(as_arg_trait));
self.write_args(opts_flags)?; try!(self.write_args(opts_flags));
} }
b"flags" => { b"flags" => {
self.write_args(parser.flags().map(as_arg_trait))?; try!(self.write_args(parser.flags()
.map(as_arg_trait)));
} }
b"options" => { b"options" => {
self.write_args(parser.opts().map(as_arg_trait))?; try!(self.write_args(parser.opts()
.map(as_arg_trait)));
} }
b"positionals" => { b"positionals" => {
self.write_args(parser.positionals().map(as_arg_trait))?; try!(self.write_args(parser.positionals()
.map(as_arg_trait)));
} }
b"subcommands" => { b"subcommands" => {
self.write_subcommands(parser)?; try!(self.write_subcommands(&parser));
} }
b"after-help" => { b"after-help" => {
write!(self.writer, try!(write!(self.writer,
"{}", "{}",
parser.meta.more_help.unwrap_or("unknown after-help"))?; parser.meta.more_help.unwrap_or("unknown after-help")));
} }
b"before-help" => { b"before-help" => {
write!(self.writer, try!(write!(self.writer,
"{}", "{}",
parser.meta.pre_help.unwrap_or("unknown before-help"))?; parser.meta.pre_help.unwrap_or("unknown before-help")));
} }
// Unknown tag, write it back. // Unknown tag, write it back.
r => { r => {
self.writer.write(b"{")?; try!(self.writer.write(b"{"));
self.writer.write(r)?; try!(self.writer.write(r));
self.writer.write(b"}")?; try!(self.writer.write(b"}"));
} }
} }
} }

View file

@ -1344,7 +1344,7 @@ impl<'a, 'b> App<'a, 'b> {
let p = Path::new(&*bn_os); let p = Path::new(&*bn_os);
if let Some(f) = p.file_name() { if let Some(f) = p.file_name() {
if let Some(s) = f.to_os_string().to_str() { if let Some(s) = f.to_os_string().to_str() {
if self.p.meta.bin_name.is_none() { if let None = self.p.meta.bin_name {
self.p.meta.bin_name = Some(s.to_owned()); self.p.meta.bin_name = Some(s.to_owned());
} }
} }

View file

@ -507,7 +507,6 @@ impl<'a, 'b> Parser<'a, 'b>
self.settings.unset(s) self.settings.unset(s)
} }
#[cfg_attr(feature = "lints", allow(block_in_if_condition_stmt))]
pub fn verify_positionals(&mut self) { pub fn verify_positionals(&mut self) {
// Because you must wait until all arguments have been supplied, this is the first chance // Because you must wait until all arguments have been supplied, this is the first chance
// to make assertions on positional argument indexes // to make assertions on positional argument indexes
@ -740,7 +739,7 @@ impl<'a, 'b> Parser<'a, 'b>
if let Some(arg) = needs_val_of { if let Some(arg) = needs_val_of {
// get the OptBuilder so we can check the settings // get the OptBuilder so we can check the settings
if let Some(opt) = self.get_opt(arg) { if let Some(opt) = self.get_opt(arg) {
needs_val_of = self.add_val_to_arg(&*opt, &arg_os, matcher)?; needs_val_of = try!(self.add_val_to_arg(&*opt, &arg_os, matcher));
// get the next value from the iterator // get the next value from the iterator
continue; continue;
} }
@ -754,7 +753,7 @@ impl<'a, 'b> Parser<'a, 'b>
continue; continue;
} }
needs_val_of = self.parse_long_arg(matcher, &arg_os)?; needs_val_of = try!(self.parse_long_arg(matcher, &arg_os));
if !(needs_val_of.is_none() && self.is_set(AppSettings::AllowLeadingHyphen)) { if !(needs_val_of.is_none() && self.is_set(AppSettings::AllowLeadingHyphen)) {
continue; continue;
} }
@ -762,7 +761,7 @@ impl<'a, 'b> Parser<'a, 'b>
// Try to parse short args like normal, if AllowLeadingHyphen or // Try to parse short args like normal, if AllowLeadingHyphen or
// AllowNegativeNumbers is set, parse_short_arg will *not* throw // AllowNegativeNumbers is set, parse_short_arg will *not* throw
// an error, and instead return Ok(None) // an error, and instead return Ok(None)
needs_val_of = self.parse_short_arg(matcher, &arg_os)?; needs_val_of = try!(self.parse_short_arg(matcher, &arg_os));
// If it's None, we then check if one of those two AppSettings was set // If it's None, we then check if one of those two AppSettings was set
debugln!("AllowLeadingHyphen set...{:?}", self.is_set(AppSettings::AllowLeadingHyphen)); debugln!("AllowLeadingHyphen set...{:?}", self.is_set(AppSettings::AllowLeadingHyphen));
debugln!("AllowNegativeNumbers set...{:?}", self.is_set(AppSettings::AllowNegativeNumbers)); debugln!("AllowNegativeNumbers set...{:?}", self.is_set(AppSettings::AllowNegativeNumbers));
@ -787,7 +786,7 @@ impl<'a, 'b> Parser<'a, 'b>
if pos_sc { if pos_sc {
if &*arg_os == "help" && self.is_set(AppSettings::NeedsSubcommandHelp) { if &*arg_os == "help" && self.is_set(AppSettings::NeedsSubcommandHelp) {
self.parse_help_subcommand(it)?; try!(self.parse_help_subcommand(it));
} }
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;
@ -809,17 +808,14 @@ impl<'a, 'b> Parser<'a, 'b>
debugln!("Positional counter...{}", pos_counter); debugln!("Positional counter...{}", pos_counter);
debug!("Checking for low index multiples..."); debug!("Checking for low index multiples...");
if self.is_set(AppSettings::LowIndexMultiplePositional) && if self.is_set(AppSettings::LowIndexMultiplePositional) && pos_counter == (self.positionals.len() - 1) {
pos_counter == (self.positionals.len() - 1) {
sdebugln!("Found"); sdebugln!("Found");
if let Some(na) = it.peek() { if let Some(na) = it.peek() {
let n = (*na).clone().into(); let n = (*na).clone().into();
if is_new_arg(&n) || self.possible_subcommand(&n) || if is_new_arg(&n) || self.possible_subcommand(&n) || suggestions::did_you_mean(&n.to_string_lossy(),
suggestions::did_you_mean(&n.to_string_lossy(), self.subcommands
self.subcommands .iter()
.iter() .map(|s| &s.p.meta.name)).is_some() {
.map(|s| &s.p.meta.name))
.is_some() {
debugln!("Bumping the positional counter..."); debugln!("Bumping the positional counter...");
pos_counter += 1; pos_counter += 1;
} }
@ -849,9 +845,11 @@ impl<'a, 'b> Parser<'a, 'b>
let mut sc_m = ArgMatcher::new(); let mut sc_m = ArgMatcher::new();
while let Some(v) = it.next() { while let Some(v) = it.next() {
let a = v.into(); let a = v.into();
if a.to_str().is_none() && !self.settings.is_set(AppSettings::StrictUtf8) { if let None = a.to_str() {
if !self.settings.is_set(AppSettings::StrictUtf8) {
return Err(Error::invalid_utf8(&*self.create_current_usage(matcher), return Err(Error::invalid_utf8(&*self.create_current_usage(matcher),
self.color())); self.color()));
}
} }
sc_m.add_val_to("", &a); sc_m.add_val_to("", &a);
} }
@ -885,7 +883,7 @@ impl<'a, 'b> Parser<'a, 'b>
.any(|&(n, _)| n == &*a)) .any(|&(n, _)| n == &*a))
}) { }) {
sdebugln!("Yes"); sdebugln!("Yes");
self.validate_required(matcher)?; try!(self.validate_required(matcher));
reqs_validated = true; reqs_validated = true;
let should_err = if let Some(v) = matcher.0.args.get(&*o.name) { let should_err = if let Some(v) = matcher.0.args.get(&*o.name) {
v.vals.is_empty() && !(o.min_vals.is_some() && o.min_vals.unwrap() == 0) v.vals.is_empty() && !(o.min_vals.is_some() && o.min_vals.unwrap() == 0)
@ -909,14 +907,14 @@ impl<'a, 'b> Parser<'a, 'b>
} }
} }
self.add_defaults(matcher)?; try!(self.add_defaults(matcher));
self.validate_blacklist(matcher)?; try!(self.validate_blacklist(matcher));
self.validate_num_args(matcher)?; try!(self.validate_num_args(matcher));
matcher.usage(self.create_usage(&[])); matcher.usage(self.create_usage(&[]));
if !(self.settings.is_set(AppSettings::SubcommandsNegateReqs) && subcmd_name.is_some()) && if !(self.settings.is_set(AppSettings::SubcommandsNegateReqs) && subcmd_name.is_some()) &&
!reqs_validated { !reqs_validated {
self.validate_required(matcher)?; try!(self.validate_required(matcher));
} }
if let Some(pos_sc_name) = subcmd_name { if let Some(pos_sc_name) = subcmd_name {
// is this is a real subcommand, or an alias // is this is a real subcommand, or an alias
@ -940,7 +938,7 @@ impl<'a, 'b> Parser<'a, 'b>
.next() .next()
.expect(INTERNAL_ERROR_MSG) .expect(INTERNAL_ERROR_MSG)
}; };
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, return Err(Error::missing_subcommand(bn,
@ -948,7 +946,7 @@ impl<'a, 'b> Parser<'a, 'b>
self.color())); self.color()));
} else if self.is_set(AppSettings::SubcommandRequiredElseHelp) { } else if self.is_set(AppSettings::SubcommandRequiredElseHelp) {
let mut out = vec![]; let mut out = vec![];
self.write_help_err(&mut out)?; try!(self.write_help_err(&mut out));
return Err(Error { return Err(Error {
message: String::from_utf8_lossy(&*out).into_owned(), message: String::from_utf8_lossy(&*out).into_owned(),
kind: ErrorKind::MissingArgumentOrSubcommand, kind: ErrorKind::MissingArgumentOrSubcommand,
@ -958,7 +956,7 @@ impl<'a, 'b> Parser<'a, 'b>
if matcher.is_empty() && matcher.subcommand_name().is_none() && if matcher.is_empty() && matcher.subcommand_name().is_none() &&
self.is_set(AppSettings::ArgRequiredElseHelp) { self.is_set(AppSettings::ArgRequiredElseHelp) {
let mut out = vec![]; let mut out = vec![];
self.write_help_err(&mut out)?; try!(self.write_help_err(&mut out));
return Err(Error { return Err(Error {
message: String::from_utf8_lossy(&*out).into_owned(), message: String::from_utf8_lossy(&*out).into_owned(),
kind: ErrorKind::MissingArgumentOrSubcommand, kind: ErrorKind::MissingArgumentOrSubcommand,
@ -1051,7 +1049,7 @@ impl<'a, 'b> Parser<'a, 'b>
"" ""
}, },
&*sc.p.meta.name)); &*sc.p.meta.name));
sc.p.get_matches_with(&mut sc_matcher, it)?; try!(sc.p.get_matches_with(&mut sc_matcher, it));
matcher.subcommand(SubCommand { matcher.subcommand(SubCommand {
name: sc.p.meta.name.clone(), name: sc.p.meta.name.clone(),
matches: sc_matcher.into(), matches: sc_matcher.into(),
@ -1205,11 +1203,11 @@ impl<'a, 'b> Parser<'a, 'b>
arg.to_str().unwrap()); arg.to_str().unwrap());
if arg == "help" && self.settings.is_set(AppSettings::NeedsLongHelp) { if arg == "help" && self.settings.is_set(AppSettings::NeedsLongHelp) {
sdebugln!("Help"); sdebugln!("Help");
self._help()?; try!(self._help());
} }
if arg == "version" && self.settings.is_set(AppSettings::NeedsLongVersion) { if arg == "version" && self.settings.is_set(AppSettings::NeedsLongVersion) {
sdebugln!("Version"); sdebugln!("Version");
self._version()?; try!(self._version());
} }
sdebugln!("Neither"); sdebugln!("Neither");
@ -1221,13 +1219,13 @@ impl<'a, 'b> Parser<'a, 'b>
if let Some(h) = self.help_short { if let Some(h) = self.help_short {
if arg == h && self.settings.is_set(AppSettings::NeedsLongHelp) { if arg == h && self.settings.is_set(AppSettings::NeedsLongHelp) {
sdebugln!("Help"); sdebugln!("Help");
self._help()?; try!(self._help());
} }
} }
if let Some(v) = self.version_short { if let Some(v) = self.version_short {
if arg == v && self.settings.is_set(AppSettings::NeedsLongVersion) { if arg == v && self.settings.is_set(AppSettings::NeedsLongVersion) {
sdebugln!("Version"); sdebugln!("Version");
self._version()?; try!(self._version());
} }
} }
sdebugln!("Neither"); sdebugln!("Neither");
@ -1236,7 +1234,10 @@ impl<'a, 'b> Parser<'a, 'b>
fn _help(&self) -> ClapResult<()> { fn _help(&self) -> ClapResult<()> {
let mut buf = vec![]; let mut buf = vec![];
Help::write_parser_help(&mut buf, self)?; try!(Help::write_parser_help(&mut buf, self));
// let out = io::stdout();
// let mut out_buf = BufWriter::new(out.lock());
// try!(out_buf.write(&*buf));
Err(Error { Err(Error {
message: unsafe { String::from_utf8_unchecked(buf) }, message: unsafe { String::from_utf8_unchecked(buf) },
kind: ErrorKind::HelpDisplayed, kind: ErrorKind::HelpDisplayed,
@ -1247,7 +1248,7 @@ impl<'a, 'b> Parser<'a, 'b>
fn _version(&self) -> ClapResult<()> { fn _version(&self) -> ClapResult<()> {
let out = io::stdout(); let out = io::stdout();
let mut buf_w = BufWriter::new(out.lock()); let mut buf_w = BufWriter::new(out.lock());
self.print_version(&mut buf_w)?; try!(self.print_version(&mut buf_w));
Err(Error { Err(Error {
message: String::new(), message: String::new(),
kind: ErrorKind::VersionDisplayed, kind: ErrorKind::VersionDisplayed,
@ -1285,7 +1286,7 @@ impl<'a, 'b> Parser<'a, 'b>
.any(|&(n, _)| n == &*arg)) .any(|&(n, _)| n == &*arg))
}) { }) {
debugln!("Found valid opt '{}'", opt.to_string()); debugln!("Found valid opt '{}'", opt.to_string());
let ret = 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);
@ -1303,9 +1304,9 @@ impl<'a, 'b> Parser<'a, 'b>
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
self.check_for_help_and_version_str(arg)?; try!(self.check_for_help_and_version_str(&arg));
self.parse_flag(flag, matcher)?; try!(self.parse_flag(flag, matcher));
// Handle conflicts, requirements, etc. // Handle conflicts, requirements, etc.
arg_post_processing!(self, flag, matcher); arg_post_processing!(self, flag, matcher);
@ -1359,7 +1360,7 @@ impl<'a, 'b> Parser<'a, 'b>
}; };
// Default to "we're expecting a value later" // Default to "we're expecting a value later"
let ret = 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);
@ -1369,8 +1370,8 @@ impl<'a, 'b> Parser<'a, 'b>
.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
self.check_for_help_and_version_char(c)?; try!(self.check_for_help_and_version_char(c));
self.parse_flag(flag, matcher)?; try!(self.parse_flag(flag, matcher));
// Handle conflicts, requirements, overrides, etc. // Handle conflicts, requirements, overrides, etc.
// Must be called here due to mutablilty // Must be called here due to mutablilty
arg_post_processing!(self, flag, matcher); arg_post_processing!(self, flag, matcher);
@ -1409,7 +1410,7 @@ impl<'a, 'b> Parser<'a, 'b>
} }
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'=']));
self.add_val_to_arg(opt, v, matcher)?; try!(self.add_val_to_arg(opt, v, matcher));
} else { } else {
sdebugln!("None"); sdebugln!("None");
} }
@ -1439,10 +1440,10 @@ impl<'a, 'b> Parser<'a, 'b>
if !(self.trailing_vals && self.is_set(AppSettings::DontDelimitTrailingValues)) { if !(self.trailing_vals && self.is_set(AppSettings::DontDelimitTrailingValues)) {
if let Some(delim) = arg.val_delim() { if let Some(delim) = arg.val_delim() {
if val.is_empty_() { if val.is_empty_() {
ret = self.add_single_val_to_arg(arg, val, matcher)?; ret = try!(self.add_single_val_to_arg(arg, val, matcher));
} else { } else {
for v in val.split(delim as u32 as u8) { for v in val.split(delim as u32 as u8) {
ret = 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) || if val.contains_byte(delim as u32 as u8) ||
@ -1451,10 +1452,10 @@ impl<'a, 'b> Parser<'a, 'b>
} }
} }
} else { } else {
ret = self.add_single_val_to_arg(arg, val, matcher)?; ret = try!(self.add_single_val_to_arg(arg, val, matcher));
} }
} else { } else {
ret = self.add_single_val_to_arg(arg, val, matcher)?; ret = try!(self.add_single_val_to_arg(arg, val, matcher));
} }
Ok(ret) Ok(ret)
} }
@ -1605,11 +1606,11 @@ impl<'a, 'b> Parser<'a, 'b>
} 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) {
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) {
self._validate_num_vals(pos, ma, matcher)?; try!(self._validate_num_vals(pos, ma, matcher));
} }
} }
Ok(()) Ok(())
@ -1894,7 +1895,7 @@ impl<'a, 'b> Parser<'a, 'b>
// Prints the version to the user and exits if quit=true // Prints the version to the user and exits if quit=true
fn print_version<W: Write>(&self, w: &mut W) -> ClapResult<()> { fn print_version<W: Write>(&self, w: &mut W) -> ClapResult<()> {
self.write_version(w)?; try!(self.write_version(w));
w.flush().map_err(Error::from) w.flush().map_err(Error::from)
} }
@ -1938,9 +1939,9 @@ impl<'a, 'b> Parser<'a, 'b>
macro_rules! add_val { macro_rules! add_val {
($_self:ident, $a:ident, $m:ident) => { ($_self:ident, $a:ident, $m:ident) => {
if $m.get($a.name).is_none() { if $m.get($a.name).is_none() {
$_self.add_val_to_arg($a, OsStr::new($a.default_val try!($_self.add_val_to_arg($a, OsStr::new($a.default_val
.as_ref() .as_ref()
.unwrap()), $m)?; .unwrap()), $m));
arg_post_processing!($_self, $a, $m); arg_post_processing!($_self, $a, $m);
} }
}; };

View file

@ -363,7 +363,7 @@ pub enum AppSettings {
/// ``` /// ```
/// [`SubCommand`]: ./struct.SubCommand.html /// [`SubCommand`]: ./struct.SubCommand.html
DisableVersion, DisableVersion,
/// Displays the arguments and [`SubCommand`]s in the help message in the order that they were /// Displays the arguments and [`SubCommand`]s in the help message in the order that they were
/// declared in, and not alphabetically which is the default. /// declared in, and not alphabetically which is the default.
/// ///
@ -667,6 +667,7 @@ pub enum AppSettings {
#[doc(hidden)] #[doc(hidden)]
LowIndexMultiplePositional, LowIndexMultiplePositional,
} }
impl FromStr for AppSettings { impl FromStr for AppSettings {

View file

@ -1,6 +1,6 @@
// Std // Std
use std::rc::Rc; use std::rc::Rc;
use std::fmt as std_fmt; use std::fmt as std_fmt;
// Third Party // Third Party
use vec_map::VecMap; use vec_map::VecMap;

View file

@ -87,9 +87,9 @@ impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for FlagBuilder<'a, 'b> {
impl<'n, 'e> Display for FlagBuilder<'n, 'e> { impl<'n, 'e> Display for FlagBuilder<'n, 'e> {
fn fmt(&self, f: &mut Formatter) -> Result { fn fmt(&self, f: &mut Formatter) -> Result {
if let Some(l) = self.long { if let Some(l) = self.long {
write!(f, "--{}", l)?; try!(write!(f, "--{}", l));
} else { } else {
write!(f, "-{}", self.short.unwrap())?; try!(write!(f, "-{}", self.short.unwrap()));
} }
Ok(()) Ok(())
@ -180,9 +180,10 @@ impl<'n, 'e> AnyArg<'n, 'e> for FlagBuilder<'n, 'e> {
} }
fn aliases(&self) -> Option<Vec<&'e str>> { fn aliases(&self) -> Option<Vec<&'e str>> {
if let Some(ref aliases) = self.aliases { if let Some(ref aliases) = self.aliases {
let vis_aliases: Vec<_> = aliases.iter() let vis_aliases: Vec<_> =
.filter_map(|&(n, v)| if v { Some(n) } else { None }) aliases.iter()
.collect(); .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 {
@ -232,8 +233,12 @@ mod test {
fn flagbuilder_display_multiple_aliases() { fn flagbuilder_display_multiple_aliases() {
let mut f = FlagBuilder::new("flg"); let mut f = FlagBuilder::new("flg");
f.short = Some('f'); f.short = Some('f');
f.aliases = f.aliases = Some(vec![
Some(vec![("alias_not_visible", false), ("f2", true), ("f3", true), ("f4", true)]); ("alias_not_visible", false),
("f2", true),
("f3", true),
("f4", true)
]);
assert_eq!(&*format!("{}", f), "-f"); assert_eq!(&*format!("{}", f), "-f");
} }
} }

View file

@ -125,41 +125,41 @@ impl<'n, 'e> Display for OptBuilder<'n, 'e> {
debugln!("fn=fmt"); debugln!("fn=fmt");
// Write the name such --long or -l // Write the name such --long or -l
if let Some(l) = self.long { if let Some(l) = self.long {
write!(f, "--{} ", l)?; try!(write!(f, "--{} ", l));
} else { } else {
write!(f, "-{} ", self.short.unwrap())?; try!(write!(f, "-{} ", self.short.unwrap()));
} }
// Write the values such as <name1> <name2> // Write the values such as <name1> <name2>
if let Some(ref vec) = self.val_names { if let Some(ref vec) = self.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() {
write!(f, "<{}>", val)?; try!(write!(f, "<{}>", val));
if it.peek().is_some() { if it.peek().is_some() {
write!(f, " ")?; try!(write!(f, " "));
} }
} }
let num = vec.len(); let num = vec.len();
if self.is_set(ArgSettings::Multiple) && num == 1 { if self.is_set(ArgSettings::Multiple) && num == 1 {
write!(f, "...")?; try!(write!(f, "..."));
} }
} else if let Some(num) = self.num_vals { } else if let Some(num) = self.num_vals {
let mut it = (0..num).peekable(); let mut it = (0..num).peekable();
while let Some(_) = it.next() { while let Some(_) = it.next() {
write!(f, "<{}>", self.name)?; try!(write!(f, "<{}>", self.name));
if it.peek().is_some() { if it.peek().is_some() {
write!(f, " ")?; try!(write!(f, " "));
} }
} }
} else { } else {
write!(f, try!(write!(f,
"<{}>{}", "<{}>{}",
self.name, self.name,
if self.is_set(ArgSettings::Multiple) { if self.is_set(ArgSettings::Multiple) {
"..." "..."
} else { } else {
"" ""
})?; }));
} }
Ok(()) Ok(())
@ -259,9 +259,10 @@ impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> {
} }
fn aliases(&self) -> Option<Vec<&'e str>> { fn aliases(&self) -> Option<Vec<&'e str>> {
if let Some(ref aliases) = self.aliases { if let Some(ref aliases) = self.aliases {
let vis_aliases: Vec<_> = aliases.iter() let vis_aliases: Vec<_> =
.filter_map(|&(n, v)| if v { Some(n) } else { None }) aliases.iter()
.collect(); .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 {
@ -334,8 +335,12 @@ mod test {
fn optbuilder_display_multiple_aliases() { fn optbuilder_display_multiple_aliases() {
let mut o = OptBuilder::new("opt"); let mut o = OptBuilder::new("opt");
o.long = Some("option"); o.long = Some("option");
o.aliases = o.aliases = Some(vec![
Some(vec![("als_not_visible", false), ("als2", true), ("als3", true), ("als4", true)]); ("als_not_visible", false),
("als2", true),
("als3", true),
("als4", true)
]);
assert_eq!(&*format!("{}", o), "--option <opt>"); assert_eq!(&*format!("{}", o), "--option <opt>");
} }
} }

View file

@ -136,17 +136,17 @@ impl<'n, 'e> PosBuilder<'n, 'e> {
impl<'n, 'e> Display for PosBuilder<'n, 'e> { impl<'n, 'e> Display for PosBuilder<'n, 'e> {
fn fmt(&self, f: &mut Formatter) -> Result { fn fmt(&self, f: &mut Formatter) -> Result {
if let Some(ref names) = self.val_names { if let Some(ref names) = self.val_names {
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 {
write!(f, "<{}>", self.name)?; try!(write!(f, "<{}>", self.name));
} }
if self.settings.is_set(ArgSettings::Multiple) && self.val_names.is_none() { if self.settings.is_set(ArgSettings::Multiple) && self.val_names.is_none() {
write!(f, "...")?; try!(write!(f, "..."));
} }
Ok(()) Ok(())

View file

@ -19,7 +19,7 @@ impl<'a, 'b> BashGen<'a, 'b> {
pub fn generate_to<W: Write>(&self, buf: &mut W) { pub fn generate_to<W: Write>(&self, buf: &mut W) {
w!(buf, w!(buf,
format!("_{name}() {{ format!("_{name}() {{
local i cur prev opts cmds local i cur prev opts cmds
COMPREPLY=() COMPREPLY=()
@ -177,9 +177,9 @@ complete -F _{name} {name}
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 = format!("{}<{}>{}",
ret, ret,
val, val,
if it.peek().is_some() { " " } 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 {
@ -189,9 +189,9 @@ complete -F _{name} {name}
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 = format!("{}<{}>{}",
ret, ret,
o.name(), o.name(),
if it.peek().is_some() { " " } 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);

View file

@ -20,7 +20,8 @@ impl<'a, 'b> FishGen<'a, 'b> {
let command = self.p.meta.bin_name.as_ref().unwrap(); let command = self.p.meta.bin_name.as_ref().unwrap();
// function to detect subcommand // function to detect subcommand
let detect_subcommand_function = r#"function __fish_using_command let detect_subcommand_function =
r#"function __fish_using_command
set cmd (commandline -opc) set cmd (commandline -opc)
if [ (count $cmd) -eq (count $argv) ] if [ (count $cmd) -eq (count $argv) ]
for i in (seq (count $argv)) for i in (seq (count $argv))
@ -33,8 +34,7 @@ impl<'a, 'b> FishGen<'a, 'b> {
return 1 return 1
end end
"# "#.to_string();
.to_string();
let mut buffer = detect_subcommand_function; let mut buffer = detect_subcommand_function;
gen_fish_inner(command, self, &command.to_string(), &mut buffer); gen_fish_inner(command, self, &command.to_string(), &mut buffer);
@ -42,7 +42,10 @@ end
} }
} }
fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, parent_cmds: &str, buffer: &mut String) { fn gen_fish_inner(root_command: &str,
comp_gen: &FishGen,
parent_cmds: &str,
buffer: &mut String) {
// example : // example :
// //
// complete // complete
@ -56,8 +59,8 @@ fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, parent_cmds: &str, buf
// -n "__fish_using_command myprog subcmd1" # complete for command "myprog subcmd1" // -n "__fish_using_command myprog subcmd1" # complete for command "myprog subcmd1"
let basic_template = format!("complete -c {} -n \"__fish_using_command {}\"", let basic_template = format!("complete -c {} -n \"__fish_using_command {}\"",
root_command, root_command,
parent_cmds); parent_cmds);
for option in &comp_gen.p.opts { for option in &comp_gen.p.opts {
let mut template = basic_template.clone(); let mut template = basic_template.clone();
@ -109,6 +112,9 @@ fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, parent_cmds: &str, buf
sub_parent_cmds.push_str(" "); sub_parent_cmds.push_str(" ");
} }
sub_parent_cmds.push_str(&subcommand.p.meta.name); sub_parent_cmds.push_str(&subcommand.p.meta.name);
gen_fish_inner(root_command, &sub_comp_gen, &sub_parent_cmds, buffer); gen_fish_inner(root_command,
&sub_comp_gen,
&sub_parent_cmds,
buffer);
} }
} }

View file

@ -30,16 +30,16 @@ impl<'a, 'b> ComplGen<'a, 'b> {
pub fn generate<W: Write>(&self, for_shell: Shell, buf: &mut W) { pub fn generate<W: Write>(&self, for_shell: Shell, buf: &mut W) {
match for_shell { match for_shell {
Shell::Bash => BashGen::new(self.p).generate_to(buf), Shell::Bash => BashGen::new(self.p).generate_to(buf),
Shell::Fish => FishGen::new(self.p).generate_to(buf), Shell::Fish => FishGen::new(self.p).generate_to(buf),
Shell::Zsh => ZshGen::new(self.p).generate_to(buf), Shell::Zsh => ZshGen::new(self.p).generate_to(buf),
Shell::PowerShell => PowerShellGen::new(self.p).generate_to(buf), Shell::PowerShell => PowerShellGen::new(self.p).generate_to(buf),
} }
} }
} }
// Gets all subcommands including child subcommands in the form of 'name' where the name // Gets all subcommands including child subcommands in the form of 'name' where the name
// is a single word (i.e. "install") of the path to said subcommand (i.e. // is a single word (i.e. "install") of the path to said subcommand (i.e.
// "rustup toolchain install") // "rustup toolchain install")
// //
// Also note, aliases are treated as their own subcommands but duplicates of whatever they're // Also note, aliases are treated as their own subcommands but duplicates of whatever they're
@ -55,7 +55,7 @@ pub fn all_subcommand_names(p: &Parser) -> Vec<String> {
} }
// Gets all subcommands including child subcommands in the form of ('name', 'bin_name') where the name // Gets all subcommands including child subcommands in the form of ('name', 'bin_name') where the name
// is a single word (i.e. "install") of the path and full bin_name of said subcommand (i.e. // is a single word (i.e. "install") of the path and full bin_name of said subcommand (i.e.
// "rustup toolchain install") // "rustup toolchain install")
// //
// Also note, aliases are treated as their own subcommands but duplicates of whatever they're // Also note, aliases are treated as their own subcommands but duplicates of whatever they're
@ -75,9 +75,7 @@ pub fn all_subcommands(p: &Parser) -> Vec<(String, String)> {
// Also note, aliases are treated as their own subcommands but duplicates of whatever they're // Also note, aliases are treated as their own subcommands but duplicates of whatever they're
// aliasing. // aliasing.
pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> { pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
debugln!("fn=subcommands_of;name={};bin_name={}", debugln!("fn=subcommands_of;name={};bin_name={}", p.meta.name, p.meta.bin_name.as_ref().unwrap());
p.meta.name,
p.meta.bin_name.as_ref().unwrap());
let mut subcmds = vec![]; let mut subcmds = vec![];
debug!("Has subcommands..."); debug!("Has subcommands...");
@ -88,8 +86,7 @@ pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
if let Some(ref aliases) = p.meta.aliases { if let Some(ref aliases) = p.meta.aliases {
for &(n, _) in aliases { for &(n, _) in aliases {
debugln!("Found alias...{}", n); debugln!("Found alias...{}", n);
let mut als_bin_name: Vec<_> = let mut als_bin_name: Vec<_> = p.meta.bin_name.as_ref().unwrap().split(' ').collect();
p.meta.bin_name.as_ref().unwrap().split(' ').collect();
als_bin_name.push(n); als_bin_name.push(n);
let old = als_bin_name.len() - 2; let old = als_bin_name.len() - 2;
als_bin_name.swap_remove(old); als_bin_name.swap_remove(old);
@ -97,19 +94,16 @@ pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
} }
} }
return ret; return ret;
} }
sdebugln!("Yes"); sdebugln!("Yes");
for sc in &p.subcommands { for sc in &p.subcommands {
debugln!("iter;name={};bin_name={}", debugln!("iter;name={};bin_name={}", sc.p.meta.name, sc.p.meta.bin_name.as_ref().unwrap());
sc.p.meta.name,
sc.p.meta.bin_name.as_ref().unwrap());
debugln!("Looking for aliases..."); debugln!("Looking for aliases...");
if let Some(ref aliases) = sc.p.meta.aliases { if let Some(ref aliases) = sc.p.meta.aliases {
for &(n, _) in aliases { for &(n, _) in aliases {
debugln!("Found alias...{}", n); debugln!("Found alias...{}", n);
let mut als_bin_name: Vec<_> = let mut als_bin_name: Vec<_> = p.meta.bin_name.as_ref().unwrap().split(' ').collect();
p.meta.bin_name.as_ref().unwrap().split(' ').collect();
als_bin_name.push(n); als_bin_name.push(n);
let old = als_bin_name.len() - 2; let old = als_bin_name.len() - 2;
als_bin_name.swap_remove(old); als_bin_name.swap_remove(old);

View file

@ -19,7 +19,7 @@ impl<'a, 'b> PowerShellGen<'a, 'b> {
pub fn generate_to<W: Write>(&self, buf: &mut W) { pub fn generate_to<W: Write>(&self, buf: &mut W) {
let bin_name = self.p.meta.bin_name.as_ref().unwrap(); let bin_name = self.p.meta.bin_name.as_ref().unwrap();
let (subcommands_detection_cases, subcommands_cases) = generate_inner(self.p, ""); let (subcommands_detection_cases, subcommands_cases) = generate_inner(&self.p, "");
let mut bin_names = vec![ let mut bin_names = vec![
bin_name.to_string(), bin_name.to_string(),
@ -32,9 +32,7 @@ impl<'a, 'b> PowerShellGen<'a, 'b> {
bin_names.push(format!(r"./{0}.exe", bin_name)); bin_names.push(format!(r"./{0}.exe", bin_name));
} }
let bin_names = bin_names.iter().fold(String::new(), |previous, current| { let bin_names = bin_names.iter().fold(String::new(), |previous, current| format!("{0}, '{1}'", previous, current));
format!("{0}, '{1}'", previous, current)
});
let bin_names = bin_names.trim_left_matches(", "); let bin_names = bin_names.trim_left_matches(", ");
let result = format!(r#" let result = format!(r#"
@ -77,17 +75,18 @@ impl<'a, 'b> PowerShellGen<'a, 'b> {
fn generate_inner<'a, 'b>(p: &Parser<'a, 'b>, previous_command_name: &str) -> (String, String) { fn generate_inner<'a, 'b>(p: &Parser<'a, 'b>, previous_command_name: &str) -> (String, String) {
let command_name = format!("{}_{}", previous_command_name, &p.meta.name); let command_name = format!("{}_{}", previous_command_name, &p.meta.name);
let mut subcommands_detection_cases = if previous_command_name == "" { let mut subcommands_detection_cases =
String::new() if previous_command_name == "" {
} else { String::new()
format!(r" }
else {
format!(r"
'{0}' {{ '{0}' {{
$command += '_{0}' $command += '_{0}'
break break
}} }}
", ", &p.meta.name)
&p.meta.name) };
};
let mut completions = String::new(); let mut completions = String::new();
for subcommand in &p.subcommands { for subcommand in &p.subcommands {
@ -104,13 +103,10 @@ fn generate_inner<'a, 'b>(p: &Parser<'a, 'b>, previous_command_name: &str) -> (S
'{}' {{ '{}' {{
$completions = @({}) $completions = @({})
}} }}
", ", &command_name, completions.trim_right_matches(", "));
&command_name,
completions.trim_right_matches(", "));
for subcommand in &p.subcommands { for subcommand in &p.subcommands {
let (subcommand_subcommands_detection_cases, subcommand_subcommands_cases) = let (subcommand_subcommands_detection_cases, subcommand_subcommands_cases) = generate_inner(&subcommand.p, &command_name);
generate_inner(&subcommand.p, &command_name);
subcommands_detection_cases.push_str(&subcommand_subcommands_detection_cases); subcommands_detection_cases.push_str(&subcommand_subcommands_detection_cases);
subcommands_cases.push_str(&subcommand_subcommands_cases); subcommands_cases.push_str(&subcommand_subcommands_cases);
} }

View file

@ -3,7 +3,6 @@ use std::str::FromStr;
use std::fmt; use std::fmt;
/// Describes which shell to produce a completions file for /// Describes which shell to produce a completions file for
#[cfg_attr(feature = "lints", allow(enum_variant_names))]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum Shell { pub enum Shell {
/// Generates a .bash-completion completion file for the Bourne Again SHell (BASH) /// Generates a .bash-completion completion file for the Bourne Again SHell (BASH)
@ -19,7 +18,12 @@ pub enum Shell {
impl Shell { impl Shell {
/// A list of possible variants in `&'static str` form /// A list of possible variants in `&'static str` form
pub fn variants() -> [&'static str; 4] { pub fn variants() -> [&'static str; 4] {
["zsh", "bash", "fish", "powershell"] [
"zsh",
"bash",
"fish",
"powershell"
]
} }
} }
@ -33,7 +37,9 @@ impl FromStr for Shell {
"FISH" | _ if s.eq_ignore_ascii_case("fish") => Ok(Shell::Fish), "FISH" | _ if s.eq_ignore_ascii_case("fish") => Ok(Shell::Fish),
"BASH" | _ if s.eq_ignore_ascii_case("bash") => Ok(Shell::Bash), "BASH" | _ if s.eq_ignore_ascii_case("bash") => Ok(Shell::Bash),
"POWERSHELL" | _ if s.eq_ignore_ascii_case("powershell") => Ok(Shell::PowerShell), "POWERSHELL" | _ if s.eq_ignore_ascii_case("powershell") => Ok(Shell::PowerShell),
_ => Err(String::from("[valid values: bash, fish, zsh, powershell]")), _ => Err(
String::from("[valid values: bash, fish, zsh, powershell]")
),
} }
} }
} }
@ -41,10 +47,11 @@ impl FromStr for Shell {
impl fmt::Display for Shell { impl fmt::Display for Shell {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
Shell::Bash => write!(f, "BASH"), Shell::Bash => write!(f, "BASH"),
Shell::Fish => write!(f, "FISH"), Shell::Fish => write!(f, "FISH"),
Shell::Zsh => write!(f, "ZSH"), Shell::Zsh => write!(f, "ZSH"),
Shell::PowerShell => write!(f, "POWERSHELL"), Shell::PowerShell => write!(f, "POWERSHELL"),
} }
} }
} }

View file

@ -19,13 +19,15 @@ pub struct ZshGen<'a, 'b>
impl<'a, 'b> ZshGen<'a, 'b> { impl<'a, 'b> ZshGen<'a, 'b> {
pub fn new(p: &'b Parser<'a, 'b>) -> Self { pub fn new(p: &'b Parser<'a, 'b>) -> Self {
debugln!("fn=ZshGen::new;"); debugln!("fn=ZshGen::new;");
ZshGen { p: p } ZshGen {
p: p,
}
} }
pub fn generate_to<W: Write>(&self, buf: &mut W) { pub fn generate_to<W: Write>(&self, buf: &mut W) {
debugln!("fn=generate_to;"); debugln!("fn=generate_to;");
w!(buf, w!(buf,
format!("\ format!("\
#compdef {name} #compdef {name}
_{name}() {{ _{name}() {{
@ -43,8 +45,7 @@ _{name} \"$@\"",
name = self.p.meta.bin_name.as_ref().unwrap(), name = self.p.meta.bin_name.as_ref().unwrap(),
initial_args = get_args_of(self.p), initial_args = get_args_of(self.p),
subcommands = get_subcommands_of(self.p), subcommands = get_subcommands_of(self.p),
subcommand_details = subcommand_details(self.p)) subcommand_details = subcommand_details(self.p)).as_bytes());
.as_bytes());
} }
} }
@ -71,11 +72,11 @@ _{name} \"$@\"",
// local commands; commands=( // local commands; commands=(
// 'show:Show the active and installed toolchains' // 'show:Show the active and installed toolchains'
// 'update:Update Rust toolchains' // 'update:Update Rust toolchains'
// # ... snip for brevity // # ... snip for brevity
// 'help:Prints this message or the help of the given subcommand(s)' // 'help:Prints this message or the help of the given subcommand(s)'
// ) // )
// _describe -t commands 'rustup commands' commands "$@" // _describe -t commands 'rustup commands' commands "$@"
// //
fn subcommand_details(p: &Parser) -> String { fn subcommand_details(p: &Parser) -> String {
debugln!("fn=subcommand_details"); debugln!("fn=subcommand_details");
// First we do ourself // First we do ourself
@ -87,10 +88,9 @@ _{bin_name_underscore}_commands() {{
) )
_describe -t commands '{bin_name} commands' commands \"$@\" _describe -t commands '{bin_name} commands' commands \"$@\"
}}", }}",
bin_name_underscore = bin_name_underscore = p.meta.bin_name.as_ref().unwrap().replace(" ", "_"),
p.meta.bin_name.as_ref().unwrap().replace(" ", "_"), bin_name = p.meta.bin_name.as_ref().unwrap(),
bin_name = p.meta.bin_name.as_ref().unwrap(), subcommands_and_args = subcommands_and_args_of(p))];
subcommands_and_args = subcommands_and_args_of(p))];
// Next we start looping through all the children, grandchildren, etc. // Next we start looping through all the children, grandchildren, etc.
let mut all_subcommands = completions::all_subcommands(p); let mut all_subcommands = completions::all_subcommands(p);
@ -106,15 +106,15 @@ _{bin_name_underscore}_commands() {{
) )
_describe -t commands '{bin_name} commands' commands \"$@\" _describe -t commands '{bin_name} commands' commands \"$@\"
}}", }}",
bin_name_underscore = bin_name.replace(" ", "_"), bin_name_underscore = bin_name.replace(" ", "_"),
bin_name = bin_name, bin_name = bin_name,
subcommands_and_args = subcommands_and_args_of(parser_of(p, bin_name)))); subcommands_and_args = subcommands_and_args_of(parser_of(p, bin_name))));
} }
ret.join("\n") ret.join("\n")
} }
// Generates subcommand and positional argument completions in form of // Generates subcommand and positional argument completions in form of
// //
// '[arg_name]:[arg_help]' // '[arg_name]:[arg_help]'
// //
@ -129,9 +129,9 @@ fn subcommands_and_args_of(p: &Parser) -> String {
debugln!("fn=subcommands_and_args_of;"); debugln!("fn=subcommands_and_args_of;");
let mut ret = vec![]; let mut ret = vec![];
fn add_sc(sc: &App, n: &str, ret: &mut Vec<String>) { fn add_sc(sc: &App, n: &str, ret: &mut Vec<String>) {
let s = format!("\"{name}:{help}\" \\", let s = format!("\"{name}:{help}\" \\",
name = n, name = n,
help = sc.p.meta.about.unwrap_or("")); help = sc.p.meta.about.unwrap_or(""));
if !s.is_empty() { if !s.is_empty() {
ret.push(s); ret.push(s);
} }
@ -142,7 +142,7 @@ fn subcommands_and_args_of(p: &Parser) -> String {
debugln!("iter;subcommand={}", sc.p.meta.name); debugln!("iter;subcommand={}", sc.p.meta.name);
add_sc(sc, &sc.p.meta.name, &mut ret); add_sc(sc, &sc.p.meta.name, &mut ret);
if let Some(ref v) = sc.p.meta.aliases { if let Some(ref v) = sc.p.meta.aliases {
for alias in v.iter().filter(|&&(_, vis)| vis).map(|&(n, _)| n) { for alias in v.iter().filter(|&&(_, vis)| vis).map(|&(n,_)| n) {
add_sc(sc, alias, &mut ret); add_sc(sc, alias, &mut ret);
} }
} }
@ -151,10 +151,10 @@ fn subcommands_and_args_of(p: &Parser) -> String {
// Then the positional args // Then the positional args
for arg in p.positionals() { for arg in p.positionals() {
debugln!("iter;arg={}", arg.name); debugln!("iter;arg={}", arg.name);
let a = format!("\"{name}:{help}\" \\", let a = format!("\"{name}:{help}\" \\",
name = arg.name.to_ascii_uppercase(), name = arg.name.to_ascii_uppercase(),
help = arg.help.unwrap_or("")); help = arg.help.unwrap_or(""));
if !a.is_empty() { if !a.is_empty() {
ret.push(a); ret.push(a);
} }
@ -184,7 +184,7 @@ fn subcommands_and_args_of(p: &Parser) -> String {
// //
// esac // esac
// ;; // ;;
// esac", // esac",
// //
// Where the following variables are present: // Where the following variables are present:
// [name] = The subcommand name in the form of "install" for "rustup toolchain install" // [name] = The subcommand name in the form of "install" for "rustup toolchain install"
@ -220,17 +220,18 @@ fn get_subcommands_of(p: &Parser) -> String {
subcmds.push(v.join("\n")); subcmds.push(v.join("\n"));
} }
format!("case $state in format!(
"case $state in
({name}) ({name})
curcontext=\"${{curcontext%:*:*}}:{name_hyphen}-command-$words[1]:\" curcontext=\"${{curcontext%:*:*}}:{name_hyphen}-command-$words[1]:\"
case $line[1] in case $line[1] in
{subcommands} {subcommands}
esac esac
;; ;;
esac", esac",
name = p.meta.name, name = p.meta.name,
name_hyphen = p.meta.bin_name.as_ref().unwrap().replace(" ", "-"), name_hyphen = p.meta.bin_name.as_ref().unwrap().replace(" ", "-"),
subcommands = subcmds.join("\n")) subcommands = subcmds.join("\n"))
} }
fn parser_of<'a, 'b>(p: &'b Parser<'a, 'b>, sc: &str) -> &'b Parser<'a, 'b> { fn parser_of<'a, 'b>(p: &'b Parser<'a, 'b>, sc: &str) -> &'b Parser<'a, 'b> {
@ -238,7 +239,7 @@ fn parser_of<'a, 'b>(p: &'b Parser<'a, 'b>, sc: &str) -> &'b Parser<'a, 'b> {
&p.find_subcommand(sc).expect(INTERNAL_ERROR_MSG).p &p.find_subcommand(sc).expect(INTERNAL_ERROR_MSG).p
} }
// Writes out the args section, which ends up being the flags and opts, and a jump to // Writes out the args section, which ends up being the flags and opts, and a jump to
// another ZSH function if there are positional args or subcommands. // another ZSH function if there are positional args or subcommands.
// The structer works like this: // The structer works like this:
// ([conflicting_args]) [multiple] arg [takes_value] [[help]] [: :(possible_values)] // ([conflicting_args]) [multiple] arg [takes_value] [[help]] [: :(possible_values)]
@ -264,15 +265,15 @@ fn get_args_of(p: &Parser) -> String {
let opts = write_opts_of(p); let opts = write_opts_of(p);
let flags = write_flags_of(p); let flags = write_flags_of(p);
let sc_or_a = if p.has_subcommands() || p.has_positionals() { let sc_or_a = if p.has_subcommands() || p.has_positionals() {
format!("\"1:: :_{name}_commands\" \\", format!("\"1:: :_{name}_commands\" \\",
name = p.meta.bin_name.as_ref().unwrap().replace(" ", "_")) name = p.meta.bin_name.as_ref().unwrap().replace(" ", "_"))
} else { } else {
String::new() String::new()
}; };
let sc = if p.has_subcommands() { let sc = if p.has_subcommands() {
format!("\"*:: :->{name}\" \\", name = p.meta.name) format!("\"*:: :->{name}\" \\", name = p.meta.name)
} else { } else {
String::new() String::new()
}; };
if !opts.is_empty() { if !opts.is_empty() {
@ -298,41 +299,33 @@ fn write_opts_of(p: &Parser) -> String {
for o in p.opts() { for o in p.opts() {
debugln!("iter;o={}", o.name()); debugln!("iter;o={}", o.name());
let help = o.help().unwrap_or(""); let help = o.help().unwrap_or("");
let mut conflicts = get_zsh_arg_conflicts!(p, o, INTERNAL_ERROR_MSG); let mut conflicts = get_zsh_arg_conflicts!(p, o, INTERNAL_ERROR_MSG);
conflicts = if conflicts.is_empty() { conflicts = if conflicts.is_empty() { String::new() } else { format!("({})", conflicts) };
String::new()
} else {
format!("({})", conflicts)
};
let multiple = if o.is_set(ArgSettings::Multiple) { let multiple = if o.is_set(ArgSettings::Multiple) { "*" } else { "" };
"*"
} else {
""
};
let pv = if let Some(pv_vec) = o.possible_vals() { let pv = if let Some(pv_vec) = o.possible_vals() {
format!(": :({})", pv_vec.join(" ")) format!(": :({})", pv_vec.join(" "))
} else { } else {
String::new() String::new()
}; };
if let Some(short) = o.short() { if let Some(short) = o.short() {
let s = format!("\"{conflicts}{multiple}-{arg}+[{help}]{possible_values}\" \\", let s = format!("\"{conflicts}{multiple}-{arg}+[{help}]{possible_values}\" \\",
conflicts = conflicts, conflicts = conflicts,
multiple = multiple, multiple = multiple,
arg = short, arg = short,
possible_values = pv, possible_values = pv,
help = help); help = help);
debugln!("Wrote...{}", &*s); debugln!("Wrote...{}", &*s);
ret.push(s); ret.push(s);
} }
if let Some(long) = o.long() { if let Some(long) = o.long() {
let l = format!("\"{conflicts}{multiple}--{arg}+[{help}]{possible_values}\" \\", let l = format!("\"{conflicts}{multiple}--{arg}+[{help}]{possible_values}\" \\",
conflicts = conflicts, conflicts = conflicts,
multiple = multiple, multiple = multiple,
arg = long, arg = long,
possible_values = pv, possible_values = pv,
help = help); help = help);
debugln!("Wrote...{}", &*l); debugln!("Wrote...{}", &*l);
ret.push(l); ret.push(l);
@ -348,24 +341,16 @@ fn write_flags_of(p: &Parser) -> String {
for f in p.flags() { for f in p.flags() {
debugln!("iter;f={}", f.name()); debugln!("iter;f={}", f.name());
let help = f.help().unwrap_or(""); let help = f.help().unwrap_or("");
let mut conflicts = get_zsh_arg_conflicts!(p, f, INTERNAL_ERROR_MSG); let mut conflicts = get_zsh_arg_conflicts!(p, f, INTERNAL_ERROR_MSG);
conflicts = if conflicts.is_empty() { conflicts = if conflicts.is_empty() { String::new() } else { format!("({})", conflicts) };
String::new()
} else {
format!("({})", conflicts)
};
let multiple = if f.is_set(ArgSettings::Multiple) { let multiple = if f.is_set(ArgSettings::Multiple) { "*" } else { "" };
"*"
} else {
""
};
if let Some(short) = f.short() { if let Some(short) = f.short() {
let s = format!("\"{conflicts}{multiple}-{arg}[{help}]\" \\", let s = format!("\"{conflicts}{multiple}-{arg}[{help}]\" \\",
multiple = multiple, multiple = multiple,
conflicts = conflicts, conflicts = conflicts,
arg = short, arg = short,
help = help); help = help);
debugln!("Wrote...{}", &*s); debugln!("Wrote...{}", &*s);
ret.push(s); ret.push(s);
@ -373,10 +358,10 @@ fn write_flags_of(p: &Parser) -> String {
if let Some(long) = f.long() { if let Some(long) = f.long() {
let l = format!("\"{conflicts}{multiple}--{arg}[{help}]\" \\", let l = format!("\"{conflicts}{multiple}--{arg}[{help}]\" \\",
conflicts = conflicts, conflicts = conflicts,
multiple = multiple, multiple = multiple,
arg = long, arg = long,
help = help); help = help);
debugln!("Wrote...{}", &*l); debugln!("Wrote...{}", &*l);
ret.push(l); ret.push(l);

View file

@ -52,7 +52,7 @@ pub enum ErrorKind {
UnknownArgument, UnknownArgument,
/// Occurs when the user provides an unrecognized [`SubCommand`] which meets the threshold for /// Occurs when the user provides an unrecognized [`SubCommand`] which meets the threshold for
/// being similar enough to an existing subcommand. /// being similar enough to an existing subcommand.
/// If it doesn't meet the threshold, or the 'suggestions' feature is disabled, /// If it doesn't meet the threshold, or the 'suggestions' feature is disabled,
/// the more general [`UnknownArgument`] error is returned. /// the more general [`UnknownArgument`] error is returned.
/// ///
@ -77,7 +77,7 @@ pub enum ErrorKind {
/// Occurs when the user provides an unrecognized [`SubCommand`] which either /// Occurs when the user provides an unrecognized [`SubCommand`] which either
/// doesn't meet the threshold for being similar enough to an existing subcommand, /// doesn't meet the threshold for being similar enough to an existing subcommand,
/// or the 'sggestions' feature is disabled. /// or the 'sggestions' feature is disabled.
/// Otherwise the more detailed [`InvalidSubcommand`] error is returned. /// Otherwise the more detailed [`InvalidSubcommand`] error is returned.
/// ///
/// This error typically happens when passing additional subcommand names to the `help` /// This error typically happens when passing additional subcommand names to the `help`

View file

@ -626,7 +626,7 @@ macro_rules! write_spaces {
($num:expr, $w:ident) => ({ ($num:expr, $w:ident) => ({
debugln!("macro=write_spaces!;"); debugln!("macro=write_spaces!;");
for _ in 0..$num { for _ in 0..$num {
write!($w, " ")?; try!(write!($w, " "));
} }
}) })
} }
@ -639,7 +639,7 @@ macro_rules! write_nspaces {
($dst:expr, $num:expr) => ({ ($dst:expr, $num:expr) => ({
debugln!("macro=write_spaces!;num={}", $num); debugln!("macro=write_spaces!;num={}", $num);
for _ in 0..$num { for _ in 0..$num {
$dst.write(b" ")?; try!($dst.write(b" "));
} }
}) })
} }

View file

@ -111,7 +111,7 @@ impl<'a> UsageParser<'a> {
{ {
debugln!("fn=stop_at;"); debugln!("fn=stop_at;");
self.start = self.pos; self.start = self.pos;
self.pos += self.usage[self.start..].bytes().take_while(|&b| f(b)).count(); self.pos += self.usage[self.start..].bytes().take_while(|&b| f(b) ).count();
} }
fn short_or_long(&mut self, arg: &mut Arg<'a, 'a>) { fn short_or_long(&mut self, arg: &mut Arg<'a, 'a>) {
@ -990,8 +990,7 @@ mod test {
assert!(d.is_set(ArgSettings::Multiple)); assert!(d.is_set(ArgSettings::Multiple));
assert!(d.is_set(ArgSettings::TakesValue)); assert!(d.is_set(ArgSettings::TakesValue));
assert!(d.is_set(ArgSettings::Required)); assert!(d.is_set(ArgSettings::Required));
assert_eq!(d.val_names.unwrap().values().collect::<Vec<_>>(), assert_eq!(d.val_names.unwrap().values().collect::<Vec<_>>(), [&"option"]);
[&"option"]);
assert!(d.num_vals.is_none()); assert!(d.num_vals.is_none());
} }
@ -1200,8 +1199,7 @@ mod test {
let a = Arg::from_usage("[ñämê] --ôpt=[üñíčöĐ€] 'hælp'"); let a = Arg::from_usage("[ñämê] --ôpt=[üñíčöĐ€] 'hælp'");
assert_eq!(a.name, "ñämê"); assert_eq!(a.name, "ñämê");
assert_eq!(a.long, Some("ôpt")); assert_eq!(a.long, Some("ôpt"));
assert_eq!(a.val_names.unwrap().values().collect::<Vec<_>>(), assert_eq!(a.val_names.unwrap().values().collect::<Vec<_>>(), [&"üñíčöĐ€"]);
[&"üñíčöĐ€"]);
assert_eq!(a.help, Some("hælp")); assert_eq!(a.help, Some("hælp"));
} }
} }