Can now use the `App::before_help` method to add additional information
that will be displayed prior to the help message. Common uses are
copyright, or license information.
Adds three new methods of `Arg` which allow for specifying three new
types of rules.
* `Arg::required_unless`
Allows saying a particular arg is only required if a specific other arg
*isn't* present.
* `Arg::required_unless_all`
Allows saying a particular arg is only required so long as *all* the
following args aren't present
* `Arg::required_unless_one`
Allows saying a particular arg is required unless at least one of the
following args is present.
A new Help Engine with templating capabilities
This set of commits brings a new Help System to CLAP.
Major changes are:
- The help format is (almost) completely defined in `help.rs` instead of being scattered across multiple files.
- The HELP object contains a writer and its methods accept AnyArgs, not the other way around.
- A template option allows the user to change completely the organization of the autogenerated help.
The strategy is to copy the template from the the reader to wrapped stream
until a tag is found. Depending on its value, the appropriate content is copied
to the wrapped stream.
The copy from template is then resumed, repeating this sequence until reading
the complete template.
Tags arg given inside curly brackets:
Valid tags are:
* `{bin}` - Binary name.
* `{version}` - Version number.
* `{author}` - Author information.
* `{usage}` - Automatically generated or given usage string.
* `{all-args}` - Help for all arguments (options, flags, positionals arguments,
and subcommands) including titles.
* `{unified}` - Unified help for options and flags.
* `{flags}` - Help for flags.
* `{options}` - Help for options.
* `{positionals}` - Help for positionals arguments.
* `{subcommands}` - Help for subcommands.
* `{after-help}` - Help for flags.
The largest organizational change is that methods used to generate the help are
implemented by the Help object and not the App, FlagBuilder, Parser, etc.
The new code is based heavily on the old one with a few minor modifications
aimed to reduce code duplication and coupling between the Help and the rest
of the code.
The new code turn things around: instead of having a HelpWriter that holds an
AnyArg object and a method that is called with a writer as argument,
there is a Help Object that holds a writer and a method that is called with a
writer as an argument.
There are still things to do such as moving `create_usage` outside the Parser.
The peformance has been affected, probably by the use of Trait Objects. This
was done as a way to reduce code duplication (i.e. in the unified help code).
This performance hit should not affect the usability as generating and printing
the help is dominated by user interaction and IO.
The old code to generate the help is still functional and is the active one.
The new code has been tested against the old one by generating help strings
for most of the examples in the repo.
`write_nspaces` has three differences with `write_spaces`
1. Accepts arguments with attribute access (such as self.writer)
2. The order of the arguments is swapped to make the writer the first
argument as in other write related macros.
3. Does not use the `write!` macro under the hood but rather calls
directly `write`
I have chosen to put the function under a new name to avoid backwards
compatibility problem but it might be better to migrate everything to
`write_nspaces` (and maybe rename it `write_spaces`)
Writing the help requires read only access to Parser's flags, opts
and positionals. This commit provides 3 functions returning iterators
over those collections (`iter_*`) allowing to have function outside
the parser to generate the help.
This commit introduces a new trait (`DispOrder`) with a single function
(`fn disp_order(&self) -> usize`). It is use to expose the display order
of an argument in a read-only manner.
Adds a crate_authors! macro that fetches
crate authors from a (recently added)
cargo enviromental variable populated
from the Cargo file. Like the
crate_version macro.
Closes#447
Passing empty values, such as `--feature ""` now stores the empty string
correctly as a value (assuming empty values are allowed as per the arg
configuration)
Closes#470
Now if the terminal size is too small to properly wrap the help text
lines, it will default to just wrapping normalling as it should.
This is determined on a per help text basis, so because the terminal
size is too small for a single argument's help to wrap properly, all
other arguments will still wrap and align correctly. Only the one
affected argument will not align properly.
Closes#453
The `help` subcommand can now accept other subcommands as arguments to
display their help message. This is similar to how many other CLIs
already perform. For example:
```
$ myprog help mysubcmd
```
Would print the help message for `mysubcmd`. But even more, the `help`
subcommand accepts nested subcommands as well, i.e. a grandchild
subcommand such as
```
$ myprog help child grandchild
```
Would print the help message of `grandchild` where `grandchild` is a
subcommand of `child` and `child` is a subcommand of `myprog`.
Closes#416
By default `clap` now automatically wraps and aligns help strings to the
term width. i.e.
```
-o, --option <opt> some really long help
text that should be auto aligned but isn't righ
t now
```
Now looks like this:
```
-o, --option <opt> some really long help
text that should be
auto aligned but isn't
right now
```
The wrapping also respects words, and wraps at spaces so as to not cut
words in the middle.
This requires the `libc` dep which is enabled (by default) with the
`wrap_help` cargo feature flag.
Closes#428
Args and subcommands can now have their display order automatically
derived by using the setting `AppSettings::DeriveDisplayOrder` which
will display the args and subcommands in the order that they were
declared in, instead of alphabetical order which is the default.
Closes#444
Allows custom ordering of subcommands within the help message. Subcommands with a lower
value will be displayed first in the help message. This is helpful when one would like to
emphasise frequently used subcommands, or prioritize those towards the top of the list.
Duplicate values **are** allowed. Subcommands with duplicate display orders will be
displayed in alphabetical order.
**NOTE:** The default is 999 for all subcommands.
```rust
use clap::{App, SubCommand};
let m = App::new("cust-ord")
.subcommand(SubCommand::with_name("alpha") // typically subcommands are grouped
// alphabetically by name. Subcommands
// without a display_order have a value of
// 999 and are displayed alphabetically with
// all other 999 subcommands
.about("Some help and text"))
.subcommand(SubCommand::with_name("beta")
.display_order(1) // In order to force this subcommand to appear *first*
// all we have to do is give it a value lower than 999.
// Any other subcommands with a value of 1 will be displayed
// alphabetically with this one...then 2 values, then 3, etc.
.about("I should be first!"))
.get_matches_from(vec![
"cust-ord", "--help"
]);
```
The above example displays the following help message
```
cust-ord
USAGE:
cust-ord [FLAGS] [OPTIONS]
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
SUBCOMMANDS:
beta I should be first!
alpha Some help and text
```
Closes#442
Allows custom ordering of args within the help message. Args with a lower value will be
displayed first in the help message. This is helpful when one would like to emphasise
frequently used args, or prioritize those towards the top of the list. Duplicate values
**are** allowed. Args with duplicate display orders will be displayed in alphabetical
order.
**NOTE:** The default is 999 for all arguments.
**NOTE:** This setting is ignored for positional arguments which are always displayed in
index order.
```rust
use clap::{App, Arg};
let m = App::new("cust-ord")
.arg(Arg::with_name("a") // typically args are grouped by alphabetically by name
// Args without a display_order have a value of 999 and are
// displayed alphabetically with all other 999 args
.long("long-option")
.short("o")
.takes_value(true)
.help("Some help and text"))
.arg(Arg::with_name("b")
.long("other-option")
.short("O")
.takes_value(true)
.display_order(1) // Let's force this arg to appear *first*
// all we have to do is give it a value lower than 999
// any other args with a value of 1 would be displayed
// alphabetically with other 1 args. Then 2, then 3, etc.
.help("I should be first!"))
.get_matches_from(vec![
"cust-ord", "--help"
]);
```
The above example displays the following help message
```
cust-ord
USAGE:
cust-ord [FLAGS] [OPTIONS]
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-O, --other-option <b> I should be first!
-o, --long-option <a> Some help and text
```