macro_rules! export {
    {
        #[export(
            $(#[$($attr:tt)*])*
            $name:ident $dollar:tt
        )]
        {
            $($t:tt)*
        }
    } => { ... };
    {
        #[export(
            $(#[$($attr:tt)*])*
            pub($($module:tt)*) $name:ident $dollar:tt
        )]
        {
            $($t:tt)*
        }
    } => { ... };
    {
        #[export(
            $(#[$($attr:tt)*])*
            pub $name:ident $dollar:tt
        )]
        {
            $($t:tt)*
        }
    } => { ... };
    {
        #[export(
            $(#[$($attr:tt)*])*
            pub crate $name:ident $dollar:tt
        )]
        {
            $($t:tt)*
        }
    } => { ... };
    {$($t:tt)*} => { ... };
}
Expand description

Export tokens for later inspection by other macros.

This macro enables exporting arbitrary token sequences to other modules or even crates. Call the macro with the following form.

export!(
    #[export(
        /// Any extra docs you want.
        <visibility> <macro name>$
    )]
    {
        <some arbitrary tokens>
    }
);

This will generate a macro_rules! with the name given at <macro name>. Any docs given in the export attribute will be added to the top of the macro docs. The macro is already given a set of basic docs and an example (see example::demo_struct for what this basic docs looks like).

<visibility> can be any of the normal visibility specifiers (nothing, pub, pub(crate), pub(super), …). It can also be pub crate which has a special meaning. pub crate is used when in the root of a crate (main.rs or lib.rs) and we want the macro to be public outside the crate. This is needed because the normal visibility specifiers don’t work there.

The public visibility specifiers also automatically put the macro’s docs in the module export was invoked in instead of having the macro docs at the root of the crate.

The $ after the macro name is always required. This is do to a limitation of macro_ruiles! where $ can’t be escaped.

The form above was chossen because it allows code formatting to work as you would expect. Any code in <some arbitrary tokens> is seen by rustfmt as a normal expression and can be formatted accordingly. rustfmt will not format the export attribute though.

Note: The docs generated for the macro include a doc test example. The doc test should always pass (if it doesn’t please post an issue). However, sometimes this may not be wanted. To disable the doc test generation (it will be generated as a text code block instead) add the mmm_no_gen_examples cfg item (its not a feature) when compiling.

macro_rules_attribute Support

There is also another form export can be called with designed for use with the macro_rules_attribute crate.

export!(
    /// Any docs or attributes for the item (not the macro).
    #[custom(export(
        /// Any extra docs you want.
        <visibility> <macro name>$
    ))]
    <some arbitrary tokens>
);

When used with the macro_rules_attribute::derive macro this allows the following.

/// Some docs for `Demo`.
#[derive(export!)]
#[custom(export(
    pub demo_struct$
))]
struct Demo {
    pub name: String,
}

Examples

See the integration tests for examples that show why you would want to use export.

export!(
    #[export(
        demo_struct$
    )]
    {
        struct Demo {
            pub name: String,
        }
    }
);
export!(
    #[export(
        pub a_plus_b$
    )]
    {
        a + b
    }
);
export!(
    #[export(
        /// Some docs.
        pub(crate) allow_unused$
    )]
    {
        #[allow(unused)]
    }
);

Invalid Input

If export is called with incorrect syntax a compile error will be generated with the expected calling syntax and the syntax it was given.

export!(
    #[export(demo_struct)]
    {
        struct Demo {
            pub name: String,
        }
    }
);
error: `export!()` expects input of the form:
       
       #[export(<vis> <name>$)] { <tokens> }
       
       instead got:
       
       #[export(demo_struct)] { struct Demo { pub name : String, } }
       
  --> src/lib.rs:132:1
   |
6  | / export!(
7  | |     #[export(demo_struct)]
8  | |     {
9  | |         struct Demo {
...  |
12 | |     }
13 | | );
   | |_^