macro_rules_attr

Crates.iomacro_rules_attr
lib.rsmacro_rules_attr
version0.1.3
created_at2025-03-26 13:13:48.788642+00
updated_at2025-03-30 02:23:04.472045+00
descriptionUse declarative macros as proc_macro attributes. (`#[apply]` your `macro_rules!`)
homepage
repositoryhttps://github.com/PRO-2684/Candy-Pile
max_upload_size
id1606531
size8,968
PRO (PRO-2684)

documentation

README

macro_rules_attr

GitHub License Crates.io Version Crates.io Total Downloads docs.rs free of syn

Use declarative macros as proc_macro attributes. (#[apply] your macro_rules!)

Usage

First, bring the apply attribute macro into scope:

use macro_rules_attr::apply;

Then, define your macro using macro_rules!:

# use macro_rules_attr::apply;
#
/// Your macro that you want to use as an attribute.
macro_rules! the_macro {
    // Your macro implementation here.
#     ($($tt:tt)*) => {}; // Matches and discards everything.
}

Finally, annotate your item with the apply attribute macro:

# use macro_rules_attr::apply;
#
# /// Your macro that you want to use as an attribute.
# macro_rules! the_macro {
#     // Your macro implementation here.
#     ($($tt:tt)*) => {}; // Matches and discards everything.
# }
#
#[apply(the_macro)]
struct One {}
// Expands to:
the_macro! { struct One {} }

Additional tokens are appended after the annotated item:

# use macro_rules_attr::apply;
#
# /// Your macro that you want to use as an attribute.
# macro_rules! the_macro {
#     // Your macro implementation here.
#     ($($tt:tt)*) => {}; // Matches and discards everything.
# }
#
#[apply(the_macro, "additional tokens", anything, (you - like))]
struct Another {}
// Expands to:
the_macro! { struct Another {}, "additional tokens", anything, (you - like) }

Example

use macro_rules_attr::apply;

/// Simple macro that generates a `hello` function for given struct, which returns `Hello, {name}!`. If given a second argument, it will replace `{name}`.
macro_rules! make_hello {
( // Matches a struct definition (some details omitted for brevity)
#     $(#[$struct_meta:meta])*
#     $struct_vis:vis
    struct $StructName:ident {
        // ...
#         $(
#             $(#[$field_meta:meta])*
#             $field_vis:vis
#             $field_name:ident : $field_ty:ty
#         ),* $(,)?
    }$(, $replacement:expr)?
) => {
    // Repeat the struct definition
#     $(#[$struct_meta])*
#     $struct_vis
    struct $StructName {
        // ...
#         $(
#             $(#[$field_meta])*
#             $field_vis:vis $field_name: $field_ty,
#         )*
    }

    // Implement the `hello` function
    impl $StructName {
        fn hello() -> String {
            let name = stringify!($StructName);
            $(let name = $replacement;)? // Shadow `name` if a replacement was provided
            format!("Hello, {name}!")
        }
    }
};
}

#[apply(make_hello)] // No additional tokens
struct WithoutReplacement {}
assert_eq!(WithoutReplacement::hello(), "Hello, WithoutReplacement!");

#[apply(make_hello, "World")] // Additional tokens
struct WithReplacement {}
assert_eq!(WithReplacement::hello(), "Hello, World!");

Cargo Features

  • log: Enable logging with the log crate. (Requires log as a dependency)

Comparison

This crate is heavily inspired by macro_rules_attribute, but differs in the following ways:

  • macro_rules_attr is more lightweight and has no dependencies by default.
    • Less than 100 lines of code. (Excluding tests and documentation)
    • You can enable logging with the log feature, which requires log as a dependency.
    • paste is required as a dev-dependency for the tests.
  • macro_rules_attr only has one attribute: #[apply], while macro_rules_attribute provides more.
  • macro_rules_attr allows you to append any tokens after the annotated item, while macro_rules_attribute does not.
Commit count: 14

cargo fmt