find-crate 0.1.0

Find the crate name from the current Cargo.toml ($crate for proc-macro).
Documentation

find-crate

Build Status version documentation license

Find the crate name from the current Cargo.toml ($crate for proc-macro).

When writing declarative macros, $crate representing the current crate is very useful, but procedural macros do not have this. To do the same thing as $crate with procedural macros, you need to know the current name of the crate you want to use as $crate. This crate provides the features to make it easy.

Documentation

Usage

Add this to your Cargo.toml:

[dependencies]
find-crate = "0.1"

Now, you can use find-crate:

use find_crate::find_crate;

The current version of find-crate requires Rust 1.30 or later.

Examples

find_crate() gets the crate name from the current Cargo.toml.

use find_crate::find_crate;
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;

fn import() -> TokenStream {
    let name = find_crate(|s| s == "foo").unwrap();
    let name = Ident::new(&name, Span::call_site());
    quote!(extern crate #name as _foo;)
}

As in this example, it is easy to handle cases where proc-macro is exported from multiple crates.

use find_crate::find_crate;
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;

fn import() -> TokenStream {
    let name = find_crate(|s| s == "foo" || s == "foo-core").unwrap();
    let name = Ident::new(&name, Span::call_site());
    quote!(extern crate #name as _foo;)
}

Search for multiple crates. It is much more efficient than using find_crate() for each crate.

use find_crate::Manifest;
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;

const CRATE_NAMES: &[&[&str]] = &[
    &["foo", "foo-core"],
    &["bar", "bar-util", "bar-core"],
    &["baz"],
];

fn imports() -> TokenStream {
    let mut tts = TokenStream::new();
    let manifest = Manifest::new().unwrap();
    let manifest = manifest.lock();

    for names in CRATE_NAMES {
        let name = manifest.find_name(|s| names.iter().any(|x| s == *x)).unwrap();
        let name = Ident::new(&name, Span::call_site());
        let import_name = Ident::new(&format!("_{}", names[0]), Span::call_site());
        tts.extend(quote!(extern crate #name as #import_name;));
    }
    tts
}

By default it will be searched from dependencies, dev-dependencies and build-dependencies. Also, find_crate() and Manifest::new() read Cargo.toml in CARGO_MANIFEST_DIR as manifest.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.