3.x is being worked on!

Since my last post, countless bug fixes, features, etc. have been merged into the project. There’s also a wave of new contributors who I’m immensely grateful for!

Something I’ve been struggling with for the past few months is conflicting priorities to get 3.x out the door, and include all the new feature requests. All this while having very little time to actually work on clap. My paid day job has been monopolizing my time for 2017 in an unfair way, I’ve been doing more traveling this year than in nearly all of 2015 and 2016 combined!

I’ve decided it’s time to get to work, I’m implementing a feature freeze for clap in an effort to get 3.x out the door, at which point the refactoring made in 3.x should also make implementing these feature requests far easier.

What Will Be New?

3.x has few “killer features” that should be headlining, namely Custom Derive, the ability to use enums as argument keys (i.e. getting away from “stringly typed” APIs), and using serde as the serialization framework. There are then several primary feature requests that will be priority number one once 3.x is available.

Some of the 3.x features will be offered as new crates, provided inside the clap repository (similar to how ripgrep offers it’s various crates), other features are being pulled out of mainline clap and moving into external crates (such as the completion generation code).

This should make the projects less monolithic, and easier to contribute to.

Custom Derive

The goal of custom derive will be to provide two or three primary traits that allow one to take an arbitrary struct and derive a clap::App from said struct, or take a clap::ArgMatches struct and convert back into your arbitrary struct. This is similar to what’s currently provided by structopt, which I’m hoping to collaborate with, or move into mainline clap.

The end result should look like this on a nightly compiler:

 

Then running:

A stable compiler should be the same, minus the IntoApp trait, where one would still have to define the:

 

But both cases are leaps and bounds better than current 2.x clap.

Enums as Argument Keys

To go along with the custom derive, I plan on providing another derivable trait to allow using enums as argument keys. So this would be possible (which would also work with subcommands):

 

This has a huge benefit of not compiling typos. For example, currently if I type, matches.is_present("verbse") my code will happily compile, and it won’t be until I reach a runtime path which executes that code that I’ll find my mistake.

The same can be said for subcommands, and adding new subcommands:

 

 

This will fail to compile because I didn’t exhaust the match possibilities and include Push(..) in the match statement.

serde

Using serde should go without saying. All clap structs will derive and implement the appropriate serde traits to allow going to/from any serde supported formats 🙂

The Ability to Mutate Args (Finally!)

3.x should also contain the ability to mutate Arg instances even after they’ve been added to an App instance. This will greatly simplify most CLI definitions as one could use the Arg::from(&str) methods and make small changes to specific args that require additional details. The exposed APIs will be something along the lines of:

  • App::mut_arg
  • App::mut_group
  • App::mut_subcommand

More Lean

The codebase should also be much more lean and easy to follow for new contributors helping everyone get involved. All this new custom derive work will take place in the clap_derive crate, and all completion generation will move to the clap_completions crate. Both of which will be hosted in the mainline clap repository.

I’ve toyed with the idea of moving the macros into a separate clap_macros crate, but at this time I will leave them in mainline.

Much, Much More

There will be quite a few other changes. If you’re curious about what they may be, look at the clap issue tracker for feature requests. Nearly all feature requests which have been tagged will be implemented in the early days of 3.x!

Sequence of Events

I plan on releasing 3.0-alpha.1 in the next few months (time permitting) which will contain all the deprecations, and new features. Most 2.x code should still work. This will provide a time to file bugs, and slowly move to 3.x APIs (which will be listed in the deprecation warnings).

After 30 days of 3.0-alpha.1 and no major regressions (small fixes will be released as 3.0-alpha.x and will not reset the 30 day window unless a major regression is found near the end of the 30 days), I will release 3.0-beta.1 which will remove all 2.x deprecations. At this point, 2.x code will break. This will give a chance to file bug reports and make any last minute changes.

After 30 days of 3.0-beta.x and no major changes, I will release 3.0-rc.1. By this point all major bugs should have already been fixed.

After 30 days of 3.0-rc.x with no major regressions, I will put out 3.0.0!

It’s a long cycle, but there are many, many changes. Hopefully everyone will enjoy the ride!

Kevin