diff --git a/CHANGELOG.md b/CHANGELOG.md index 8506c70b907..b71d44c525b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,30 @@ + +### v2.14.1 (2016-10-20) + + +#### Documentation + +* Improve documentation around features ([4ee85b95](https://github.com/kbknapp/clap-rs/commit/4ee85b95d2d16708a016a3ba4e6e2c93b89b7fad)) +* reword docs for ErrorKind and app::Settings ([3ccde7a4](https://github.com/kbknapp/clap-rs/commit/3ccde7a4b8f7a2ea8b916a5415c04a8ff4b5cb7a)) +* fix tests that fail when the "suggestions" feature is disabled ([996fc381](https://github.com/kbknapp/clap-rs/commit/996fc381763a48d125c7ea8a58fed057fd0b4ac6)) +* fix the OsString-using doc-tests ([af9e1a39](https://github.com/kbknapp/clap-rs/commit/af9e1a393ce6cdda46a03c8a4f48df222b015a24)) +* tag non-rust code blocks as such instead of ignoring them ([0ba9f4b1](https://github.com/kbknapp/clap-rs/commit/0ba9f4b123f281952581b6dec948f7e51dd22890)) +* **ErrorKind:** improve some errors about subcommands ([9f6217a4](https://github.com/kbknapp/clap-rs/commit/9f6217a424da823343d7b801b9c350dee3cd1906)) +* **yaml:** make sure the doc-tests don't fail before "missing file" ([8c0f5551](https://github.com/kbknapp/clap-rs/commit/8c0f55516f4910c78c9f8a2bdbd822729574f95b)) + +#### Improvements + +* Stabilize clap_app! ([cd516006](https://github.com/kbknapp/clap-rs/commit/cd516006e35c37b005f329338560a0a53d1f3e00)) +* **with_defaults:** Deprecate App::with_defaults() ([26085409](https://github.com/kbknapp/clap-rs/commit/2608540940c8bb66e517b65706bc7dea55510682), closes [#638](https://github.com/kbknapp/clap-rs/issues/638)) + +#### Bug Fixes + +* fixes a bug that made determining when to auto-wrap long help messages inconsistent ([468baadb](https://github.com/kbknapp/clap-rs/commit/468baadb8398fc1d37897b0c49374aef4cf97dca), closes [#688](https://github.com/kbknapp/clap-rs/issues/688)) +* **Completions:** fish completions for nested subcommands ([a61eaf8a](https://github.com/kbknapp/clap-rs/commit/a61eaf8aade76cfe90ccc0f7125751ebf60e3254)) +* **features:** Make lints not enable other nightly-requiring features ([835f75e3](https://github.com/kbknapp/clap-rs/commit/835f75e3ba20999117363ed9f916464d777f36ef)) + + + ## v2.14.0 (2016-10-05) diff --git a/Cargo.toml b/Cargo.toml index 3abe65cecb6..4a093abd218 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clap" -version = "2.14.0" +version = "2.14.1" authors = ["Kevin K. "] exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"] repository = "https://github.com/kbknapp/clap-rs.git" diff --git a/README.md b/README.md index 9b1db05bfff..458b31d65ee 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,21 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) ## What's New +Here's the highlights for v2.14.1 (Huge thanks to all the contributors who put in a lot of work this cycle! Especially @tormol @nabijaczleweli and @wdv4758h) + +* Stabilize `clap_app!` macro (i.e. no longer need to use `unstable` feature) +* Fixes a bug that made determining when to auto-wrap long help messages inconsistent +* Fixes fish completions for nested subcommands +* Improve documentation around features +* Reword docs for `ErrorKind` and `App::settings` +* Fix tests that fail when the `suggestions` feature is disabled +* Fix the `OsString`-using doc-tests +* Tag non-rust code blocks as such instead of ignoring them +* Improve some errors about subcommands +* Makes sure the doc-tests don't fail before "missing file" in YAML tests +* Deprecate `App::with_defaults` +* Make lints not enable other nightly-requiring features + Here's the highlights for v2.14.0 * One can now alias arguments either visibly (whichc appears in the help text) or invisibly just like subcommands! diff --git a/src/app/help.rs b/src/app/help.rs index 0b22a277d98..7699f3050d1 100644 --- a/src/app/help.rs +++ b/src/app/help.rs @@ -84,6 +84,8 @@ pub struct Help<'a> { term_w: usize, color: bool, cizer: Colorizer, + longest: usize, + force_next_line: bool, } // Public Functions @@ -111,6 +113,8 @@ impl<'a> Help<'a> { }, color: color, cizer: cizer, + longest: 0, + force_next_line: false, } } @@ -169,13 +173,14 @@ impl<'a> Help<'a> { fn write_args_unsorted<'b: 'd, 'c: 'd, 'd, I: 'd>(&mut self, args: I) -> io::Result<()> where I: Iterator> { - let mut longest = 0; + // The shortest an arg can legally be is 2 (i.e. '-x') + self.longest = 2; let mut arg_v = Vec::with_capacity(10); for arg in args.filter(|arg| { !(arg.is_set(ArgSettings::Hidden)) || arg.is_set(ArgSettings::NextLineHelp) }) { if arg.longest_filter() { - longest = cmp::max(longest, arg.to_string().len()); + self.longest = cmp::max(self.longest, arg.to_string().len()); } if !arg.is_set(ArgSettings::Hidden) { arg_v.push(arg) @@ -188,7 +193,7 @@ impl<'a> Help<'a> { } else { try!(self.writer.write(b"\n")); } - try!(self.write_arg(arg.as_base(), longest)); + try!(self.write_arg(arg.as_base())); } Ok(()) } @@ -198,18 +203,23 @@ impl<'a> Help<'a> { where I: Iterator> { debugln!("fn=write_args;"); - let mut longest = 0; + // The shortest an arg can legally be is 2 (i.e. '-x') + self.longest = 2; let mut ord_m = VecMap::new(); + // Determine the longest for arg in args.filter(|arg| { - !(arg.is_set(ArgSettings::Hidden)) || arg.is_set(ArgSettings::NextLineHelp) + // 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 + // args alignment + !arg.is_set(ArgSettings::Hidden) || arg.is_set(ArgSettings::NextLineHelp) }) { if arg.longest_filter() { - longest = cmp::max(longest, arg.to_string().len()); - } - if !arg.is_set(ArgSettings::Hidden) { - let btm = ord_m.entry(arg.disp_ord()).or_insert(BTreeMap::new()); - btm.insert(arg.name(), arg); + debugln!("Longest...{}", self.longest); + self.longest = cmp::max(self.longest, arg.to_string().len()); + debugln!("New Longest...{}", self.longest); } + let btm = ord_m.entry(arg.disp_ord()).or_insert(BTreeMap::new()); + btm.insert(arg.name(), arg); } let mut first = true; for btm in ord_m.values() { @@ -219,7 +229,7 @@ impl<'a> Help<'a> { } else { try!(self.writer.write(b"\n")); } - try!(self.write_arg(arg.as_base(), longest)); + try!(self.write_arg(arg.as_base())); } } Ok(()) @@ -227,14 +237,13 @@ impl<'a> Help<'a> { /// Writes help for an argument to the wrapped stream. fn write_arg<'b, 'c>(&mut self, - arg: &ArgWithDisplay<'b, 'c>, - longest: usize) + arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> { debugln!("fn=write_arg;"); try!(self.short(arg)); - try!(self.long(arg, longest)); - try!(self.val(arg, longest)); - try!(self.help(arg, longest)); + try!(self.long(arg)); + let spec_vals = try!(self.val(arg)); + try!(self.help(arg, &*spec_vals)); Ok(()) } @@ -252,7 +261,7 @@ impl<'a> Help<'a> { } /// Writes argument's long command to the wrapped stream. - fn long<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>, longest: usize) -> io::Result<()> { + fn long<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> { debugln!("fn=long;"); if !arg.has_switch() { return Ok(()); @@ -270,62 +279,64 @@ impl<'a> Help<'a> { try!(write!(self.writer, ", ")); } try!(color!(self, "--{}", l, good)); - if !self.next_line_help || !arg.is_set(ArgSettings::NextLineHelp) { - write_nspaces!(self.writer, (longest + 4) - (l.len() + 2)); - } - } else if !self.next_line_help || !arg.is_set(ArgSettings::NextLineHelp) { - // 6 is tab (4) + -- (2) - write_nspaces!(self.writer, (longest + 6)); } Ok(()) } /// Writes argument's possible values to the wrapped stream. - fn val<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>, longest: usize) -> io::Result<()> { - debugln!("fn=val;"); - if !arg.takes_value() { - return Ok(()); - } - if let Some(vec) = arg.val_names() { - let mut it = vec.iter().peekable(); - while let Some((_, val)) = it.next() { - try!(color!(self, "<{}>", val, good)); - if it.peek().is_some() { - try!(write!(self.writer, " ")); + fn val<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> Result { + debugln!("fn=val;arg={}", arg); + if arg.takes_value() { + if let Some(vec) = arg.val_names() { + let mut it = vec.iter().peekable(); + while let Some((_, val)) = it.next() { + try!(color!(self, "<{}>", val, good)); + if it.peek().is_some() { + try!(write!(self.writer, " ")); + } } - } - let num = vec.len(); - if arg.is_set(ArgSettings::Multiple) && num == 1 { - try!(color!(self, "...", good)); - } - } else if let Some(num) = arg.num_vals() { - let mut it = (0..num).peekable(); - while let Some(_) = it.next() { - try!(color!(self, "<{}>", arg.name(), good)); - if it.peek().is_some() { - try!(write!(self.writer, " ")); + let num = vec.len(); + if arg.is_set(ArgSettings::Multiple) && num == 1 { + try!(color!(self, "...", good)); + } + } else if let Some(num) = arg.num_vals() { + let mut it = (0..num).peekable(); + while let Some(_) = it.next() { + try!(color!(self, "<{}>", arg.name(), good)); + if it.peek().is_some() { + try!(write!(self.writer, " ")); + } } + } else if arg.has_switch() { + try!(color!(self, "<{}>", arg.name(), good)); + } else { + try!(color!(self, "{}", arg, good)); } - } else if arg.has_switch() { - try!(color!(self, "<{}>", arg.name(), good)); - } else { - try!(color!(self, "{}", arg, good)); } let spec_vals = self.spec_vals(arg); let h = arg.help().unwrap_or(""); + let h_w = str_width(h) + str_width(&*spec_vals); let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp); - let width = self.term_w; - let taken = (longest + 12) + str_width(&*spec_vals); - let force_next_line = !nlh && width >= taken && - (taken as f32 / width as f32) > 0.40 && - str_width(h) > (width - taken); + let taken = self.longest + 12; + self.force_next_line = !nlh && self.term_w >= taken && + (taken as f32 / self.term_w as f32) > 0.40 && + h_w > (self.term_w - taken); + debug!("Has switch..."); if arg.has_switch() { - if !(nlh || force_next_line) { + sdebugln!("Yes"); + debugln!("force_next_line...{:?}", self.force_next_line); + debugln!("nlh...{:?}", nlh); + debugln!("taken...{}", taken); + debugln!("help_width > (width - taken)...{} > ({} - {})", h_w, self.term_w, taken); + debugln!("longest...{}", self.longest); + debug!("next_line..."); + if !(nlh || self.force_next_line) { + sdebugln!("No"); let self_len = arg.to_string().len(); // subtract ourself - let mut spcs = longest - self_len; + let mut spcs = self.longest - self_len; // Since we're writing spaces from the tab point we first need to know if we // had a long and short, or just short if arg.long().is_some() { @@ -337,20 +348,24 @@ impl<'a> Help<'a> { } write_nspaces!(self.writer, spcs); + } else { + sdebugln!("Yes"); } - } else if !(nlh || force_next_line) { - write_nspaces!(self.writer, longest + 4 - (arg.to_string().len())); + } else if !(nlh || self.force_next_line) { + sdebugln!("No, and not next_line"); + write_nspaces!(self.writer, self.longest + 4 - (arg.to_string().len())); + } else { + sdebugln!("No"); } - Ok(()) + Ok(spec_vals) } fn write_before_after_help(&mut self, h: &str) -> io::Result<()> { debugln!("fn=before_help;"); let mut help = String::new(); // determine if our help fits or needs to wrap - let width = self.term_w; - debugln!("Term width...{}", width); - let too_long = str_width(h) >= width; + debugln!("Term width...{}", self.term_w); + let too_long = str_width(h) >= self.term_w; debug!("Too long..."); if too_long || h.contains("{n}") { @@ -359,7 +374,7 @@ impl<'a> Help<'a> { debugln!("help: {}", help); debugln!("help width: {}", str_width(&*help)); // Determine how many newlines we need to insert - debugln!("Usable space: {}", width); + debugln!("Usable space: {}", self.term_w); let longest_w = { let mut lw = 0; for l in help.split(' ').map(|s| str_width(s)) { @@ -370,7 +385,7 @@ impl<'a> Help<'a> { lw }; help = help.replace("{n}", "\n"); - wrap_help(&mut help, longest_w, width); + wrap_help(&mut help, longest_w, self.term_w); } else { sdebugln!("No"); } @@ -394,53 +409,36 @@ impl<'a> Help<'a> { } /// Writes argument's help to the wrapped stream. - fn help<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>, longest: usize) -> io::Result<()> { + fn help<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>, spec_vals: &str) -> io::Result<()> { debugln!("fn=help;"); - let spec_vals = self.spec_vals(arg); let mut help = String::new(); let h = arg.help().unwrap_or(""); let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp); debugln!("Next Line...{:?}", nlh); - // determine if our help fits or needs to wrap - let width = self.term_w; - debugln!("Term width...{}", width); - - // We calculate with longest+12 since if it's already NLH we don't care - let taken = (longest + 12) + str_width(&*spec_vals); - let force_next_line = !nlh && width >= taken && - (taken as f32 / width as f32) > 0.40 && - str_width(h) > (width - taken); - debugln!("Force Next Line...{:?}", force_next_line); - 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 || self.force_next_line { 12 // "tab" * 3 } else { - longest + 12 + self.longest + 12 }; - let too_long = spcs + str_width(h) + str_width(&*spec_vals) >= width; - debugln!("Spaces: {}", spcs); + let too_long = spcs + str_width(h) + str_width(&*spec_vals) >= self.term_w; // Is help on next line, if so then indent - if nlh || force_next_line { + if nlh || self.force_next_line { try!(write!(self.writer, "\n{}{}{}", TAB, TAB, TAB)); } debug!("Too long..."); - if too_long && spcs <= width || h.contains("{n}") { + if too_long && spcs <= self.term_w || h.contains("{n}") { sdebugln!("Yes"); help.push_str(h); help.push_str(&*spec_vals); - debugln!("help: {}", help); - debugln!("help width: {}", str_width(&*help)); + debugln!("help...{}", help); + debugln!("help width...{}", str_width(&*help)); // Determine how many newlines we need to insert - let avail_chars = width - spcs; - debugln!("Usable space: {}", avail_chars); + let avail_chars = self.term_w - spcs; + debugln!("Usable space...{}", avail_chars); let longest_w = { let mut lw = 0; for l in help.split(' ').map(|s| str_width(s)) { @@ -470,12 +468,12 @@ impl<'a> Help<'a> { } for part in help.lines().skip(1) { try!(write!(self.writer, "\n")); - if nlh || force_next_line { + if nlh || self.force_next_line { try!(write!(self.writer, "{}{}{}", TAB, TAB, TAB)); } else if arg.has_switch() { - write_nspaces!(self.writer, longest + 12); + write_nspaces!(self.writer, self.longest + 12); } else { - write_nspaces!(self.writer, longest + 8); + write_nspaces!(self.writer, self.longest + 8); } try!(write!(self.writer, "{}", part)); } @@ -486,35 +484,20 @@ impl<'a> Help<'a> { } fn spec_vals(&self, a: &ArgWithDisplay) -> String { - debugln!("fn=spec_vals;"); + debugln!("fn=spec_vals;a={}", a); + let mut spec_vals = vec![]; if let Some(pv) = a.default_val() { - debugln!("Writing defaults"); - return format!(" [default: {}] {}", - if self.color { - self.cizer.good(pv) - } else { - Format::None(pv) - }, - if self.hide_pv || a.is_set(ArgSettings::HidePossibleValues) { - "".into() - } else { - if let Some(ref pv) = a.possible_vals() { - if self.color { - format!(" [values: {}]", - pv.iter() - .map(|v| format!("{}", self.cizer.good(v))) - .collect::>() - .join(", ")) - } else { - format!(" [values: {}]", pv.join(", ")) - } - } else { - "".into() - } - }); - } else if let Some(ref aliases) = a.aliases() { - debugln!("Writing aliases"); - return format!(" [aliases: {}]", + debugln!("Found default value...[{}]", pv); + spec_vals.push(format!(" [default: {}]", + if self.color { + self.cizer.good(pv) + } else { + Format::None(pv) + })); + } + if let Some(ref aliases) = a.aliases() { + debugln!("Found aliases...{:?}", aliases); + spec_vals.push(format!(" [aliases: {}]", if self.color { aliases.iter() .map(|v| format!("{}", self.cizer.good(v))) @@ -522,12 +505,12 @@ impl<'a> Help<'a> { .join(", ") } else { aliases.join(", ") - }); - } else if !self.hide_pv && !a.is_set(ArgSettings::HidePossibleValues) { - debugln!("Writing values"); - if let Some(pv) = a.possible_vals() { - debugln!("Possible vals...{:?}", pv); - return if self.color { + })); + } + if !self.hide_pv && !a.is_set(ArgSettings::HidePossibleValues) { + if let Some(ref pv) = a.possible_vals() { + debugln!("Found possible vals...{:?}", pv); + spec_vals.push(if self.color { format!(" [values: {}]", pv.iter() .map(|v| format!("{}", self.cizer.good(v))) @@ -535,10 +518,10 @@ impl<'a> Help<'a> { .join(", ")) } else { format!(" [values: {}]", pv.join(", ")) - }; + }); } } - String::new() + spec_vals.join(" ") } } @@ -606,12 +589,12 @@ impl<'a> Help<'a> { /// Writes help for subcommands of a Parser Object to the wrapped stream. fn write_subcommands(&mut self, parser: &Parser) -> io::Result<()> { debugln!("fn=write_subcommands;"); - let mut longest = 0; - + // The shortest an arg can legally be is 2 (i.e. '-x') + self.longest = 2; let mut ord_m = VecMap::new(); for sc in parser.subcommands.iter().filter(|s| !s.p.is_set(AppSettings::Hidden)) { let btm = ord_m.entry(sc.p.meta.disp_ord).or_insert(BTreeMap::new()); - longest = cmp::max(longest, sc.p.meta.name.len()); + self.longest = cmp::max(self.longest, sc.p.meta.name.len()); btm.insert(sc.p.meta.name.clone(), sc.clone()); } @@ -623,7 +606,7 @@ impl<'a> Help<'a> { } else { try!(self.writer.write(b"\n")); } - try!(self.write_arg(sc, longest)); + try!(self.write_arg(sc)); } } Ok(()) diff --git a/src/args/arg_builder/flag.rs b/src/args/arg_builder/flag.rs index 5f99017b5be..78df5c835c2 100644 --- a/src/args/arg_builder/flag.rs +++ b/src/args/arg_builder/flag.rs @@ -89,21 +89,6 @@ impl<'n, 'e> Display for FlagBuilder<'n, 'e> { try!(write!(f, "-{}", self.short.unwrap())); } - // Write aliases such as [aliases: alias, new-alias] - if let Some(ref vec) = self.aliases { - try!(write!(f, " [aliases: ")); - let mut it = vec.iter().peekable(); - while let Some(&(val, b)) = it.next() { - if b { - try!(write!(f, "{}", val)); - if it.peek().is_some() { - try!(write!(f, ", ")); - } - } - } - try!(write!(f, "]")); - } - Ok(()) } } @@ -237,7 +222,7 @@ mod test { f.long = Some("flag"); f.aliases = Some(vec![("als", true)]); - assert_eq!(&*format!("{}", f), "--flag [aliases: als]"); + assert_eq!(&*format!("{}", f), "--flag"); } #[test] @@ -250,6 +235,6 @@ mod test { ("f3", true), ("f4", true) ]); - assert_eq!(&*format!("{}", f), "-f [aliases: f2, f3, f4]"); + assert_eq!(&*format!("{}", f), "-f"); } } diff --git a/src/args/arg_builder/option.rs b/src/args/arg_builder/option.rs index 5182c449c7f..b918dccedfa 100644 --- a/src/args/arg_builder/option.rs +++ b/src/args/arg_builder/option.rs @@ -160,21 +160,6 @@ impl<'n, 'e> Display for OptBuilder<'n, 'e> { })); } - // Write aliases such as [aliases: alias, new-alias] - if let Some(ref vec) = self.aliases { - try!(write!(f, " [aliases: ")); - let mut it = vec.iter().peekable(); - while let Some(&(val, b)) = it.next() { - if b { - try!(write!(f, "{}", val)); - if it.peek().is_some() { - try!(write!(f, ", ")); - } - } - } - try!(write!(f, "]")); - } - Ok(()) } } @@ -340,7 +325,7 @@ mod test { o.long = Some("option"); o.aliases = Some(vec![("als", true)]); - assert_eq!(&*format!("{}", o), "--option [aliases: als]"); + assert_eq!(&*format!("{}", o), "--option "); } #[test] @@ -353,6 +338,6 @@ mod test { ("als3", true), ("als4", true) ]); - assert_eq!(&*format!("{}", o), "--option [aliases: als2, als3, als4]"); + assert_eq!(&*format!("{}", o), "--option "); } } diff --git a/src/macros.rs b/src/macros.rs index 8df6a0811e8..932397f6fb3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -637,7 +637,7 @@ macro_rules! write_spaces { // src/app/mod.rs macro_rules! write_nspaces { ($dst:expr, $num:expr) => ({ - debugln!("macro=write_spaces!;"); + debugln!("macro=write_spaces!;num={}", $num); for _ in 0..$num { try!($dst.write(b" ")); } diff --git a/tests/arg_aliases.rs b/tests/arg_aliases.rs index 9c1c419ea79..9703a3e1805 100644 --- a/tests/arg_aliases.rs +++ b/tests/arg_aliases.rs @@ -12,7 +12,7 @@ USAGE: test [FLAGS] [OPTIONS] FLAGS: - -f, --flag [aliases: v_flg, flag2, flg3] + -f, --flag [aliases: v_flg, flag2, flg3] OPTIONS: -o, --opt [aliases: visible]"; @@ -24,7 +24,7 @@ USAGE: test [FLAGS] [OPTIONS] FLAGS: - -f, --flag + -f, --flag OPTIONS: -o, --opt "; diff --git a/tests/help.rs b/tests/help.rs index 5d8fa633a16..8b2a87d1c8b 100644 --- a/tests/help.rs +++ b/tests/help.rs @@ -3,7 +3,7 @@ extern crate regex; include!("../clap-test.rs"); -use clap::{App, SubCommand, ErrorKind, Arg}; +use clap::{App, AppSettings, SubCommand, ErrorKind, Arg}; static HELP: &'static str = "clap-test v1.4.8 Kevin K. @@ -144,6 +144,21 @@ FLAGS: (Defaults to something) -V, --version Prints version information"; + +static ISSUE_688: &'static str = "ctest 0.1 + +USAGE: + ctest [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + --filter Sets the filter, or sampling method, to use for interpolation when resizing the particle + images. The default is Linear (Bilinear). [values: Nearest, Linear, Cubic, Gaussian, + Lanczos3]"; + #[test] fn help_short() { let m = App::new("test") @@ -351,3 +366,41 @@ fn old_newline_chars() { .help("Some help with some wrapping{n}(Defaults to something)")); test::check_err_output(app, "ctest --help", OLD_NEWLINE_CHARS, false); } + +#[test] +fn issue_688_hidden_pos_vals() { + let filter_values = ["Nearest", "Linear", "Cubic", "Gaussian", "Lanczos3"]; + + let app1 = App::new("ctest") + .version("0.1") + .set_term_width(120) + .setting(AppSettings::HidePossibleValuesInHelp) + .arg(Arg::with_name("filter") + .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \ + images. The default is Linear (Bilinear). [values: Nearest, Linear, Cubic, Gaussian, Lanczos3]") + .long("filter") + .possible_values(&filter_values) + .takes_value(true)); + test::check_err_output(app1, "ctest --help", ISSUE_688, false); + + let app2 = App::new("ctest") + .version("0.1") + .set_term_width(120) + .arg(Arg::with_name("filter") + .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \ + images. The default is Linear (Bilinear).") + .long("filter") + .possible_values(&filter_values) + .takes_value(true)); + test::check_err_output(app2, "ctest --help", ISSUE_688, false); + + let app3 = App::new("ctest") + .version("0.1") + .set_term_width(120) + .arg(Arg::with_name("filter") + .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \ + images. The default is Linear (Bilinear). [values: Nearest, Linear, Cubic, Gaussian, Lanczos3]") + .long("filter") + .takes_value(true)); + test::check_err_output(app3, "ctest --help", ISSUE_688, false); +} \ No newline at end of file diff --git a/tests/template_help.rs b/tests/template_help.rs index e3fda73b088..05ffaefce69 100644 --- a/tests/template_help.rs +++ b/tests/template_help.rs @@ -15,7 +15,7 @@ USAGE: MyApp [FLAGS] [OPTIONS] [SUBCOMMAND] FLAGS: - -d Turn debugging information on + -d Turn debugging information on OPTIONS: -c, --config Sets a custom config file ARGS: @@ -31,7 +31,7 @@ USAGE: MyApp [FLAGS] [OPTIONS] [SUBCOMMAND] FLAGS: - -d Turn debugging information on + -d Turn debugging information on OPTIONS: -c, --config Sets a custom config file