compose-idents
A macro for generating new identifiers (names of variables, functions, traits, etc.) by concatenating one or more arbitrary parts and applying other manipulations.
It was created as an alternative to macro_rules! that doesn't allow creating new identifiers from the macro arguments
and concat_idents! macro from the nightly Rust, which is limited in capabilities and has not been stabilized
since 2015.
Features
-
Identifier generation
Identifiers can be generated via concatenation of multiple parts. Arguments of the outer macro definitions and literals are supported for identifier definitions.
-
Functions
Functions can be applied when defining new identifiers for changing case and style.
-
String formatting
Strings can be formatted with
%alias%syntax, which is useful for generating doc-attributes. -
Unique identifier generation
Unique identifiers can be deterministically generated by using
hash()function which is uniquely seeded each invocation of the macro. This might be useful for generating unique global variables.
Usage
This section contains various usage examples. For even more usage examples look into tests/ directory
of the repository.
Quick start
compose_idents! works by accepting definitions of aliases and a code block where aliases
could be used as normal identifiers. When the macro is expanded, the aliases are replaced with their
definitions:
use compose_idents;
// We generate separate const-functions for each type as a workaround
// since Rust doesn't allow us to use `core::ops::Add` in `const fn`.
gen_const_add!; // Expands into `add_u32()` function.
gen_const_add!; // Expands into `add_u64()` function.
assert_eq!;
assert_eq!;
Generating tests for different types
A practical example for how to auto-generate names for macro-generated tests for different data types:
use compose_idents;
// Generates tests for u32 and &'static str types
generate_frobnicate_test!;
generate_frobnicate_test!;
test_frobnicate_u32;
// Notice - "&'static str" has been turned into just "static_str"
test_frobnicate_static_str;
Reference example
This example includes all the features of the macro:
use compose_idents;
compose_idents!;
// It's possible to use arguments of declarative macros as parts of the identifiers.
outer_macro!;
global_var_macro!;
global_var_macro!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Functions
| Function | Description |
|---|---|
upper(arg) |
Converts the arg to upper case. |
lower(arg) |
Converts the arg to lower case. |
snake_case(arg) |
Converts the arg to snake_case. |
camel_case(arg) |
Converts the arg to camelCase. |
pascal_case(arg) |
Converts the arg to PascalCase. |
normalize(tokens) |
Transforms a random sequence of tokens tokens into a valid identifier. |
hash(arg) |
Hashes the arg deterministically within a single macro invocation. |
Alternatives
There some other tools and projects dedicated to identifier manipulation:
- A macro from Nightly Rust that allows to concatenate identifiers. It is limited in functionality and nowhere near to be stabilized: https://doc.rust-lang.org/std/macro.concat_idents.html
- A very similar macro that doesn't support multiple aliases and is not maintained: https://github.com/DzenanJupic/concat-idents
- A macro that allows to define and refer to unique temporary variables: https://crates.io/crates/templest
Development
The following standards are followed to maintain the project: