Skip to content

Commit

Permalink
Merge pull request #1045 from kbknapp/issues-1043,1044
Browse files Browse the repository at this point in the history
Issues 1043,1044
  • Loading branch information
kbknapp committed Sep 14, 2017
2 parents 2094c28 + cbd813c commit 326d0a5
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 22 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,21 @@
<a name="v2.26.1"></a>
### v2.26.1 (2017-09-14)


#### Bug Fixes

* fixes using require_equals(true) and min_values(0) together ([10ae208f](https://github.com/kbknapp/clap-rs/commit/10ae208f68518eff6e98166724065745f4083174), closes [#1044](https://github.com/kbknapp/clap-rs/issues/1044))
* escape special characters in zsh and fish completions ([87e019fc](https://github.com/kbknapp/clap-rs/commit/87e019fc84ba6193a8c4ddc26c61eb99efffcd25))
* avoid panic generating default help msg if term width set to 0 due to bug in textwrap 0.7.0 ([b3eadb0d](https://github.com/kbknapp/clap-rs/commit/b3eadb0de516106db4e08f078ad32e8f6d6e7a57))
* Change `who's` -> `whose` ([53c1ffe8](https://github.com/kbknapp/clap-rs/commit/53c1ffe87f38b05d8804a0f7832412a952845349))
* adds a debug assertion to ensure all args added to groups actually exist ([7ad123e2](https://github.com/kbknapp/clap-rs/commit/7ad123e2c02577e3ca30f7e205181e896b157d11), closes [#917](https://github.com/kbknapp/clap-rs/issues/917))
* fixes a bug where args that allow values to start with a hyphen couldnt contain a double hyphen -- as a value ([ab2f4c9e](https://github.com/kbknapp/clap-rs/commit/ab2f4c9e563e36ec739a4b55d5a5b76fdb9e9fa4), closes [#960](https://github.com/kbknapp/clap-rs/issues/960))
* fixes a bug where positional argument help text is misaligned ([54c16836](https://github.com/kbknapp/clap-rs/commit/54c16836dea4651806a2cfad53146a83fa3abf21))
* **Help Message:** fixes long_about not being usable ([a8257ea0](https://github.com/kbknapp/clap-rs/commit/a8257ea0ffb812e552aca256c4a3d2aebfd8065b), closes [#1043](https://github.com/kbknapp/clap-rs/issues/1043))
* **Suggestions:** output for flag after subcommand ([434ea5ba](https://github.com/kbknapp/clap-rs/commit/434ea5ba71395d8c1afcf88e69f0b0d8339b01a1))



<a name="v2.26.0"></a>
## v2.26.0 (2017-07-29)

Expand Down
3 changes: 1 addition & 2 deletions Cargo.toml
@@ -1,7 +1,7 @@
[package]

name = "clap"
version = "2.26.0"
version = "2.26.1"
authors = ["Kevin K. <kbknapp@gmail.com>"]
exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"]
repository = "https://github.com/kbknapp/clap-rs.git"
Expand All @@ -23,7 +23,6 @@ appveyor = { repository = "kbknapp/clap-rs" }
bitflags = "0.9"
vec_map = "0.8"
unicode-width = "0.1.4"
unicode-segmentation = "1.2.0"
textwrap = "0.8.0"
strsim = { version = "0.6.0", optional = true }
ansi_term = { version = "0.9.0", optional = true }
Expand Down
16 changes: 11 additions & 5 deletions README.md
Expand Up @@ -45,15 +45,21 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)

## What's New

Here's the highlights for v2.26.0
Here's what's new in 2.26.1:

* **The minimum required version of Rust is now 1.13.0 (Stable)**
* bumps unicode-segmentation to v1.2
* update textwrap to version 0.7.0 which increases the performance of writing help strings
* fixes using require_equals(true) and min_values(0) together
* escape special characters in zsh and fish completions
* avoid panic generating default help msg if term width set to 0 due to bug in textwrap 0.7.0
* Change `who's` -> `whose` in documentation
* **Help Message:** fixes `App::long_about` not being displayed
* **Suggestions:** output for flag after subcommand


Here's the highlights for v2.21.0 to v2.25.1
Here's the highlights for v2.21.0 to v2.26.0

* **The minimum required version of Rust is now 1.13.0 (Stable)**
* bumps unicode-segmentation to v1.2
* update textwrap to version 0.7.0 which increases the performance of writing help strings
* impl Default for Values + OsValues for any lifetime.
* use textwrap crate for wrapping help texts
* suggests to use flag after subcommand when applicable
Expand Down
23 changes: 21 additions & 2 deletions src/app/help.rs
Expand Up @@ -657,8 +657,22 @@ impl<'a> Help<'a> {
if let Some(author) = parser.meta.author {
write_thing!(author)
}
if let Some(about) = parser.meta.about {
write_thing!(about)
if self.use_long {
if let Some(about) = parser.meta.long_about {
debugln!("Help::write_default_help: writing long about");
write_thing!(about)
} else if let Some(about) = parser.meta.about {
debugln!("Help::write_default_help: writing about");
write_thing!(about)
}
} else {
if let Some(about) = parser.meta.about {
debugln!("Help::write_default_help: writing about");
write_thing!(about)
} else if let Some(about) = parser.meta.long_about {
debugln!("Help::write_default_help: writing long about");
write_thing!(about)
}
}

color!(self, "\nUSAGE:", warning)?;
Expand Down Expand Up @@ -861,6 +875,11 @@ impl<'a> Help<'a> {
"{}",
parser.meta.about.unwrap_or("unknown about"))?;
}
b"long-about" => {
write!(self.writer,
"{}",
parser.meta.long_about.unwrap_or("unknown about"))?;
}
b"usage" => {
write!(self.writer, "{}", usage::create_usage_no_title(parser, &[]))?;
}
Expand Down
23 changes: 15 additions & 8 deletions src/app/parser.rs
Expand Up @@ -1339,7 +1339,8 @@ impl<'a, 'b> Parser<'a, 'b>

#[cfg_attr(feature = "cargo-clippy", allow(let_and_return))]
fn use_long_help(&self) -> bool {
let ul = self.flags.iter().any(|f| f.b.long_help.is_some()) ||
let ul = self.meta.long_about.is_some() ||
self.flags.iter().any(|f| f.b.long_help.is_some()) ||
self.opts.iter().any(|o| o.b.long_help.is_some()) ||
self.positionals.values().any(|p| p.b.long_help.is_some()) ||
self.subcommands
Expand Down Expand Up @@ -1529,13 +1530,17 @@ impl<'a, 'b> Parser<'a, 'b>
debugln!("Parser::parse_opt; opt={}, val={:?}", opt.b.name, val);
debugln!("Parser::parse_opt; opt.settings={:?}", opt.b.settings);
let mut has_eq = false;
let no_val = val.is_none();
let empty_vals = opt.is_set(ArgSettings::EmptyValues);
let min_vals_zero = opt.v.min_vals.unwrap_or(1) == 0;
let needs_eq = opt.is_set(ArgSettings::RequireEquals);

debug!("Parser::parse_opt; Checking for val...");
if let Some(fv) = val {
has_eq = fv.starts_with(&[b'=']) || had_eq;
let v = fv.trim_left_matches(b'=');
if !opt.is_set(ArgSettings::EmptyValues) &&
(v.len_() == 0 || (opt.is_set(ArgSettings::RequireEquals) && !has_eq)) {
if !empty_vals &&
(v.len_() == 0 || (needs_eq && !has_eq)) {
sdebugln!("Found Empty - Error");
return Err(Error::empty_value(opt,
&*usage::create_error_usage(self, matcher, None),
Expand All @@ -1546,7 +1551,7 @@ impl<'a, 'b> Parser<'a, 'b>
fv,
fv.starts_with(&[b'=']));
self.add_val_to_arg(opt, v, matcher)?;
} else if opt.is_set(ArgSettings::RequireEquals) && !opt.is_set(ArgSettings::EmptyValues) {
} else if needs_eq && !(empty_vals || min_vals_zero) {
sdebugln!("None, but requires equals...Error");
return Err(Error::empty_value(opt,
&*usage::create_error_usage(self, matcher, None),
Expand All @@ -1561,10 +1566,12 @@ impl<'a, 'b> Parser<'a, 'b>
self.groups_for_arg(opt.b.name)
.and_then(|vec| Some(matcher.inc_occurrences_of(&*vec)));

if val.is_none() ||
!has_eq &&
(opt.is_set(ArgSettings::Multiple) && !opt.is_set(ArgSettings::RequireDelimiter) &&
matcher.needs_more_vals(opt)) {
let needs_delim = opt.is_set(ArgSettings::RequireDelimiter);
let mult = opt.is_set(ArgSettings::Multiple);
if no_val && min_vals_zero && !has_eq && needs_eq {
debugln!("Parser::parse_opt: More arg vals not required...");
return Ok(ParseResult::ValuesDone);
} else if no_val || (mult && !needs_delim) && !has_eq && matcher.needs_more_vals(opt) {
debugln!("Parser::parse_opt: More arg vals required...");
return Ok(ParseResult::Opt(opt.b.name));
}
Expand Down
9 changes: 5 additions & 4 deletions src/app/validator.rs
Expand Up @@ -294,9 +294,9 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
self.0.color()));
}
}
if let Some(num) = a.min_vals() {
let min_vals_zero = if let Some(num) = a.min_vals() {
debugln!("Validator::validate_arg_num_vals: min_vals set: {}", num);
if (ma.vals.len() as u64) < num {
if (ma.vals.len() as u64) < num && num != 0 {
debugln!("Validator::validate_arg_num_vals: Sending error TooFewValues");
return Err(Error::too_few_values(a,
num,
Expand All @@ -306,9 +306,10 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
None),
self.0.color()));
}
}
num == 0
} else { false };
// Issue 665 (https://github.com/kbknapp/clap-rs/issues/665)
if a.takes_value() && !a.is_set(ArgSettings::EmptyValues) && ma.vals.is_empty() {
if a.takes_value() && !(a.is_set(ArgSettings::EmptyValues) || min_vals_zero) && ma.vals.is_empty() {
return Err(Error::empty_value(a,
&*usage::create_error_usage(self.0, matcher, None),
self.0.color()));
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Expand Up @@ -542,7 +542,6 @@ extern crate vec_map;
#[cfg(feature = "wrap_help")]
extern crate term_size;
extern crate textwrap;
extern crate unicode_segmentation;
#[cfg(feature = "color")]
extern crate atty;

Expand Down
31 changes: 31 additions & 0 deletions tests/help.rs
Expand Up @@ -440,6 +440,26 @@ FLAGS:
-h, --help Prints help information
-V, --version Prints version information";

static LONG_ABOUT: &'static str = "myapp 1.0
foo
something really really long, with
multiple lines of text
that should be displayed
USAGE:
myapp [arg1]
FLAGS:
-h, --help
Prints help information
-V, --version
Prints version information
ARGS:
<arg1>
some option";
#[test]
fn help_short() {
let m = App::new("test")
Expand Down Expand Up @@ -784,6 +804,17 @@ fn issue_702_multiple_values() {
assert!(test::compare_output(app, "myapp --help", ISSUE_702, false));
}

#[test]
fn long_about() {
let app = App::new("myapp")
.version("1.0")
.author("foo")
.about("bar")
.long_about("something really really long, with\nmultiple lines of text\nthat should be displayed")
.arg(Arg::with_name("arg1").help("some option"));
assert!(test::compare_output(app, "myapp --help", LONG_ABOUT, false));
}

#[test]
fn issue_760() {
let app = App::new("ctest")
Expand Down
18 changes: 18 additions & 0 deletions tests/opts.rs
Expand Up @@ -28,6 +28,24 @@ fn require_equals_fail() {
assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
}

#[test]
fn require_equals_min_values_zero() {
let res = App::new("prog")
.arg(Arg::with_name("cfg")
.require_equals(true)
.takes_value(true)
.min_values(0)
.long("config"))
.arg(Arg::with_name("cmd"))
.get_matches_from_safe(vec![
"prog", "--config", "cmd"
]);
assert!(res.is_ok());
let m = res.unwrap();
assert!(m.is_present("cfg"));
assert_eq!(m.value_of("cmd"), Some("cmd"));
}

#[test]
fn double_hyphen_as_value() {
let res = App::new("prog")
Expand Down

0 comments on commit 326d0a5

Please sign in to comment.