From 1a84ce22bcd6bccc57aef1d24ca148e5e8c459d5 Mon Sep 17 00:00:00 2001 From: nabijaczleweli Date: Sun, 18 Dec 2016 13:17:34 +0100 Subject: [PATCH 1/4] Replace colons with newlines in crate_authors!() The implementation is basically manually expanded lazy_static! macro (with some hand-crafted simplifications and inlining), since you can't use extern crates (and therefore import macros therefrom) in macros. This ensures that you get this: p:\Rust\http>target\debug\http -h http 0.1.0 thecoshman nabijaczleweli Host These Things Please - a basic HTTP server for hosting a folder fast and simply Instead of this: p:\Rust\http>target\debug\http -h http 0.1.0 thecoshman :nabijaczleweli Host These Things Please - a basic HTTP server for hosting a folder fast and simply Closes #779 --- src/macros.rs | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 9478857cb0a..a6e817c50f1 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -411,9 +411,48 @@ macro_rules! crate_version { /// ``` #[macro_export] macro_rules! crate_authors { - () => { - env!("CARGO_PKG_AUTHORS") - }; + () => {{ + use std::ops::Deref; + use std::sync::{ONCE_INIT, Once}; + + struct Lazy(pub *const T, pub Once); + + impl Lazy { + #[inline(always)] + pub fn get T>(&'static mut self, f: F) -> &T { + unsafe { + let r = &mut self.0; + self.1.call_once(|| { + *r = Box::into_raw(Box::new(f())); + }); + &*self.0 + } + } + } + + unsafe impl Sync for Lazy {} + + #[allow(missing_copy_implementations)] + #[allow(non_camel_case_types)] + #[allow(dead_code)] + struct CARGO_AUTHORS {__private_field: ()} + static CARGO_AUTHORS: CARGO_AUTHORS = CARGO_AUTHORS {__private_field: ()}; + + impl Deref for CARGO_AUTHORS { + type Target = String; + + #[allow(unsafe_code)] + fn deref<'a>(&'a self) -> &'a String { + unsafe { + static mut LAZY: Lazy = Lazy(0 as *const String, ONCE_INIT); + + LAZY.get(|| env!("CARGO_PKG_AUTHORS").replace(':', "\n")) + } + } + } + + &CARGO_AUTHORS[..] + }}; } /// Build `App`, `Arg`s, `SubCommand`s and `Group`s with Usage-string like input From 05f4953409abbca4905823d948ed0c89462e8368 Mon Sep 17 00:00:00 2001 From: nabijaczleweli Date: Sun, 18 Dec 2016 13:29:50 +0100 Subject: [PATCH 2/4] Inline lazy_static! even harder in crate_authors!() Functionality remains the same --- src/macros.rs | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index a6e817c50f1..b08aaf1af56 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -415,23 +415,6 @@ macro_rules! crate_authors { use std::ops::Deref; use std::sync::{ONCE_INIT, Once}; - struct Lazy(pub *const T, pub Once); - - impl Lazy { - #[inline(always)] - pub fn get T>(&'static mut self, f: F) -> &T { - unsafe { - let r = &mut self.0; - self.1.call_once(|| { - *r = Box::into_raw(Box::new(f())); - }); - &*self.0 - } - } - } - - unsafe impl Sync for Lazy {} - #[allow(missing_copy_implementations)] #[allow(non_camel_case_types)] #[allow(dead_code)] @@ -444,9 +427,10 @@ macro_rules! crate_authors { #[allow(unsafe_code)] fn deref<'a>(&'a self) -> &'a String { unsafe { - static mut LAZY: Lazy = Lazy(0 as *const String, ONCE_INIT); + static mut LAZY: (*const String, Once) = (0 as *const String, ONCE_INIT); - LAZY.get(|| env!("CARGO_PKG_AUTHORS").replace(':', "\n")) + LAZY.1.call_once(|| LAZY.0 = Box::into_raw(Box::new(env!("CARGO_PKG_AUTHORS").replace(':', "\n")))); + &*LAZY.0 } } } From 15d1619fa2900439780cbca482e6d95c69b72d5b Mon Sep 17 00:00:00 2001 From: nabijaczleweli Date: Sun, 18 Dec 2016 21:56:44 +0100 Subject: [PATCH 3/4] Default crate_authors!() macro to colon version. Add arm to handle custom separators This makes default crate_authors!() invocation same as before the changes --- src/macros.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index b08aaf1af56..13181cf9dfb 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -411,7 +411,7 @@ macro_rules! crate_version { /// ``` #[macro_export] macro_rules! crate_authors { - () => {{ + ($sep:expr) => {{ use std::ops::Deref; use std::sync::{ONCE_INIT, Once}; @@ -429,7 +429,7 @@ macro_rules! crate_authors { unsafe { static mut LAZY: (*const String, Once) = (0 as *const String, ONCE_INIT); - LAZY.1.call_once(|| LAZY.0 = Box::into_raw(Box::new(env!("CARGO_PKG_AUTHORS").replace(':', "\n")))); + LAZY.1.call_once(|| LAZY.0 = Box::into_raw(Box::new(env!("CARGO_PKG_AUTHORS").replace(':', $sep)))); &*LAZY.0 } } @@ -437,6 +437,9 @@ macro_rules! crate_authors { &CARGO_AUTHORS[..] }}; + () => { + env!("CARGO_PKG_AUTHORS") + }; } /// Build `App`, `Arg`s, `SubCommand`s and `Group`s with Usage-string like input From 315dffc011c65f41393820803d327bf1672b00ee Mon Sep 17 00:00:00 2001 From: nabijaczleweli Date: Sun, 18 Dec 2016 22:43:43 +0100 Subject: [PATCH 4/4] Add documentation for new crate_authors!() functionality --- src/macros.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 13181cf9dfb..5a23196a1bb 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -393,9 +393,13 @@ macro_rules! crate_version { } /// Allows you to pull the authors for the app from your Cargo.toml at -/// compile time as -/// "author1 lastname. ", -/// "author2 lastname. " +/// compile time in the form: +/// `"author1 lastname :author2 lastname "` +/// +/// You can replace the colons with a custom separator by supplying a +/// replacement string, so, for example, +/// `crate_authors!(",\n")` would become +/// `"author1 lastname ,\nauthor2 lastname ,\nauthor3 lastname "` /// /// # Examples /// @@ -404,9 +408,9 @@ macro_rules! crate_version { /// # extern crate clap; /// # use clap::App; /// # fn main() { -/// let m = App::new("app") -/// .author(crate_authors!()) -/// .get_matches(); +/// let m = App::new("app") +/// .author(crate_authors!("\n")) +/// .get_matches(); /// # } /// ``` #[macro_export]