#macros #crate

find-crate

Find the crate name from the current Cargo.toml

11 unstable releases

0.6.3 Jan 5, 2021
0.6.2 Dec 29, 2020
0.6.1 Sep 7, 2020
0.5.0 Sep 28, 2019
0.3.0 Feb 21, 2019

#72 in Procedural macros

Download history 3604/week @ 2021-10-05 6609/week @ 2021-10-12 5478/week @ 2021-10-19 3795/week @ 2021-10-26 3867/week @ 2021-11-02 4868/week @ 2021-11-09 5024/week @ 2021-11-16 7054/week @ 2021-11-23 5885/week @ 2021-11-30 6176/week @ 2021-12-07 6175/week @ 2021-12-14 4598/week @ 2021-12-21 5144/week @ 2021-12-28 5612/week @ 2022-01-04 5217/week @ 2022-01-11 5173/week @ 2022-01-18

21,912 downloads per month
Used in 134 crates (4 directly)

Apache-2.0 OR MIT

23KB
236 lines

find-crate

crates.io docs.rs license rustc build status

Find the crate name from the current Cargo.toml.

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

Usage

Add this to your Cargo.toml:

[dependencies]
find-crate = "0.5"

Compiler support: requires rustc 1.31+

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().name;
    let name = Ident::new(&name, Span::call_site());
    // If your proc-macro crate is 2018 edition, use `quote!(use #name as _foo;)` instead.
    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().name;
    let name = Ident::new(&name, Span::call_site());
    // If your proc-macro crate is 2018 edition, use `quote!(use #name as _foo;)` instead.
    quote!(extern crate #name as _foo;)
}

Using Manifest to 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::{format_ident, 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();

    for names in CRATE_NAMES {
        let name = manifest.find(|s| names.iter().any(|x| s == *x)).unwrap().name;
        let name = Ident::new(&name, Span::call_site());
        let import_name = format_ident!("_{}", names[0]);
        // If your proc-macro crate is 2018 edition, use `quote!(use #name as #import_name;)` instead.
        tts.extend(quote!(extern crate #name as #import_name;));
    }
    tts
}

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

Alternatives

If you write function-like procedural macros, you can combine it with declarative macros to support both crate renaming and macro re-exporting.

This crate is intended to provide more powerful features such as support for multiple crate names and versions. For general purposes, proc-macro-crate, which provides a simpler API, may be easier to use.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

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.

Dependencies

~335–480KB
~11K SLoC