mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 06:42:33 +00:00
commit
ce724d8f61
6 changed files with 185 additions and 22 deletions
33
CHANGELOG.md
33
CHANGELOG.md
|
@ -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)
|
||||
|
||||
|
|
25
README.md
25
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)
|
||||
|
|
103
src/app/help.rs
103
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<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)
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in a new issue