Repository: clap-rs/clap (rust)

Issue:
Macros aren't imported properly in Rust 2018
<!--
Please use the following template to assist with creating an issue and to ensure a speedy resolution. If an area is not applicable, feel free to delete the area or mark with `N/A`
-->

### Rust Version

`rustc 1.35.0 (3c235d560 2019-05-20)`

### Affected Version of clap

`2.33.0`

### Bug or Feature Request Summary

Macros such as `app_from_crate!()` which rely on other custom macros do not do so properly (using `$crate`) in many cases, meaning that all dependent macros must also be individually imported with `use`.

### Expected Behavior Summary

For example:

```rust
macro_rules! app_from_crate {
    () => {
        $crate::App::new(crate_name!())
            .version($crate::crate_version!())
            .author($crate::crate_authors!())
            .about($crate::crate_description!())
    };
    ($sep:expr) => {
        $crate::App::new($crate::crate_name!())
            .version($crate::crate_version!())
            .author($crate::crate_authors!($sep))
            .about($crate::crate_description!())
    };
}
```

### Actual Behavior Summary

Current implementation:

https://github.com/clap-rs/clap/blob/784524f7eb193e35f81082cc69454c8c21b948f7/src/macros.rs#L559-L572

### Steps to Reproduce the issue

`src/main.rs`:

```rust
use clap::app_from_crate;

fn main() {
    let matches = app_from_crate!().get_matches();
}
```

Output:

```
error: cannot find macro `crate_name!` in this scope
 --> src/main.rs:4:19
  |
4 |     let matches = app_from_crate!().get_matches();
  |                   ^^^^^^^^^^^^^^^^^
  |
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: cannot find macro `crate_version!` in this scope
 --> src/main.rs:4:19
  |
4 |     let matches = app_from_crate!().get_matches();
  |                   ^^^^^^^^^^^^^^^^^
  |
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: cannot find macro `crate_authors!` in this scope
 --> src/main.rs:4:19
  |
4 |     let matches = app_from_crate!().get_matches();
  |                   ^^^^^^^^^^^^^^^^^
  |
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: cannot find macro `crate_description!` in this scope
 --> src/main.rs:4:19
  |
4 |     let matches = app_from_crate!().get_matches();
  |                   ^^^^^^^^^^^^^^^^^
  |
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to 4 previous errors
```

### Sample Code or Link to Sample Code

N/A

### Debug output

N/A

Pull request:
Added tests for cargo macros, fixes #1478
When you approve this PR, instead of merging it, please comment "bors r+". I want to test the bors workflow.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9eb19112..fbbdb6a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,10 +2,10 @@
 
 #### Minimum Required Rust
 
-* As of this release, `clap` requires `rustc 1.33.0` or greater.
+* As of this release, `clap` requires `rustc 1.36.0` or greater.
 
 <a name="v2.29.2"></a>
-### v2.29.2 (2018-01-16)
+## v2.29.2 (2018-01-16)
 
 
 #### Features


Test patch:
diff --git a/tests/app_from_crate.rs b/tests/app_from_crate.rs
new file mode 100644
index 00000000..2129a0dd
--- /dev/null
+++ b/tests/app_from_crate.rs
@@ -0,0 +1,26 @@
+use clap::{app_from_crate, ErrorKind};
+
+static EVERYTHING: &str = "clap {{version}}
+Kevin K. <kbknapp@gmail.com>
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+USAGE:
+    clap
+
+FLAGS:
+    -h, --help       Prints help information
+    -V, --version    Prints version information
+";
+
+#[test]
+fn app_from_crate() {
+    let res = app_from_crate!().try_get_matches_from(vec!["clap", "--help"]);
+
+    assert!(res.is_err());
+    let err = res.unwrap_err();
+    assert_eq!(err.kind, ErrorKind::HelpDisplayed);
+    assert_eq!(
+        err.message,
+        EVERYTHING.replace("{{version}}", env!("CARGO_PKG_VERSION"))
+    );
+}
diff --git a/tests/cargo.rs b/tests/cargo.rs
new file mode 100644
index 00000000..9fe2234e
--- /dev/null
+++ b/tests/cargo.rs
@@ -0,0 +1,71 @@
+use clap::{crate_authors, crate_description, crate_name, crate_version, App, ErrorKind};
+
+static DESCRIPTION_ONLY: &str = "prog 1
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+USAGE:
+    prog
+
+FLAGS:
+    -h, --help       Prints help information
+    -V, --version    Prints version information
+";
+
+static AUTHORS_ONLY: &str = "prog 1
+Kevin K. <kbknapp@gmail.com>
+
+USAGE:
+    prog
+
+FLAGS:
+    -h, --help       Prints help information
+    -V, --version    Prints version information
+";
+
+#[test]
+fn crate_version() {
+    let res = App::new("prog")
+        .version(crate_version!())
+        .try_get_matches_from(vec!["prog", "--version"]);
+
+    assert!(res.is_err());
+    let err = res.unwrap_err();
+    assert_eq!(err.kind, ErrorKind::VersionDisplayed);
+    assert_eq!(err.message, format!("prog {}", env!("CARGO_PKG_VERSION")));
+}
+
+#[test]
+fn crate_description() {
+    let res = App::new("prog")
+        .version("1")
+        .about(crate_description!())
+        .try_get_matches_from(vec!["prog", "--help"]);
+
+    assert!(res.is_err());
+    let err = res.unwrap_err();
+    assert_eq!(err.kind, ErrorKind::HelpDisplayed);
+    assert_eq!(err.message, DESCRIPTION_ONLY);
+}
+
+#[test]
+fn crate_authors() {
+    let res = App::new("prog")
+        .version("1")
+        .author(crate_authors!())
+        .try_get_matches_from(vec!["prog", "--help"]);
+
+    assert!(res.is_err());
+    let err = res.unwrap_err();
+    assert_eq!(err.kind, ErrorKind::HelpDisplayed);
+    assert_eq!(err.message, AUTHORS_ONLY);
+}
+
+#[test]
+fn crate_name() {
+    let res = App::new(crate_name!()).try_get_matches_from(vec!["clap", "--version"]);
+
+    assert!(res.is_err());
+    let err = res.unwrap_err();
+    assert_eq!(err.kind, ErrorKind::VersionDisplayed);
+    assert_eq!(err.message, "clap ");
+}