1612: Use about() with help() and long_about() with long_help() r=pksunkara a=TheLostLambda
I was going through the clap documentation and was under the impression that calling `help()` would call `about()` and `long_help()` would call `long_about()`, but I've actually discovered this not to be the case. Instead, the `long_about()` was always shown when it existed, rendering the output (in the about section) of programs called with `-h` and `--help` identical. Issue #1472 shows this and that is fixed here.
Note this doesn't remove the ability to use the same about in both cases: if `long_about()` is unset, then `about()` is used in both cases.
I've changed the implementation here to use `is_some()` and `unwrap()` as opposed to `if let` because it ultimately allows for less repetitive code. Ideally, I'd be able to pair `if let` with a secondary condition (namely `self.use_long`), but to my dismay, let-chains are not stabilized yet.
For a second opinion, here is the code a settled on:
```
if self.use_long && parser.meta.long_about.is_some() {
debugln!("Help::write_default_help: writing long about");
write_thing!(parser.meta.long_about.unwrap())
} else if parser.meta.about.is_some() {
debugln!("Help::write_default_help: writing about");
write_thing!(parser.meta.about.unwrap())
}
```
Here is the alternative:
```
if self.use_long {
if let Some(about) = parser.meta.long_about {
debugln!("Help::write_default_help: writing long about");
write_thing!(about)
} else if let Some(about) = parser.meta.about {
debugln!("Help::write_default_help: writing about");
write_thing!(about)
}
} else {
if let Some(about) = parser.meta.about {
debugln!("Help::write_default_help: writing about");
write_thing!(about)
}
}
```
Co-authored-by: Brooks J Rady <b.j.rady@gmail.com>
> incidentally, how do we feel about adding a rustfmt check to the CI(s)?
yes we should be doing that. you can send another pr that adds the check to the Ci
The example code.
~~~rust
use clap::{App, Arg};
fn main() {
let matches = App::new("My Super Program")
.arg(
Arg::with_name("verbose")
.help("Sets the level of verbosity")
.short('v')
.long("verbose")
.takes_value(false)
.multiple_occurrences(true)
.env("VERBOSE"),
)
.get_matches();
match matches.occurrences_of("verbose") {
0 => println!("0 No verbose info"),
1 => println!("1 Some verbose info"),
2 => println!("2 Tons of verbose info"),
3 | _ => println!("3 >= Don't be crazy"),
}
}
~~~
It code use multiple_occurrences with env.
But it do not work.
`env` method set require take value.
It result see under.
~~~console
% cargo run -- -v
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/foo -v`
error: The argument '--verbose <verbose>...' requires a value but none was supplied
USAGE:
foo [OPTIONS]
For more information try --help
~~~
And, structopt or clap_derive may be create similar code.
So I am confused by structopt.
This to fix code small.
- Manually fix some problems
- Run 'cargo fix --clippy'
Commits taken from similar PRs open at that time:
- Replace indexmap remove with swap_remove
Resolves#1562 and closes#1563
- Use cognitive_complexity for clippy lint
Resolves#1564 and closes#1565
- Replace deprecated trim_left_matches with trim_start_matches
Closes#1539
Co-authored-by: Antoine Martin <antoine97.martin@gmail.com>
Co-authored-by: Brian Foley <bpfoley@users.noreply.github.com>
This patch:
* Removes the `ArgSettings::Global` variant, and replaces all
users of it to `Arg::global(...)`. The variant itself is lifted up
into a field on Arg. This was deprecated in clap 2.32.0.
* Removes AppFlags::PropagateGlobalValuesDown. This was deprecated in
clap 2.27.0.
* Removes `Arg::empty_values`. This was deprecated in clap 2.30.0.
* Removes `ArgMatches::usage`. This was deprecated in clap 2.32.0.
subcommands
This commit changes the internal ID to a u64 which will allow for
greater optimizations down the road. In addition, it lays the ground
work for allowing users to use things like enum variants as argument
keys instead of strings.
The only downside is each key needs to be hashed (the implementation
used is an FNV hasher for performance). However, the performance gains
in faster iteration, comparison, etc. should easily outweigh the single
hash of each argument.
Another benefit of if this commit is the removal of several lifetime
parameters, as it stands Arg and App now only have a single lifetime
parameter, and ArgMatches and ArgGroup have no lifetime parameter.
Args can now be added to custom help sections. This breaks up the builder pattern a little by adding help section declarations inline, but it's the most intuitive method and doesn't require strange nesting that feels awkward.
```rust
app::new("foo")
.arg(Arg::with_name("arg1")) // under normal headers
.help_heading("SPECIAL")
.arg(Arg::with_name("arg2")) // under SPECIAL: heading
```
Closes#805
Add logic to filter based on hidden long/short.
There is still an issue with the logic in parser.rs use_long_help. This
causes invalid evaluation of whether to show/hide based on long or short help
Complete check for use_long_help, add tests
For version 3, we want the args section to immediately follow
the usage section in the default help message.
One change that I am unhappy with is needing to make "write_arg"
in app/help.rs accept an extra param that makes it suppress the
extra line. This is to prevent an extra blank line from appearing
between args and options in the default help, and seems necessary,
but there might be a better way.
Optional positionals mixed with subcommands will still break this, since
I can't see how to tell which element of $line is the command than.
Mixing optional positionals with subcommands is a bit weird and awkward
though...
This changes the way we complete positionals to complete them using
_arguments, as should be done, instead of completing their uppercase name
as a string.
Currently I made it offer _files completion for all positional arguments.
This can be improved to complete actual possible values of the arguments
and only complete files if the argument truly takes them. But this will
require further changes in clap to actually have the required
functionality to get this information.
Long options take their argument either in the next word or after an
equals sign, but the Zsh completion specified that they take it either
in the same word with no separator or in the next word. See the
documentation of the Zsh _arguments function for more information.
From -> To
===========================================
with_underscore -> (with_)?special_commands
WUS -> SPECIAL_CMDS
special -> special_help
SPECIAL -> SPECIAL_HELP
When used with `Arg::possible_values` it allows the argument value to pass validation even if
the case differs from that of the specified `possible_value`.
```rust
let m = App::new("pv")
.arg(Arg::with_name("option")
.long("--option")
.takes_value(true)
.possible_value("test123")
.case_insensitive(true))
.get_matches_from(vec![
"pv", "--option", "TeSt123",
]);
assert!(m.value_of("option").unwrap().eq_ignore_ascii_case("test123"));
```
This setting also works when multiple values can be defined:
```rust
let m = App::new("pv")
.arg(Arg::with_name("option")
.short("-o")
.long("--option")
.takes_value(true)
.possible_value("test123")
.possible_value("test321")
.multiple(true)
.case_insensitive(true))
.get_matches_from(vec![
"pv", "--option", "TeSt123", "teST123", "tESt321"
]);
let matched_vals = m.values_of("option").unwrap().collect::<Vec<_>>();
assert_eq!(&*matched_vals, &["TeSt123", "teST123", "tESt321"]);
```
Closes#1118
If one is using a nightly Rust compiler they should compile clap
with the `nightly` feature.
```toml
[dependencies]
clap = { version = "2.27", features = ["nightly"] }
```
This isn't required for compilation to succeed, only to take
advantage of any nightly features used by clap.
If one is compiling with `#[deny(warnings)]` this commit will cause
compilation to fail if one *does not* compile with the `nightly`
since `std::ascii::AsciiExt` is no longer required in in multiple
files as of the latest Rust nightly (Nov 6th, 2017).
Closes#1095
Issue 978 mentions that subcommands cannot see the value
of globals that get passed, even if ArgSettings::PropagateGlobalsDown
is true.
This change commits a failing test that reproduces this error.
This doc attribute is used by rustdoc when generating documentation
for other crates that depend on this crate. With the html_root_url,
rustdoc will be able to generate correct links into this crate.
See C-HTML-ROOT in the Rust API Guidelines for more information:
https://rust-lang-nursery.github.io/api-guidelines/documentation.html#crate-sets-html_root_url-attribute-c-html-root
A version-sync check was added to ensure that the URL is kept up to
date when the crate version changes.
The textwrap crate uses a simpler linear-time algorithm for wrapping
the text. The current algorithm in wrap_help uses several O(n) calls
to String::insert and String::remove, which makes it potentially
quadratic in complexity.
Comparing the 05_ripgrep benchmark at commits textwrap~2 and textwrap
gives this result on my machine:
name before ns/iter after ns/iter diff ns/iter diff %
build_app_long 22,101 21,099 -1,002 -4.53%
build_app_short 22,138 21,205 -933 -4.21%
build_help_long 514,265 284,467 -229,798 -44.68%
build_help_short 85,720 85,693 -27 -0.03%
parse_clean 23,471 22,859 -612 -2.61%
parse_complex 29,535 28,919 -616 -2.09%
parse_lots 422,815 414,577 -8,238 -1.95%
As part of this commit, the wrapping_newline_chars test was updated.
The old algorithm had a subtle bug where it would break lines too
early. That is, it wrapped the text like
ARGS:
<mode> x, max, maximum 20 characters, contains
symbols.
l, long Copy-friendly,
14 characters, contains symbols.
m, med, medium Copy-friendly, 8
characters, contains symbols.";
when it should really have wrapped it like
ARGS:
<mode> x, max, maximum 20 characters, contains
symbols.
l, long Copy-friendly, 14
characters, contains symbols.
m, med, medium Copy-friendly, 8
characters, contains symbols.";
Notice how the word "14" was incorrectly moved to the next line. There
is clearly room for the word on the line with the "l, long" option
since there is room for "contains" just above it.
I'm not sure why this is, but the algorithm in textwrap handles this
case correctly.