In particular, fix macros that take an enum of one of the the following forms:
- `#[...] enum { ... , }`
- `pub enum { ... , }`
- `enum { ... , }`
Previously, these expansions would result in an error message like "error: no
rules expected the token `:`".
Add extensive tests for each pattern. Only two of the patterns had tests
before, so these errors did not surface automatically.
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>
1681: WIP: Extract subcommands into separate trait r=pksunkara a=CreepySkeleton
Not-yet-working-but-almost-there "multiple traits" approach. More or less done, what's left is to catch some bugs and adapt tests/examples.
For the record: it took so long because of RL stuff (who would have thought?) and because [there was a detailed description of the experience I've had here, but it was deleted because it contained a lot of profanity and emotional notes].
As the only person alive that understands how the derive works (if you won't blow your own horn, nobody will do it for you, yeah), I'd like to made a statement: we Do need the refactoring.
Co-authored-by: CreepySkeleton <creepy-skeleton@yandex.ru>
1683: Added HelpRequired AppSetting r=pksunkara a=thomasfermi
Closes#1683
There are likely some problems with my solution to this issue. I would be thankful for a review!
Co-authored-by: thomasfermi <mario.theers@gmail.com>
1678: Refactor clap_generate r=CreepySkeleton a=pksunkara
I have copied the code from [clap_generate]( https://github.com/clap-rs/clap_generate) and refactored the structure a bit.
This new structure will allow people to write their own generators using our `Generator` trait which will contain some helpers (Still working on polishing them).
Co-authored-by: Ole Martin Ruud <barskern@outlook.com>
Co-authored-by: Pavan Kumar Sunkara <pavan.sss1991@gmail.com>
1664: Import structopt r=pksunkara a=CreepySkeleton
OK, here is about 50% of what's left to import.
`impl StructOpt for Box<impl StructOpt>` is not imported because layouts of `StructOpt` and `Clap` are too different. I'll work it out after the import is done.
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/clap-rs/clap/1664)
<!-- Reviewable:end -->
Co-authored-by: CreepySkeleton <creepy-skeleton@yandex.ru>
Co-authored-by: Cecile Tonglet <cecile.tonglet@cecton.com>
Co-authored-by: David McNeil <mcneil.david2@gmail.com>
1670: Minor refactoring r=pksunkara a=CreepySkeleton
Some minor improvements. Also gets some bugs fixed
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/clap-rs/clap/1670)
<!-- Reviewable:end -->
Co-authored-by: CreepySkeleton <creepy-skeleton@yandex.ru>
This reverts commit 7dcdfc8b231b41a46d4d7ab7ec2664d32804b4a3.
That commit caused doc tests to break, as well as issues with importing
macros in other modules. Note that the yaml example in `src/lib.rs` at
line 184 is broken and should probably be fixed.
* parse: fix build in debug mode
This fixes a build failure in debug mode, as the value to be printed
does not implement Display.
* output: get rid of an unsafe block
This get rid of an unsafe block which is not necessary, and only used
when building in debug mode.
> 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.
This quotes all field names in errors. It makes easier for humans to
disambiguate common network-related cases which currently end up in
messages like "address is already in use".
The lack of qualification caused odd errors such as:
```
use clap;
let foo = clap::value_t!(matches.value_of("foo"),i u32).unwrap(); # OK
lot bar = clap::value_t!(matches, "bar", u32).unwrap(); # Compile fail
```
but
```
use clap::value_t;
let foo = value_t!(matches.value_of("foo"),i u32).unwrap(); # OK
lot bar = value_t!(matches, "bar", u32).unwrap(); # OK
```
- 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.
The return value is only used in the error case, and only a single
String allocation, therefore the complexities introduced by using string
slices isn't worth it. clap primarily only needs to be as fast as
possible in the happy path, the error path can afford additional
allocations.
The return value is only used in the error case, and only a single
String allocation, therefore the complexities introduced by using string
slices isn't worth it. clap primarily only needs to be as fast as
possible in the happy path, the error path can afford additional
allocations.
Makes the validator functions more flexible by changing the return
type from Result<(), String> to Result<O, E> where O is anything
and E is anything convertible to a String.
This allows, for example, using the same function for validating
and parsing your argument.
Breaking change (albeit tiny) due to function signature change.
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
Once can now mutate an Arg instance after it's already been added to an App struct.
This is helpful when you wish to add all the args in an non-verbose way, such as
via the usage strings, but wish for a handful to have settings which arne't posible
in the usage string definitions.
Adds the abiltiy to query the matches struct for the indices of values or flags. The index
is similar to that of an argv index, but not exactly a 1:1.
For flags (i.e. those arguments which don't have an associated value), indices refer
to occurrence of the switch, such as `-f`, or `--flag`. However, for options the indices
refer to the *values* `-o val` would therefore not represent two distinct indices, only the
index for `val` would be recorded. This is by design.
Besides the flag/option descrepancy, the primary difference between an argv index and clap
index, is that clap continues counting once all arguments have properly seperated, whereas
an argv index does not.
The examples should clear this up.
*NOTE:* If an argument is allowed multiple times, this method will only give the *first*
index.
The argv indices are listed in the comments below. See how they correspond to the clap
indices. Note that if it's not listed in a clap index, this is becuase it's not saved in
in an `ArgMatches` struct for querying.
```rust
let m = App::new("myapp")
.arg(Arg::with_name("flag")
.short("f"))
.arg(Arg::with_name("option")
.short("o")
.takes_value(true))
.get_matches_from(vec!["myapp", "-f", "-o", "val"]);
// ARGV idices: ^0 ^1 ^2 ^3
// clap idices: ^1 ^3
assert_eq!(m.index_of("flag"), Some(1));
assert_eq!(m.index_of("option"), Some(3));
```
Now notice, if we use one of the other styles of options:
```rust
let m = App::new("myapp")
.arg(Arg::with_name("flag")
.short("f"))
.arg(Arg::with_name("option")
.short("o")
.takes_value(true))
.get_matches_from(vec!["myapp", "-f", "-o=val"]);
// ARGV idices: ^0 ^1 ^2
// clap idices: ^1 ^3
assert_eq!(m.index_of("flag"), Some(1));
assert_eq!(m.index_of("option"), Some(3));
```
Things become much more complicated, or clear if we look at a more complex combination of
flags. Let's also throw in the final option style for good measure.
```rust
let m = App::new("myapp")
.arg(Arg::with_name("flag")
.short("f"))
.arg(Arg::with_name("flag2")
.short("F"))
.arg(Arg::with_name("flag3")
.short("z"))
.arg(Arg::with_name("option")
.short("o")
.takes_value(true))
.get_matches_from(vec!["myapp", "-fzF", "-oval"]);
// ARGV idices: ^0 ^1 ^2
// clap idices: ^1,2,3 ^5
//
// clap sees the above as 'myapp -f -z -F -o val'
// ^0 ^1 ^2 ^3 ^4 ^5
assert_eq!(m.index_of("flag"), Some(1));
assert_eq!(m.index_of("flag2"), Some(3));
assert_eq!(m.index_of("flag3"), Some(2));
assert_eq!(m.index_of("option"), Some(5));
```
One final combination of flags/options to see how they combine:
```rust
let m = App::new("myapp")
.arg(Arg::with_name("flag")
.short("f"))
.arg(Arg::with_name("flag2")
.short("F"))
.arg(Arg::with_name("flag3")
.short("z"))
.arg(Arg::with_name("option")
.short("o")
.takes_value(true)
.multiple(true))
.get_matches_from(vec!["myapp", "-fzFoval"]);
// ARGV idices: ^0 ^1
// clap idices: ^1,2,3^5
//
// clap sees the above as 'myapp -f -z -F -o val'
// ^0 ^1 ^2 ^3 ^4 ^5
assert_eq!(m.index_of("flag"), Some(1));
assert_eq!(m.index_of("flag2"), Some(3));
assert_eq!(m.index_of("flag3"), Some(2));
assert_eq!(m.index_of("option"), Some(5));
```
The last part to mention is when values are sent in multiple groups with a [delimiter].
```rust
let m = App::new("myapp")
.arg(Arg::with_name("option")
.short("o")
.takes_value(true)
.multiple(true))
.get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
// ARGV idices: ^0 ^1
// clap idices: ^2 ^3 ^4
//
// clap sees the above as 'myapp -o val1 val2 val3'
// ^0 ^1 ^2 ^3 ^4
assert_eq!(m.index_of("option"), Some(2));
```
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.
This adds a keys method to the internal implementation of vec_map and
adds conditional compilation in the parser to make the parser compile
with or without the vec_map dependency.
Before this commit, ansi_term was compiled anytime the `color` feature
was used. However, on Windows the `color` feature is ignored. Even so
ansi_term was compiled, and just not used. This commit fixes that by
only compiling ansi_term on non-Windows targets. Thanks to @retep998 for
the gudiance.
Closes#1155
This commit primarily changes to a lazy handling of POSIX overrides by
relying on github.com/bluss/ordermap instead of the old HashMap impl.
The ordermap allows us to keep track of which arguments arrived first,
and therefore determine which ones should be removed when an override
conflict is found.
This has the added benefit of we no longer have to do the bookkeeping to
keep track and override args as they come in, we can do it once at the
end.
Finally, ordermap allows fast Vec like iteration of the keys, which we
end up doing several times. Benching is still TBD once the v3 prep is
done, but this change should have a meaningful impact.
Contains a *MINOR* breaking change. App::write_help now requires `&mut self` instead of `&self`.
This fixes a major bug where the help message is entirely incorrect.
More can be found at https://github.com/kbknapp/clap-rs/issues/808
I've decided to make this change because it was preventing further progress.
Anyone's code who breaks the fix is trivial:
```rust
// OLD BROKEN
let app = App::new("broken");
let mut out = io::stdout();
app.write_help(&mut out).expect("failed to write to stdout");
// NEW FIX
let mut app = App::new("broken"); // <-- let mut
let mut out = io::stdout();
app.write_help(&mut out).expect("failed to write to stdout");
```
Closes#808
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.
This commit removes heavy use of macros in certain functions which
drastically increased code size. Some of the macros could be turned
into functions, while others could be removed entirely.
Examples were removing arg_post_processing! which did things like
checked overrides, requirements, groups, etc. This would happen
after every argument was parsed. This macro also had several other
macros inside it, and would expand to several tens or hundreds of
lines of code.
Then add that due to borrowck and branch issues, this macro may be
included in multiple parts of a function. Unlike traditional functions
each of these uses expanded into TONS of code (just like agressive
inlining).
This commit primarily removes those arg_post_processing! calls and
breaks up the functionality into two types. The first must happen at
ever new argument (not new value, but new argument). This is pretty
cheap. The next type was moved to the end of parsing validation section
which is more expensive, but only happens once.
i.e. clap was validating each argument/value as it saw them, now it's
lazy and validates them all at once at the end. This MUCH more
efficient!