Macros you wish you had while you were writing your non-proc macro.
This library privides some macros that make writing regural non-proc macros much simpler, readable and with less dirty tricks.
The main macro of this library is place
. It is able to expand the macros in
this library in reverse expansion order.
Every time I'm missing a proc macro while creating macro, I will add it here :).
place
: expands the following macros in reverse order, see belowignore
: expands to nothingidentity
: expands to what is given, it bypasses the reverse order in the
place
macrodollar
: expands to dollar sign $
string
: concats the contents into single string, see the docidentifier
: concats the contents into sintle identifier in the same way as
stringhead
: expands to the first tokentail
: expands to all but the first tokenstart
: expands to all but the last tokenlast
: expands to the last tokenreverse
: expands to the tokens in reverse orderstringify
: expands to string of the inputreplace_newline
: replaces all newlines and folowing whitespace in literal
with the given literalstr_replace
: replace in string literalplace
Expands the other macros inside in reverse order. The macros inside that will
be expanded are used with a different sintax: instead of calling a macro as
string!("hello" "there")
you call it as __string__("hello" "there")
. One
exception is the macro dollar
that is called without the parenthesis:
__dollar__
instead of dollar!()
.
For some of the macros there are also shorter names:
- __identity__
- __id__
- __string__
- __str__
- __dollar__
- __s__
- __identifier__
- __ident__
- __stringify__
- __strfy__
- __replace_newline__
- __repnl__
- __str_replace__
- __repstr__
The following passes: ```rust use place_macro::place;
let res = place!(string(1 string(2 identity(3 string(4))))); assert_eq!(res, "123string4"); ```
Why is this useful?
macrorules! mycoolmacro { ($name:ident -> $t:ty, $body:expr) => { place! { fn identifier(cool $name)() -> $t { $body } } }; }
mycoolmacro! { foo -> &'static str, "cool!" }
/// Expands to:
fn coolfoo() -> &'static str {
"cool!"
}
- You can generate strings as macro parameters in your macros:
rust
use placemacro::place;
macrorules! mycoolmacro {
($name:ident -> $t:ty, $body:expr) => {
place! {
#[doc =
string(
"cool function called " $name ". Returns "
__stringify__($t) "
."
)
]
fn identifier(cool $name)() -> $t {
$body
}
}
};
}
mycoolmacro! { foo -> &'static str, "cool!" } /// Expands to:
&'static str
."]fn coolfoo() -> &'static str {
"cool!"
}
- Or you can even generate macros in your macros
rust
use placemacro::place;
macrorules! mycoolermacro {
($t:ident) => {
place! {
macrorules! identifier(my_ $t _macro) {
(dollar name:ident -> dollar t:ty, dollar body:expr) => {
place! {
#[doc =
identity(string)(
$t " function called " dollar name ". Returns "
__identity__(__stringify__)(__dollar__ t) "
."
)
]
fn identity(identifier)($t dollar name)() -> dollar t {
dollar body
}
}
};
}
}
};
}
mycoolermacro! { cool }; mycoolmacro! { foo -> &'static str, "cool!" } /// now you have the same function as in the previous example ``` The last example was a little less readable, but you can see that you can do a lot with this macro.