From 8513891e07af8b93b670a0dda0e9d83edd6fd44a Mon Sep 17 00:00:00 2001 From: Robin Moussu Date: Sat, 20 Jun 2020 12:52:39 +0200 Subject: [PATCH] Automatically read license field from Cargo.toml --- examples/01a_quick_example.rs | 1 + examples/01b_quick_example.rs | 1 + examples/01c_quick_example.rs | 1 + examples/02_apps.rs | 1 + examples/04_using_matches.rs | 1 + examples/08_subcommands.rs | 1 + examples/18_builder_macro.rs | 1 + examples/20_subcommands.rs | 1 + examples/21_aliases.rs | 1 + src/build/app/mod.rs | 22 ++++++++++++++++++++++ src/macros.rs | 33 +++++++++++++++++++++++++++++++++ 11 files changed, 64 insertions(+) diff --git a/examples/01a_quick_example.rs b/examples/01a_quick_example.rs index f9180c6213c1..57bb48fd3ed6 100644 --- a/examples/01a_quick_example.rs +++ b/examples/01a_quick_example.rs @@ -33,6 +33,7 @@ fn main() { .version("1.0") .author("Kevin K. ") .about("Does awesome things") + .license("MIT OR Apache-2.0") .arg("-c, --config=[FILE] 'Sets a custom config file'") .arg(" 'Sets an optional output file'") .arg("-d..., --debug... 'Turn debugging information on'") diff --git a/examples/01b_quick_example.rs b/examples/01b_quick_example.rs index 9e9ff976f0eb..db6be37a2170 100644 --- a/examples/01b_quick_example.rs +++ b/examples/01b_quick_example.rs @@ -35,6 +35,7 @@ fn main() { .version("1.0") .author("Kevin K. ") .about("Does awesome things") + .license("MIT OR Apache-2.0") .arg( Arg::new("config") .short('c') diff --git a/examples/01c_quick_example.rs b/examples/01c_quick_example.rs index 937dfb57f54c..5c1644e7bed3 100644 --- a/examples/01c_quick_example.rs +++ b/examples/01c_quick_example.rs @@ -32,6 +32,7 @@ fn main() { (version: "1.0") (author: "Kevin K. ") (about: "Does awesome things") + (license: "MIT OR Apache-2.0") (@arg CONFIG: -c --config +takes_value "Sets a custom config file") (@arg INPUT: +required "Sets the input file to use") (@arg debug: -d ... "Sets the level of debugging information") diff --git a/examples/02_apps.rs b/examples/02_apps.rs index 03555317b32d..206b5ebfd6cf 100644 --- a/examples/02_apps.rs +++ b/examples/02_apps.rs @@ -20,6 +20,7 @@ fn main() { .version("1.0") .author("Kevin K. ") .about("Does awesome things") + .license("MIT OR Apache-2.0") .get_matches(); // This example doesn't do much, but it *does* give automatic -h, --help, -V, and --version functionality ;) diff --git a/examples/04_using_matches.rs b/examples/04_using_matches.rs index 806f7b516599..59623aaf438f 100644 --- a/examples/04_using_matches.rs +++ b/examples/04_using_matches.rs @@ -16,6 +16,7 @@ fn main() { // argument. let matches = App::new("MyApp") .about("Parses an input file to do awesome things") + .license("MIT OR Apache-2.0") .version("1.0") .author("Kevin K. ") .arg( diff --git a/examples/08_subcommands.rs b/examples/08_subcommands.rs index 4581c7aaa663..7381b0b6adbe 100644 --- a/examples/08_subcommands.rs +++ b/examples/08_subcommands.rs @@ -24,6 +24,7 @@ fn main() { App::new("add") // The name we call argument with .about("Adds files to myapp") // The message displayed in "myapp -h" // or "myapp help" + .license("MIT OR Apache-2.0") .version("0.1") // Subcommands can have independent version .author("Kevin K.") // And authors .arg( diff --git a/examples/18_builder_macro.rs b/examples/18_builder_macro.rs index 01ce0ab6e7ad..4df765b65bd6 100644 --- a/examples/18_builder_macro.rs +++ b/examples/18_builder_macro.rs @@ -23,6 +23,7 @@ fn main() { (@setting SubcommandRequiredElseHelp) (version: "1.0") (author: "Alice") + (license: "MIT OR Apache-2.0") (about: "Does awesome things") (@arg config: -c --config #{1, 2} {file_exists} "Sets a custom config file") (@arg proxyHostname: --("proxy-hostname") +takes_value "Sets the hostname of the proxy to use") diff --git a/examples/20_subcommands.rs b/examples/20_subcommands.rs index c47c891dc280..190abde550a1 100644 --- a/examples/20_subcommands.rs +++ b/examples/20_subcommands.rs @@ -49,6 +49,7 @@ fn main() { .subcommand( App::new("clone") .about("clones repos") + .license("MIT OR Apache-2.0") .arg(Arg::new("repo").about("The repo to clone").required(true)), ) .subcommand( diff --git a/examples/21_aliases.rs b/examples/21_aliases.rs index 601f02987da5..a8a504a645be 100644 --- a/examples/21_aliases.rs +++ b/examples/21_aliases.rs @@ -6,6 +6,7 @@ fn main() { App::new("ls") .aliases(&["list", "dir"]) .about("Adds files to myapp") + .license("MIT OR Apache-2.0") .version("0.1") .author("Kevin K.") .arg( diff --git a/src/build/app/mod.rs b/src/build/app/mod.rs index 972e86e9c2e9..86c410b6300a 100644 --- a/src/build/app/mod.rs +++ b/src/build/app/mod.rs @@ -81,6 +81,7 @@ pub struct App<'help> { pub(crate) author: Option<&'help str>, pub(crate) version: Option<&'help str>, pub(crate) long_version: Option<&'help str>, + pub(crate) license: Option<&'help str>, pub(crate) about: Option<&'help str>, pub(crate) long_about: Option<&'help str>, pub(crate) help_about: Option<&'help str>, @@ -788,6 +789,27 @@ impl<'help> App<'help> { self } + /// Sets a string of the license to be displayed when displaying help information. + /// + /// **Pro-tip:** Use `clap`s convenience macro [`crate_license!`] to automatically set your + /// application's license to the same thing as your crate at compile time. See the + /// [`examples/`] directory for more information + /// + /// # Examples + /// + /// ```no_run + /// # use clap::{App, Arg}; + /// App::new("myprog") + /// .license("MIT OR Apache-2.0") + /// # ; + /// ``` + /// [`crate_license!`]: ./macro.crate_license!.html + /// [`examples/`]: https://github.com/clap-rs/clap/tree/master/examples + pub fn license>(mut self, license: S) -> Self { + self.license = Some(license.into()); + self + } + /// Overrides the `clap` generated usage string. /// /// This will be displayed to the user when errors are found in argument parsing. diff --git a/src/macros.rs b/src/macros.rs index 0d4cba3e354f..78f232004c71 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -32,6 +32,37 @@ macro_rules! load_yaml { }; } +/// Allows you to pull the licence from your Cargo.toml at compile time. If the `license` field is +/// empty, then the `licence-field` is read. If both fields are empty, then an empty string is +/// returned. +/// +/// # Examples +/// +/// ```no_run +/// # #[macro_use] +/// # extern crate clap; +/// # use clap::App; +/// # fn main() { +/// let m = App::new("app") +/// .version(crate_license!()) +/// .get_matches(); +/// # } +/// ``` +#[cfg(not(feature = "no_cargo"))] +#[macro_export] +macro_rules! crate_license { + () => {{ + let mut license = env!("CARGO_PKG_LICENSE"); + if license.is_empty() { + license = env!("CARGO_PKG_LICENSE_FILE"); + } + if license.is_empty() { + license = ""; + } + license + }}; +} + /// Allows you to pull the version from your Cargo.toml at compile time as /// `MAJOR.MINOR.PATCH_PKGVERSION_PRE` /// @@ -166,12 +197,14 @@ macro_rules! app_from_crate { .version($crate::crate_version!()) .author($crate::crate_authors!()) .about($crate::crate_description!()) + .license($crate::crate_license!()) }; ($sep:expr) => { $crate::App::new($crate::crate_name!()) .version($crate::crate_version!()) .author($crate::crate_authors!($sep)) .about($crate::crate_description!()) + .license($crate::crate_license!()) }; }