diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d7d4395..5f224f32 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,36 @@
+
+## 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))
+
+
+
### v2.5.2 (2016-05-31)
diff --git a/README.md b/README.md
index 4d5e130d..2aeb3288 100644
--- a/README.md
+++ b/README.md
@@ -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)
diff --git a/src/app/help.rs b/src/app/help.rs
index 0831f225..b77e4753 100644
--- a/src/app/help.rs
+++ b/src/app/help.rs
@@ -80,7 +80,7 @@ pub struct Help<'a> {
writer: &'a mut Write,
next_line_help: bool,
hide_pv: bool,
- term_w: Option,
+ 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) -> 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)
diff --git a/src/app/meta.rs b/src/app/meta.rs
index 4fb63290..b22c09af 100644
--- a/src/app/meta.rs
+++ b/src/app/meta.rs
@@ -13,6 +13,7 @@ pub struct AppMeta<'b> {
pub usage: Option,
pub help_str: Option<&'b str>,
pub disp_ord: usize,
+ pub term_w: Option,
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,
}
}
}
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 03675b4f..f8006adf 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -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
@@ -640,7 +669,7 @@ impl<'a, 'b> App<'a, 'b> {
self
}
- /// Allows adding a [`SubCommand`] alias that functions exactly like those defined with
+ /// Allows adding a [`SubCommand`] alias that functions exactly like those defined with
/// [`App::alias`], except that they are visible inside the help message.
///
/// # Examples
@@ -664,7 +693,7 @@ impl<'a, 'b> App<'a, 'b> {
self
}
- /// Allows adding multiple [`SubCommand`] aliases that functions exactly like those defined
+ /// Allows adding multiple [`SubCommand`] aliases that functions exactly like those defined
/// with [`App::aliases`], except that they are visible inside the help message.
///
/// # Examples
diff --git a/src/app/parser.rs b/src/app/parser.rs
index bedb90dd..e194b154 100644
--- a/src/app/parser.rs
+++ b/src/app/parser.rs
@@ -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");
@@ -532,14 +534,14 @@ impl<'a, 'b> Parser<'a, 'b>
}
} else if let Some(c) = sc.subcommands
.iter()
- .filter(|s|
+ .filter(|s|
if let Some(ref als) = s.p
.meta
- .aliases {
+ .aliases {
als.iter()
.any(|&(a, _)| &a == &&*cmd.to_string_lossy())
- } else {
- false
+ } else {
+ false
}
)
.next()