diff --git a/examples/cargo-example.rs b/examples/cargo-example.rs index 61fcd8aa518..149bf599184 100644 --- a/examples/cargo-example.rs +++ b/examples/cargo-example.rs @@ -5,7 +5,7 @@ fn main() { .bin_name("cargo") .subcommand_required(true) .subcommand( - clap::app_from_crate!().name("example").arg( + clap::command!("example").arg( clap::arg!(--"manifest-path" ) .required(false) .allow_invalid_utf8(true), diff --git a/examples/escaped-positional.rs b/examples/escaped-positional.rs index 814e2a7cbdf..f6d61bd9651 100644 --- a/examples/escaped-positional.rs +++ b/examples/escaped-positional.rs @@ -1,9 +1,9 @@ // Note: this requires the `cargo` feature -use clap::{app_from_crate, arg}; +use clap::{arg, command}; fn main() { - let matches = app_from_crate!() + let matches = command!() .arg(arg!(eff: -f)) .arg(arg!(pea: -p ).required(false)) .arg( diff --git a/examples/tutorial_builder/01_quick.rs b/examples/tutorial_builder/01_quick.rs index 0f7c84fd0ef..bb8b6804611 100644 --- a/examples/tutorial_builder/01_quick.rs +++ b/examples/tutorial_builder/01_quick.rs @@ -1,8 +1,8 @@ -use clap::{app_from_crate, arg, Command}; +use clap::{arg, command, Command}; use std::path::Path; fn main() { - let matches = app_from_crate!() + let matches = command!() .arg(arg!([name] "Optional name to operate on")) .arg( arg!( diff --git a/examples/tutorial_builder/02_app_settings.rs b/examples/tutorial_builder/02_app_settings.rs index 213b6e58bc9..64109424d73 100644 --- a/examples/tutorial_builder/02_app_settings.rs +++ b/examples/tutorial_builder/02_app_settings.rs @@ -1,7 +1,7 @@ -use clap::{app_from_crate, arg, AppSettings}; +use clap::{arg, command, AppSettings}; fn main() { - let matches = app_from_crate!() + let matches = command!() .args_override_self(true) .global_setting(AppSettings::DeriveDisplayOrder) .allow_negative_numbers(true) diff --git a/examples/tutorial_builder/02_crate.rs b/examples/tutorial_builder/02_crate.rs index c36299dab62..05bb14ff3d9 100644 --- a/examples/tutorial_builder/02_crate.rs +++ b/examples/tutorial_builder/02_crate.rs @@ -1,7 +1,7 @@ -use clap::{app_from_crate, arg}; +use clap::{arg, command}; fn main() { - let matches = app_from_crate!() + let matches = command!() .arg(arg!(--two )) .arg(arg!(--one )) .get_matches(); diff --git a/examples/tutorial_builder/03_01_flag_bool.rs b/examples/tutorial_builder/03_01_flag_bool.rs index f19b65b88ee..2b7f6e187e5 100644 --- a/examples/tutorial_builder/03_01_flag_bool.rs +++ b/examples/tutorial_builder/03_01_flag_bool.rs @@ -1,7 +1,7 @@ -use clap::{app_from_crate, arg}; +use clap::{arg, command}; fn main() { - let matches = app_from_crate!().arg(arg!(-v - -verbose)).get_matches(); + let matches = command!().arg(arg!(-v - -verbose)).get_matches(); println!("verbose: {:?}", matches.is_present("verbose")); } diff --git a/examples/tutorial_builder/03_01_flag_count.rs b/examples/tutorial_builder/03_01_flag_count.rs index 6fc15b26816..814593c6c62 100644 --- a/examples/tutorial_builder/03_01_flag_count.rs +++ b/examples/tutorial_builder/03_01_flag_count.rs @@ -1,7 +1,7 @@ -use clap::{app_from_crate, arg}; +use clap::{arg, command}; fn main() { - let matches = app_from_crate!().arg(arg!(-v --verbose ...)).get_matches(); + let matches = command!().arg(arg!(-v --verbose ...)).get_matches(); println!("verbose: {:?}", matches.occurrences_of("verbose")); } diff --git a/examples/tutorial_builder/03_02_option.rs b/examples/tutorial_builder/03_02_option.rs index d03afe0f7b4..fd6737e3862 100644 --- a/examples/tutorial_builder/03_02_option.rs +++ b/examples/tutorial_builder/03_02_option.rs @@ -1,7 +1,7 @@ -use clap::{app_from_crate, arg}; +use clap::{arg, command}; fn main() { - let matches = app_from_crate!() + let matches = command!() .arg(arg!(-n --name ).required(false)) .get_matches(); diff --git a/examples/tutorial_builder/03_03_positional.rs b/examples/tutorial_builder/03_03_positional.rs index ea77ccc2ea2..5ad8e281e7c 100644 --- a/examples/tutorial_builder/03_03_positional.rs +++ b/examples/tutorial_builder/03_03_positional.rs @@ -1,7 +1,7 @@ -use clap::{app_from_crate, arg}; +use clap::{arg, command}; fn main() { - let matches = app_from_crate!().arg(arg!([NAME])).get_matches(); + let matches = command!().arg(arg!([NAME])).get_matches(); println!("NAME: {:?}", matches.value_of("NAME")); } diff --git a/examples/tutorial_builder/03_04_subcommands.rs b/examples/tutorial_builder/03_04_subcommands.rs index dbf27081381..b4f1eeb3d04 100644 --- a/examples/tutorial_builder/03_04_subcommands.rs +++ b/examples/tutorial_builder/03_04_subcommands.rs @@ -1,7 +1,7 @@ -use clap::{app_from_crate, arg, Command}; +use clap::{arg, command, Command}; fn main() { - let matches = app_from_crate!() + let matches = command!() .propagate_version(true) .subcommand_required(true) .arg_required_else_help(true) diff --git a/examples/tutorial_builder/03_05_default_values.rs b/examples/tutorial_builder/03_05_default_values.rs index 28bef52b6d8..2e863ace402 100644 --- a/examples/tutorial_builder/03_05_default_values.rs +++ b/examples/tutorial_builder/03_05_default_values.rs @@ -1,7 +1,7 @@ -use clap::{app_from_crate, arg}; +use clap::{arg, command}; fn main() { - let matches = app_from_crate!() + let matches = command!() .arg(arg!([NAME]).default_value("alice")) .get_matches(); diff --git a/examples/tutorial_builder/04_01_enum.rs b/examples/tutorial_builder/04_01_enum.rs index c3ac8be1bdd..8900b29e58c 100644 --- a/examples/tutorial_builder/04_01_enum.rs +++ b/examples/tutorial_builder/04_01_enum.rs @@ -1,4 +1,4 @@ -use clap::{app_from_crate, arg, ArgEnum, PossibleValue}; +use clap::{arg, command, ArgEnum, PossibleValue}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ArgEnum)] enum Mode { @@ -37,7 +37,7 @@ impl std::str::FromStr for Mode { } fn main() { - let matches = app_from_crate!() + let matches = command!() .arg( arg!() .help("What mode to run the program in") diff --git a/examples/tutorial_builder/04_01_possible.rs b/examples/tutorial_builder/04_01_possible.rs index 33ca131a137..8d43dc5a4f8 100644 --- a/examples/tutorial_builder/04_01_possible.rs +++ b/examples/tutorial_builder/04_01_possible.rs @@ -1,7 +1,7 @@ -use clap::{app_from_crate, arg}; +use clap::{arg, command}; fn main() { - let matches = app_from_crate!() + let matches = command!() .arg( arg!() .help("What mode to run the program in") diff --git a/examples/tutorial_builder/04_02_parse.rs b/examples/tutorial_builder/04_02_parse.rs index ff2bebbe833..817f056d0f4 100644 --- a/examples/tutorial_builder/04_02_parse.rs +++ b/examples/tutorial_builder/04_02_parse.rs @@ -1,7 +1,7 @@ -use clap::{app_from_crate, arg}; +use clap::{arg, command}; fn main() { - let matches = app_from_crate!() + let matches = command!() .arg( arg!() .help("Network port to use") diff --git a/examples/tutorial_builder/04_02_validate.rs b/examples/tutorial_builder/04_02_validate.rs index 1867dbf92d4..03f41540c4f 100644 --- a/examples/tutorial_builder/04_02_validate.rs +++ b/examples/tutorial_builder/04_02_validate.rs @@ -1,11 +1,11 @@ -use clap::{app_from_crate, arg}; +use clap::{arg, command}; use std::ops::RangeInclusive; use std::str::FromStr; const PORT_RANGE: RangeInclusive = 1..=65535; fn main() { - let matches = app_from_crate!() + let matches = command!() .arg(arg!().help("Network port to use").validator(|s| { usize::from_str(s) .map(|port| PORT_RANGE.contains(&port)) diff --git a/examples/tutorial_builder/04_03_relations.rs b/examples/tutorial_builder/04_03_relations.rs index fdd74411b38..6b4df01c6ce 100644 --- a/examples/tutorial_builder/04_03_relations.rs +++ b/examples/tutorial_builder/04_03_relations.rs @@ -1,8 +1,8 @@ -use clap::{app_from_crate, arg, ArgGroup}; +use clap::{arg, command, ArgGroup}; fn main() { // Create application like normal - let matches = app_from_crate!() + let matches = command!() // Add the version arguments .arg(arg!(--"set-ver" "set version manually").required(false)) .arg(arg!(--major "auto inc major")) diff --git a/examples/tutorial_builder/04_04_custom.rs b/examples/tutorial_builder/04_04_custom.rs index 747cc95fb61..67cc67389aa 100644 --- a/examples/tutorial_builder/04_04_custom.rs +++ b/examples/tutorial_builder/04_04_custom.rs @@ -1,8 +1,8 @@ -use clap::{app_from_crate, arg, ErrorKind}; +use clap::{arg, command, ErrorKind}; fn main() { // Create application like normal - let mut cmd = app_from_crate!() + let mut cmd = command!() // Add the version arguments .arg(arg!(--"set-ver" "set version manually").required(false)) .arg(arg!(--major "auto inc major")) diff --git a/examples/tutorial_builder/05_01_assert.rs b/examples/tutorial_builder/05_01_assert.rs index b341cd96385..26f073b6775 100644 --- a/examples/tutorial_builder/05_01_assert.rs +++ b/examples/tutorial_builder/05_01_assert.rs @@ -1,4 +1,4 @@ -use clap::{app_from_crate, arg}; +use clap::{arg, command}; fn main() { let matches = cmd().get_matches(); @@ -11,7 +11,7 @@ fn main() { } fn cmd() -> clap::Command<'static> { - app_from_crate!().arg( + command!().arg( arg!() .help("Network port to use") .validator(|s| s.parse::()), diff --git a/examples/tutorial_builder/README.md b/examples/tutorial_builder/README.md index 9906b386a65..990d6af120f 100644 --- a/examples/tutorial_builder/README.md +++ b/examples/tutorial_builder/README.md @@ -86,7 +86,7 @@ MyApp 1.0 ``` -You can use `app_from_crate!()` to fill these fields in from your `Cargo.toml` +You can use `command!()` to fill these fields in from your `Cargo.toml` file. **This requires the `cargo` feature flag.** [Example:](02_crate.rs) diff --git a/examples/tutorial_derive/README.md b/examples/tutorial_derive/README.md index 71cde2a990c..82f1b10821f 100644 --- a/examples/tutorial_derive/README.md +++ b/examples/tutorial_derive/README.md @@ -89,7 +89,7 @@ MyApp 1.0 ``` -You can use `app_from_crate!()` to fill these fields in from your `Cargo.toml` file. +You can use `command!()` to fill these fields in from your `Cargo.toml` file. [Example:](02_crate.rs) ```console diff --git a/src/build/command.rs b/src/build/command.rs index 5e95fd6854d..bc26924d3e3 100644 --- a/src/build/command.rs +++ b/src/build/command.rs @@ -111,7 +111,7 @@ impl<'help> App<'help> { /// name will only be displayed to the user when they request to print /// version or help and usage information. /// - /// See also [`app_from_crate!`](crate::app_from_crate!) and [`crate_name!`](crate::crate_name!). + /// See also [`command!`](crate::command!) and [`crate_name!`](crate::crate_name!). /// /// # Examples /// diff --git a/src/macros.rs b/src/macros.rs index 49467a616e2..2b04228d251 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -283,15 +283,10 @@ macro_rules! crate_name { /// Allows you to build the `Command` instance from your Cargo.toml at compile time. /// -/// Equivalent to using the `crate_*!` macros with their respective fields. -/// -/// Provided separator is for the [`crate_authors!`] macro, -/// refer to the documentation therefor. -/// /// **NOTE:** Changing the values in your `Cargo.toml` does not trigger a re-build automatically, /// and therefore won't change the generated output until you recompile. /// -/// **Pro Tip:** In some cases you can "trick" the compiler into triggering a rebuild when your +/// In some cases you can "trick" the compiler into triggering a rebuild when your /// `Cargo.toml` is changed by including this in your `src/main.rs` file /// `include_str!("../Cargo.toml");` /// @@ -301,11 +296,36 @@ macro_rules! crate_name { /// # #[macro_use] /// # extern crate clap; /// # fn main() { -/// let m = app_from_crate!().get_matches(); +/// let m = command!().get_matches(); /// # } /// ``` #[cfg(feature = "cargo")] #[macro_export] +macro_rules! command { + () => {{ + $crate::command!($crate::crate_name!()) + }}; + ($name:expr) => {{ + let mut cmd = $crate::Command::new($name).version($crate::crate_version!()); + + let author = $crate::crate_authors!(); + if !author.is_empty() { + cmd = cmd.author(author) + } + + let about = $crate::crate_description!(); + if !about.is_empty() { + cmd = cmd.about(about) + } + + cmd + }}; +} + +/// Deprecated, replaced with [`clap::command!`][crate::command] +#[cfg(feature = "cargo")] +#[deprecated(since = "3.1.0", note = "Replaced with `clap::command!")] +#[macro_export] macro_rules! app_from_crate { () => {{ let mut cmd = $crate::Command::new($crate::crate_name!()).version($crate::crate_version!()); diff --git a/tests/builder/app_from_crate.rs b/tests/builder/app_from_crate.rs index dabd836f3a9..7559e697ce1 100644 --- a/tests/builder/app_from_crate.rs +++ b/tests/builder/app_from_crate.rs @@ -1,4 +1,5 @@ #![cfg(feature = "cargo")] +#![allow(deprecated)] use clap::{app_from_crate, error::ErrorKind}; diff --git a/tests/builder/command.rs b/tests/builder/command.rs new file mode 100644 index 00000000000..9f31d7a9d6a --- /dev/null +++ b/tests/builder/command.rs @@ -0,0 +1,27 @@ +#![cfg(feature = "cargo")] + +use clap::{command, error::ErrorKind}; + +static EVERYTHING: &str = "clap {{version}} +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + clap + +OPTIONS: + -h, --help Print help information + -V, --version Print version information +"; + +#[test] +fn command() { + let res = command!().try_get_matches_from(vec!["clap", "--help"]); + + assert!(res.is_err()); + let err = res.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::DisplayHelp); + assert_eq!( + err.to_string(), + EVERYTHING.replace("{{version}}", env!("CARGO_PKG_VERSION")) + ); +} diff --git a/tests/builder/main.rs b/tests/builder/main.rs index ab181047f2f..124111f1011 100644 --- a/tests/builder/main.rs +++ b/tests/builder/main.rs @@ -6,6 +6,7 @@ mod arg_matcher_assertions; mod arg_settings; mod borrowed; mod cargo; +mod command; mod conflicts; mod default_missing_vals; mod default_vals;