Skip to content

Commit

Permalink
Auto merge of #425 - kbknapp:issue-421, r=kbknapp
Browse files Browse the repository at this point in the history
Issue 421, 427, and 429

This PR adds better examples for `Arg` methods as well as

* implements support for displaying the help on the next line (#427)
* Clarifies `AppSettings` propagation rules (#429)
* Fixes failing clippy lints
* Moves github specific files to a `.github` directory

----

Copied from #421

- [x] `short`
- [x] `long`
- [x] `help`
- [x] `required`
- [x] `conflicts_with`
- [x] `conflicts_with_all`
- [x] `overrides_with`
- [x] `overrides_with_all`
- [x] `requires`
- [x] `requires_all`
- [x] `takes_value`
- [x] `index`
- [x] `multiple`
- [x] `global`
- [x] `empty_values`
- [x] `hidden`
- [x] `possible_values`
- [x] `possible_value`
- [x] `group`
- [x] `number_of_values`
- [x] `validator`
- [x] `max_values`
- [x] `min_values`
- [x] `use_delimiter`
- [x] `value_delimiter`
- [x] `value_names`
- [x] `value_name`
- [x] `default_value`
- [x] `next_line_help`
  • Loading branch information
homu committed Feb 19, 2016
2 parents e08fdfb + d0c956c commit 1be8d4d
Show file tree
Hide file tree
Showing 16 changed files with 1,014 additions and 353 deletions.
File renamed without changes.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
<a name="v2.1.1"></a>
### v2.1.1 (2016-02-19)


#### Documentation

* **AppSettings:** clarifies that AppSettings do not propagate ([3c8db0e9](https://github.com/kbknapp/clap-rs/commit/3c8db0e9be1d24edaad364359513cbb02abb4186), closes [#429](https://github.com/kbknapp/clap-rs/issues/429))
* **Arg Examples:** adds better examples ([1e79cccc](https://github.com/kbknapp/clap-rs/commit/1e79cccc12937bc0e7cd2aad8e404410798e9fff))

#### Improvements

* **Help:** adds setting for next line help by arg ([066df748](https://github.com/kbknapp/clap-rs/commit/066df7486e684cf50a8479a356a12ba972c34ce1), closes [#427](https://github.com/kbknapp/clap-rs/issues/427))


<a name="v2.1.0"></a>
## v2.1.0 (2016-02-10)

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

name = "clap"
version = "2.1.0"
version = "2.1.1"
authors = ["Kevin K. <kbknapp@gmail.com>"]
exclude = ["examples/*", "clap-tests/*", "tests/*", "benches/*", "*.png", "clap-perf/*"]
description = "A simple to use, efficient, and full featured Command Line Argument Parser"
Expand Down
68 changes: 6 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,72 +38,16 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)

## What's New

v**2.0** has been released! This means fixing some pain points, new features, better documentation, improved ergonomics, and also some minor breaking changes if you're used to v1.x
In v2.1.1

#### New Features

Here are some key points about the 2.x release
* **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

* Support for arguments with invalid UTF-8 values!: Helps with POSIX and Unix like OSs
* Even better performance boost!
* Far better documentation
* Support for delimited values
* Support for custom delimiter in values
* Support for external subcommands
* Support for options that act as flags (i.e., ones which optionally have no value)
* Support for negative numbers as arguments (i.e., `-10`, etc.)
* Better Errors and error handling
* Improved "from usage" strings
* Better support for generics, instead of being locked in to `Vec` at key points
* Improved macros
* Better regression testing
* Vastly improved ergonomics
* Numerous bug fixes
#### Improvements

![clap Performance Graph](https://github.com/kbknapp/clap-rs/blob/master/clap-perf/clap_perf.png)

#### Breaking Changes

Below is a list of breaking changes between 1.x and 2.x and how you can change your code to update.

* **Fewer lifetimes! Yay!**
* `App<'a, 'b, 'c, 'd, 'e, 'f>` => `App<'a, 'b>`
* `Arg<'a, 'b, 'c, 'd, 'e, 'f>` => `Arg<'a, 'b>`
* `ArgMatches<'a, 'b>` => `ArgMatches<'a>`
* **Simply Renamed**
* `App::arg_group` => `App::group`
* `App::arg_groups` => `App::groups`
* `ArgGroup::add` => `ArgGroup::arg`
* `ArgGroup::add_all` => `ArgGroup::args`
* `ClapError` => `Error`
* `ClapResult` => `Result`
* `ClapErrorType` => `ErrorKind`
* struct field `ClapError::error_type` => `Error::kind`
* **Removed Deprecated Functions and Methods**
* `App::subcommands_negate_reqs`
* `App::subcommand_required`
* `App::arg_required_else_help`
* `App::global_version(bool)`
* `App::versionless_subcommands`
* `App::unified_help_messages`
* `App::wait_on_error`
* `App::subcommand_required_else_help`
* `SubCommand::new`
* `App::error_on_no_subcommand`
* `Arg::new`
* `Arg::mutually_excludes`
* `Arg::mutually_excludes_all`
* `Arg::mutually_overrides_with`
* `simple_enum!`
* **Renamed Errors Variants**
* `InvalidUnicode` => `InvalidUtf8`
* `InvalidArgument` => `UnknownArgument`
* **Usage Parser**
* Value names can now be specified inline: `-o, --option <FILE> <FILE2> 'some option which takes two files'`
* **There is now a priority of order to determine the name** - This is perhaps the biggest breaking change. See the documentation for full details. Prior to this change, the value name took precedence. **Ensure your args are using the proper names (i.e. typically the long or short and NOT the value name) throughout the code**
* `ArgMatches::values_of` returns an `Values` now which implements `Iterator` (should not break any code)
* `crate_version!` returns `&'static str` instead of `String`
* Using the `clap_app!` macro requires compiling with the `unstable` feature because the syntax could change slightly in the future
* **Documenation 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)

Expand Down Expand Up @@ -609,6 +553,6 @@ As of 2.0.0 (From 1.x)

Old method names will be left around for several minor version bumps, or one major version bump.

As of 2.0.0:
As of 2.1.1:

* None!
8 changes: 4 additions & 4 deletions clap-tests/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
-o, --option <opt>... tests options
ARGS:
positional tests positionals
positional2 tests positionals with exclusions
positional3... tests positionals with specific values [values: vi, emacs]
<positional> tests positionals
<positional2> tests positionals with exclusions
<positional3>... tests positionals with specific values [values: vi, emacs]
SUBCOMMANDS:
help Prints this message
Expand Down Expand Up @@ -152,7 +152,7 @@
-o, --option <scoption>... tests options
ARGS:
scpositional tests positionals'''
<scpositional> tests positionals'''

_scfop = '''flag NOT present
option NOT present
Expand Down
19 changes: 10 additions & 9 deletions src/app/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {

fn write_version<W: Write>(&self, w: &mut W) -> io::Result<()> {
if let Some(bn) = self.meta.bin_name.as_ref() {
if bn.contains(" ") {
if bn.contains(' ') {
// Incase we're dealing with subcommands i.e. git mv is translated to git-mv
writeln!(w, "{} {}", bn.replace(" ", "-"), self.meta.version.unwrap_or("".into()))
} else {
Expand Down Expand Up @@ -1400,15 +1400,15 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {

let mut longest_flag = 0;
for fl in self.flags.iter()
.filter(|f| f.long.is_some() && !f.settings.is_set(ArgSettings::Hidden))
.filter(|f| f.long.is_some() && !(f.settings.is_set(ArgSettings::Hidden) || f.settings.is_set(ArgSettings::NextLineHelp)))
.map(|a| a.to_string().len()) {
if fl > longest_flag {
longest_flag = fl;
}
}
let mut longest_opt = 0;
for ol in self.opts.iter()
.filter(|o| !o.settings.is_set(ArgSettings::Hidden))
.filter(|o| !(o.settings.is_set(ArgSettings::Hidden) || o.settings.is_set(ArgSettings::NextLineHelp)))
.map(|a| a.to_string().len()) {
if ol > longest_opt {
longest_opt = ol;
Expand All @@ -1417,7 +1417,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
let mut longest_pos = 0;
for pl in self.positionals
.values()
.filter(|p| !p.settings.is_set(ArgSettings::Hidden))
.filter(|p| !(p.settings.is_set(ArgSettings::Hidden) || p.settings.is_set(ArgSettings::NextLineHelp)))
.map(|f| f.to_string().len()) {
if pl > longest_pos {
longest_pos = pl;
Expand All @@ -1443,17 +1443,18 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
} else {
longest_opt
};
let nlh = self.settings.is_set(AppSettings::NextLineHelp);
if unified_help && (flags || opts) {
try!(write!(w, "\nOPTIONS:\n"));
let mut combined = BTreeMap::new();
for f in self.flags.iter().filter(|f| !f.settings.is_set(ArgSettings::Hidden)) {
let mut v = vec![];
try!(f.write_help(&mut v, tab, longest));
try!(f.write_help(&mut v, tab, longest, nlh));
combined.insert(f.name, v);
}
for o in self.opts.iter().filter(|o| !o.settings.is_set(ArgSettings::Hidden)) {
let mut v = vec![];
try!(o.write_help(&mut v, tab, longest, self.is_set(AppSettings::HidePossibleValuesInHelp)));
try!(o.write_help(&mut v, tab, longest, self.is_set(AppSettings::HidePossibleValuesInHelp), nlh));
combined.insert(o.name, v);
}
for (_, a) in combined {
Expand All @@ -1468,7 +1469,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
.map(|f| (f.name, f))
.collect::<BTreeMap<_, _>>()
.values() {
try!(f.write_help(w, tab, longest));
try!(f.write_help(w, tab, longest, nlh));
}
}
if opts {
Expand All @@ -1478,15 +1479,15 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
.map(|o| (o.name, o))
.collect::<BTreeMap<_, _>>()
.values() {
try!(o.write_help(w, tab, longest_opt, self.is_set(AppSettings::HidePossibleValuesInHelp)));
try!(o.write_help(w, tab, longest_opt, self.is_set(AppSettings::HidePossibleValuesInHelp), nlh));
}
}
}
if pos {
try!(write!(w, "\nARGS:\n"));
for v in self.positionals.values()
.filter(|p| !p.settings.is_set(ArgSettings::Hidden)) {
try!(v.write_help(w, tab, longest_pos, self.is_set(AppSettings::HidePossibleValuesInHelp)));
try!(v.write_help(w, tab, longest_pos, self.is_set(AppSettings::HidePossibleValuesInHelp), nlh));
}
}
if subcmds {
Expand Down
66 changes: 43 additions & 23 deletions src/app/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,27 @@ use std::ascii::AsciiExt;

bitflags! {
flags Flags: u32 {
const SC_NEGATE_REQS = 0b00000000000000000001,
const SC_REQUIRED = 0b00000000000000000010,
const A_REQUIRED_ELSE_HELP = 0b00000000000000000100,
const GLOBAL_VERSION = 0b00000000000000001000,
const VERSIONLESS_SC = 0b00000000000000010000,
const UNIFIED_HELP = 0b00000000000000100000,
const WAIT_ON_ERROR = 0b00000000000001000000,
const SC_REQUIRED_ELSE_HELP= 0b00000000000010000000,
const NEEDS_LONG_HELP = 0b00000000000100000000,
const NEEDS_LONG_VERSION = 0b00000000001000000000,
const NEEDS_SC_HELP = 0b00000000010000000000,
const DISABLE_VERSION = 0b00000000100000000000,
const HIDDEN = 0b00000001000000000000,
const TRAILING_VARARG = 0b00000010000000000000,
const NO_BIN_NAME = 0b00000100000000000000,
const ALLOW_UNK_SC = 0b00001000000000000000,
const UTF8_STRICT = 0b00010000000000000000,
const UTF8_NONE = 0b00100000000000000000,
const LEADING_HYPHEN = 0b01000000000000000000,
const NO_POS_VALUES = 0b10000000000000000000,
const SC_NEGATE_REQS = 0b000000000000000000001,
const SC_REQUIRED = 0b000000000000000000010,
const A_REQUIRED_ELSE_HELP = 0b000000000000000000100,
const GLOBAL_VERSION = 0b000000000000000001000,
const VERSIONLESS_SC = 0b000000000000000010000,
const UNIFIED_HELP = 0b000000000000000100000,
const WAIT_ON_ERROR = 0b000000000000001000000,
const SC_REQUIRED_ELSE_HELP= 0b000000000000010000000,
const NEEDS_LONG_HELP = 0b000000000000100000000,
const NEEDS_LONG_VERSION = 0b000000000001000000000,
const NEEDS_SC_HELP = 0b000000000010000000000,
const DISABLE_VERSION = 0b000000000100000000000,
const HIDDEN = 0b000000001000000000000,
const TRAILING_VARARG = 0b000000010000000000000,
const NO_BIN_NAME = 0b000000100000000000000,
const ALLOW_UNK_SC = 0b000001000000000000000,
const UTF8_STRICT = 0b000010000000000000000,
const UTF8_NONE = 0b000100000000000000000,
const LEADING_HYPHEN = 0b001000000000000000000,
const NO_POS_VALUES = 0b010000000000000000000,
const NEXT_LINE_HELP = 0b100000000000000000000,
}
}

Expand Down Expand Up @@ -55,11 +56,15 @@ impl AppFlags {
StrictUtf8 => UTF8_STRICT,
AllowInvalidUtf8 => UTF8_NONE,
AllowLeadingHyphen => LEADING_HYPHEN,
HidePossibleValuesInHelp => NO_POS_VALUES
HidePossibleValuesInHelp => NO_POS_VALUES,
NextLineHelp => NEXT_LINE_HELP
}
}

/// Application level settings, which affect how `App` operates
///
/// **NOTE:** When these settings are used, they apply only to current command, and are *not*
/// propagated down or up through child or parent subcommands
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum AppSettings {
/// Allows subcommands to override all requirements of the parent command. For example
Expand Down Expand Up @@ -374,7 +379,8 @@ pub enum AppSettings {
/// assert_eq!(m.value_of_os("arg").unwrap().as_bytes(), &[0xe9]);
/// ```
AllowInvalidUtf8,
/// Specifies that leading hyphens are allowed in argument values, such as `-10`
/// Specifies that leading hyphens are allowed in argument *values*, such as negative numbers
/// `-10`
///
/// **NOTE:** This can only be set application wide and not on a per argument basis.
///
Expand All @@ -398,9 +404,22 @@ pub enum AppSettings {
/// # ;
/// ```
AllowLeadingHyphen,
/// Tells `clap` *not* to print possible values when displaying help information. This can be
/// Tells `clap` *not* to print possible values when displaying help information. This can be
/// useful if there are many values, or they are explained elsewhere.
HidePossibleValuesInHelp,
/// Places the help string for all arguments on the line after the argument
///
/// **NOTE:** This setting is cosmetic only and does not affect any functionality.
///
/// # Examples
///
/// ```no_run
/// # use clap::{App, Arg, SubCommand, AppSettings};
/// App::new("myprog")
/// .setting(AppSettings::NextLineHelp)
/// .get_matches();
/// ```
NextLineHelp,
#[doc(hidden)]
NeedsLongVersion,
#[doc(hidden)]
Expand Down Expand Up @@ -431,6 +450,7 @@ impl FromStr for AppSettings {
"allowinvalidutf8" => Ok(AppSettings::AllowInvalidUtf8),
"allowleadinghyphen" => Ok(AppSettings::AllowLeadingHyphen),
"hidepossiblevaluesinhelp" => Ok(AppSettings::HidePossibleValuesInHelp),
"nextlinehelp" => Ok(AppSettings::NextLineHelp),
_ => Err("unknown AppSetting, cannot convert from str".to_owned()),
}
}
Expand Down
Loading

0 comments on commit 1be8d4d

Please sign in to comment.