Merge pull request #531 from kbknapp/issues-451,516

Issues 451,516
This commit is contained in:
Kevin K 2016-06-14 22:07:45 -04:00 committed by GitHub
commit ce724d8f61
6 changed files with 185 additions and 22 deletions

View file

@ -1,3 +1,36 @@
<a name="v2.6.0"></a>
## v2.6.0 (2016-06-14)
#### Improvements
* removes extra newline from help output ([86e61d19](https://github.com/kbknapp/clap-rs/commit/86e61d19a748fb9870fcf1175308984e51ca1115))
* allows printing version to any io::Write object ([921f5f79](https://github.com/kbknapp/clap-rs/commit/921f5f7916597f1d028cd4a65bfe76a01c801724))
* removes extra newline when printing version ([7e2e2cbb](https://github.com/kbknapp/clap-rs/commit/7e2e2cbb4a8a0f050bb8072a376f742fc54b8589))
* **Aliases:** improves readability of asliases in help messages ([ca511de7](https://github.com/kbknapp/clap-rs/commit/ca511de71f5b8c2ac419f1b188658e8c63b67846), closes [#526](https://github.com/kbknapp/clap-rs/issues/526), [#529](https://github.com/kbknapp/clap-rs/issues/529))
* **Usage Strings:** improves the default usage string when only a single positional arg is present ([ec86f2da](https://github.com/kbknapp/clap-rs/commit/ec86f2dada1545a63fc72355e22fcdc4c466c215), closes [#518](https://github.com/kbknapp/clap-rs/issues/518))
#### Features
* **Help:** allows wrapping at specified term width (Even on Windows!) ([1761dc0d](https://github.com/kbknapp/clap-rs/commit/1761dc0d27d0d621229d792be40c36fbf65c3014), closes [#451](https://github.com/kbknapp/clap-rs/issues/451))
* **Settings:**
* adds new setting to stop delimiting values with -- or TrailingVarArg ([fc3e0f5a](https://github.com/kbknapp/clap-rs/commit/fc3e0f5afda6d24cdb3c4676614beebe13e1e870), closes [#511](https://github.com/kbknapp/clap-rs/issues/511))
* one can now set an AppSetting which is propogated down through child subcommands ([e2341835](https://github.com/kbknapp/clap-rs/commit/e23418351a3b98bf08dfd7744bc14377c70d59ee), closes [#519](https://github.com/kbknapp/clap-rs/issues/519))
* **Subcommands:** adds support for visible aliases ([7b10e7f8](https://github.com/kbknapp/clap-rs/commit/7b10e7f8937a07fdb8d16a6d8df79ce78d080cd3), closes [#522](https://github.com/kbknapp/clap-rs/issues/522))
#### Bug Fixes
* fixes bug where args are printed out of order with templates ([05abb534](https://github.com/kbknapp/clap-rs/commit/05abb534864764102031a0d402e64ac65867aa87))
* fixes bug where one can't override version or help flags ([90d7d6a2](https://github.com/kbknapp/clap-rs/commit/90d7d6a2ea8240122dd9bf8d82d3c4f5ebb5c703), closes [#514](https://github.com/kbknapp/clap-rs/issues/514))
* fixes issue where before_help wasn't printed ([b3faff60](https://github.com/kbknapp/clap-rs/commit/b3faff6030f76a23f26afcfa6a90169002ed7106))
* **Help:** `App::before_help` and `App::after_help` now correctly wrap ([1f4da767](https://github.com/kbknapp/clap-rs/commit/1f4da7676e6e71aa8dda799f3eeefad105a47819), closes [#516](https://github.com/kbknapp/clap-rs/issues/516))
* **Settings:** fixes bug where new color settings couldn't be converted from strs ([706a7c11](https://github.com/kbknapp/clap-rs/commit/706a7c11b0900be594de6d5a3121938eff197602))
* **Subcommands:** subcommands with aliases now display help of the aliased subcommand ([5354d14b](https://github.com/kbknapp/clap-rs/commit/5354d14b51f189885ba110e01e6b76cca3752992), closes [#521](https://github.com/kbknapp/clap-rs/issues/521))
* **Windows:** fixes a failing windows build ([01e7dfd6](https://github.com/kbknapp/clap-rs/commit/01e7dfd6c07228c0be6695b3c7bf9370d82860d4))
* **YAML:** adds missing YAML methods for App and Arg ([e468faf3](https://github.com/kbknapp/clap-rs/commit/e468faf3f05950fd9f72d84b69aa2061e91c6c64), closes [#528](https://github.com/kbknapp/clap-rs/issues/528))
<a name="v2.5.2"></a>
### v2.5.2 (2016-05-31)

View file

@ -38,6 +38,24 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
## What's New
Here's the highlights for v2.6.0
* **Global Settings:** One can now set an `AppSetting` which is propogated down through child subcommands
* **Terminal Wrapping:** Allows wrapping at specified term width (Even on Windows!) (can now set an absolute width to "smart" wrap at)
* **SubCommands/Aliases:** adds support for visible aliases for subcommands (i.e. aliases that are dipslayed in the help message)
* **Subcommands/Aliases:** when viewing the help of an alias, it now display help of the aliased subcommand
* Improves the default usage string when only a single positional arg is present
* Adds new setting to stop delimiting values with `--` or `AppSettings::TrailingVarArg`
* `App::before_help` and `App::after_help` now correctly wrap
* Fixes bug where positional args are printed out of order when using templates
* Fixes bug where one can't override the auto-generated version or help flags
* Fixes issue where `App::before_help` wasn't printed
* Fixes a failing windows build
* Fixes bug where new color settings couldn't be converted from strings
* Adds missing YAML methods for App and Arg
* Allows printing version to any io::Write object
* Removes extra newline from help and version output
Here's what's new in v.2.5.2
* Removes trailing newlines from help and version output
@ -86,8 +104,6 @@ An example of the optional colored help:
Here's the highlights from v2.2.0
#### Features
* **Help text auto wraps and aligns at term width!** - Long help strings will now properly wrap and align to term width on Linux and OS X (and presumably Unix too). This can be turned off as well.
* **Can customize the order of opts, flags, and subcommands in help messages** - Instead of using the default alphabetical order, you can now re-arrange the order of your args and subcommands in help message. This helps to emphasize more popular or important options.
* **Can auto-derive the order from declaration order** - Have a bunch of args or subcommmands to re-order? You can now just derive the order from the declaration order!
@ -101,13 +117,8 @@ An example of the help text wrapping at term width:
In v2.1.2
#### New Features
* **Default Values**: Args can now specify default values
* **Next Line Help**: Args can have help strings on the line following the argument (useful for long arguments, or those with many values). This can be set command-wide or for individual args
#### Improvements
* **Documentation Examples**: The examples in the documentation have been vastly improved
For full details, see [CHANGELOG.md](https://github.com/kbknapp/clap-rs/blob/master/CHANGELOG.md)

View file

@ -80,7 +80,7 @@ pub struct Help<'a> {
writer: &'a mut Write,
next_line_help: bool,
hide_pv: bool,
term_w: Option<usize>,
term_w: usize,
color: bool,
cizer: Colorizer,
}
@ -88,13 +88,16 @@ pub struct Help<'a> {
// Public Functions
impl<'a> Help<'a> {
/// Create a new `Help` instance.
pub fn new(w: &'a mut Write, next_line_help: bool, hide_pv: bool, color: bool, cizer: Colorizer) -> Self {
pub fn new(w: &'a mut Write, next_line_help: bool, hide_pv: bool, color: bool, cizer: Colorizer, term_w: Option<usize>) -> Self {
debugln!("fn=Help::new;");
Help {
writer: w,
next_line_help: next_line_help,
hide_pv: hide_pv,
term_w: term::dimensions().map(|(w, _)| w),
term_w: match term_w {
Some(width) => width,
None => term::dimensions().map(|(w, _)| w).unwrap_or(120),
},
color: color,
cizer: cizer,
}
@ -132,7 +135,7 @@ impl<'a> Help<'a> {
use_stderr: stderr,
when: parser.color(),
};
Self::new(w, nlh, hide_v, color, cizer).write_help(parser)
Self::new(w, nlh, hide_v, color, cizer, parser.meta.term_w).write_help(parser)
}
/// Writes the parser help to the wrapped stream.
@ -324,6 +327,89 @@ impl<'a> Help<'a> {
Ok(())
}
fn write_before_after_help<'b, 'c>(&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!("Too long...{:?}", too_long);
debug!("Too long...");
if too_long {
sdebugln!("Yes");
help.push_str(h);
debugln!("help: {}", help);
debugln!("help width: {}", str_width(&*help));
// Determine how many newlines we need to insert
debugln!("Usable space: {}", width);
let longest_w = {
let mut lw = 0;
for l in help.split(' ').map(|s| str_width(s)) {
if l > lw {
lw = l;
}
}
lw
};
debugln!("Longest word...{}", longest_w);
debug!("Enough space to wrap...");
if longest_w < width {
sdebugln!("Yes");
let mut indices = vec![];
let mut idx = 0;
loop {
idx += width - 1;
if idx >= help.len() {
break;
}
// 'a' arbitrary non space char
if help.chars().nth(idx).unwrap_or('a') != ' ' {
idx = find_idx_of_space(&*help, idx);
}
debugln!("Adding idx: {}", idx);
debugln!("At {}: {:?}", idx, help.chars().nth(idx));
indices.push(idx);
if str_width(&help[idx..]) <= width {
break;
}
}
for (i, idx) in indices.iter().enumerate() {
debugln!("iter;i={},idx={}", i, idx);
let j = idx + (2 * i);
debugln!("removing: {}", j);
debugln!("at {}: {:?}", j, help.chars().nth(j));
help.remove(j);
help.insert(j, '{');
help.insert(j + 1, 'n');
help.insert(j + 2, '}');
}
} else {
sdebugln!("No");
}
} else {
sdebugln!("No");
}
let help = if !help.is_empty() {
&*help
} else {
help.push_str(h);
&*help
};
if help.contains("{n}") {
if let Some(part) = help.split("{n}").next() {
try!(write!(self.writer, "{}", part));
}
for part in help.split("{n}").skip(1) {
try!(write!(self.writer, "\n{}", part));
}
} else {
try!(write!(self.writer, "{}", help));
}
Ok(())
}
/// Writes argument's help to the wrapped stream.
fn help<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>, longest: usize) -> io::Result<()> {
debugln!("fn=help;");
@ -336,10 +422,9 @@ impl<'a> Help<'a> {
longest + 12
};
// determine if our help fits or needs to wrap
let width = self.term_w.unwrap_or(0);
let width = self.term_w;
debugln!("Term width...{}", width);
let too_long = self.term_w.is_some() &&
(spcs + str_width(h) + str_width(&*spec_vals) >= width);
let too_long = spcs + str_width(h) + str_width(&*spec_vals) >= width;
debugln!("Too long...{:?}", too_long);
// Is help on next line, if so newline + 2x tab
@ -603,7 +688,7 @@ impl<'a> Help<'a> {
pub fn write_default_help(&mut self, parser: &Parser) -> ClapResult<()> {
debugln!("fn=write_default_help;");
if let Some(h) = parser.meta.pre_help {
try!(write!(self.writer, "{}", h));
try!(self.write_before_after_help(h));
try!(self.writer.write(b"\n\n"));
}
@ -638,7 +723,7 @@ impl<'a> Help<'a> {
if flags || opts || pos || subcmds {
try!(self.writer.write(b"\n\n"));
}
try!(write!(self.writer, "{}", h));
try!(self.write_before_after_help(h));
}
self.writer.flush().map_err(Error::from)

View file

@ -13,6 +13,7 @@ pub struct AppMeta<'b> {
pub usage: Option<String>,
pub help_str: Option<&'b str>,
pub disp_ord: usize,
pub term_w: Option<usize>,
pub template: Option<&'b str>,
}
@ -32,6 +33,7 @@ impl<'b> Default for AppMeta<'b> {
disp_ord: 999,
template: None,
aliases: None,
term_w: None,
}
}
}
@ -61,6 +63,7 @@ impl<'b> Clone for AppMeta<'b> {
disp_ord: self.disp_ord,
template: self.template,
aliases: self.aliases.clone(),
term_w: self.term_w,
}
}
}

View file

@ -482,6 +482,35 @@ impl<'a, 'b> App<'a, 'b> {
self
}
/// Sets the terminal width at which to wrap help messages. Defaults to `120`.
///
/// `clap` automatically tries to determine the terminal width on Unix, Linux, and OSX if the
/// `wrap_help` cargo "feature" has been used while compiling. If the terminal width cannot be
/// determined, `clap` defaults to `120`.
///
/// **NOTE:** This setting applies globally and *not* on a per-command basis.
///
/// **NOTE:** This setting must be set **before** any subcommands are added!
///
/// # Platform Specific
///
/// Only Unix, Linux, and OSX support automatic determination of terminal width. Even on those
/// platforms, this setting is useful if for any reason the terminal width cannot be
/// determined.
///
/// # Examples
///
/// ```no_run
/// # use clap::App;
/// App::new("myprog")
/// .set_term_width(80)
/// # ;
/// ```
pub fn set_term_width(mut self, width: usize) -> Self {
self.p.meta.term_w = Some(width);
self
}
/// Adds an [argument] to the list of valid possibilties.
///
/// # Examples

View file

@ -195,6 +195,8 @@ impl<'a, 'b> Parser<'a, 'b>
pub fn add_subcommand(&mut self, mut subcmd: App<'a, 'b>) {
debugln!("fn=Parser::add_subcommand;");
debugln!("Term widnth...{:?}", self.p.meta.term_w);
subcmd.p.meta.term_w = self.meta.term_w;
debug!("Is help...");
if subcmd.p.meta.name == "help" {
sdebugln!("Yes");