clap v4.2.0 is now out with styling of help descriptions! See the changelog for more details.
What Changed in v4.2.0
User Styling of Help Descriptions
By default, clap will style the output of --help
but there wasn't a way for
users to do the same, whether to emphasize something or for a custom section,
like "Examples".
As previously discussed, we settled on using ANSI escape codes for this so you can use the library of your choice. For example, with the color-print crate, you can now do:
// `cstr!` converts tags to ANSI codes
let after_help: &'static str = color_print::cstr!(
r#"<bold><underline>Examples</underline></bold>
<dim>$</dim> <bold>mybin --input file.toml</bold>
"#);
let cmd = clap::Command::new("mybin")
.after_help(after_help) // The `&str` gets converted into a `StyledStr`
// ...
To know if ANSI escape codes will be handled properly, look for builder methods that accept
StyledStr
.
Further Error Tweaks
In clap v4.1, we changed error messages. This release further iterates on them based on feedback we received.
clap v4.0:
error: Found argument '--optio' which wasn't expected, or isn't valid in this context
Did you mean '--option'?
Usage: clap-test --option <opt>... [positional] [positional2] [positional3]...
For more information try '--help'
clap v4.1:
error: unexpected argument '--optio'
note: argument '--option' exists
Usage: clap-test --option <opt>... [positional] [positional2] [positional3]...
For more information, try '--help'.
clap v4.2:
error: unexpected argument '--optio'
tip: a similar argument exists: '--option'
Usage: clap-test --option <opt>... [positional] [positional2] [positional3]...
For more information, try '--help'.
I'm sure there is room for improvement. We welcome further discussion on this on #4638.
Removed unstable-replace
We've had
Command::replace
behind the unstable-replace
feature flag since 3.0.0 but there has been little
interest expressed in it and the design doesn't align well with the rest of
clap, so we've removed it.
As alternatives
- For commands that are meant to expand to nested subcommands, we recommend
just creating a
Command
for it and having it reuse the relevant args and help. - For args implying other args, we hope to solve this with #4793.
If you have any feedback on this decision, we welcome it at #2836.
What Changed in v4.1.x
While minor releases get a lot more attention, there is still a lot of interesting work done in patch releases that deserve being highlighted.
Build Times
We've seen several different build-time improvements including
- Speed up of the
arg!
macro - Split out a
clap_builder
crate to parallelize its build withclap_derive
- Builder users should not notice the difference because the
clap
facade gets built in parallel toclap_builder
s code-gen
- Builder users should not notice the difference because the
- Removed some dependencies including
proc-macro-error
(derive-specific)
For very unscientific numbers:
v4.1.0 | v4.2.0 | |
---|---|---|
clap $ cargo build | 4.250s | 3.923s |
clap $ cargo build -F derive | 6.419s | 4.602s |
For more numbers, see argparse-rosetta-rs.
Deriving ArgGroup
In clap v4.0.0, we automatically generate an
ArgGroup
for each
derived Args
but there was no way to customize the ArgGroup
, requiring
people to still manually create them in some cases:
#[derive(Parser)]
#[command(group(
ArgGroup::new("vers")
.required(true)
.args(["set_ver", "major", "minor", "patch"]),
))]
struct Cli {
/// set version manually
#[arg(long, value_name = "VER")]
set_ver: Option<String>,
/// auto inc major
#[arg(long)]
major: bool,
/// auto inc minor
#[arg(long)]
minor: bool,
/// auto inc patch
#[arg(long)]
patch: bool,
/// some regular input
#[arg(group = "input")]
input_file: Option<String>,
}
We now support #[group]
raw attributes,
allowing
any ArgGroup
builder method
to be used:
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(flatten)]
vers: Vers,
/// some regular input
#[arg(group = "input")]
input_file: Option<String>,
}
#[derive(Args)]
#[group(required = true, multiple = false)]
struct Vers {
/// set version manually
#[arg(long, value_name = "VER")]
set_ver: Option<String>,
/// auto inc major
#[arg(long)]
major: bool,
/// auto inc minor
#[arg(long)]
minor: bool,
/// auto inc patch
#[arg(long)]
patch: bool,
}
Granted, the above would be better expressed as an enum
which we are tracking
in #2621.