Rust syntax tools for procedural macros: tokens, typed syntax trees, templates, formatting, and diagnostics.
Warning
Moxy is under active development.
APIs, behavior, and documentation may change frequently and without notice. Moxy is not yet considered stable or production-ready.
cargo add moxy --features template,fmtuse moxy::ast::Item;
let name = "Widget";
let tokens = moxy::template! {
pub struct {{ name }};
};
let item: Item = moxy::parse!(tokens).unwrap();
assert_eq!(item.as_struct().unwrap().ident.text(), "Widget");
assert_eq!(moxy::fmt!(&item).unwrap(), "pub struct Widget;");Default features are token and ast.
| Feature | Default | Enables |
|---|---|---|
token |
yes | Token streams, spans, parsing, and token construction |
ast |
yes | Typed Rust syntax trees; implies token |
template |
no | template! and paste!; implies token |
fmt |
no | AST formatting with fmt!; implies ast |
diagnostic |
no | Span-aware error, warning, note, and help diagnostics |
build |
no | Cargo build-script and rustc-version helpers |
derive |
no | #[derive(ToTokens)] and its supporting pipeline |
serde |
no | Serialization for supported token, AST, and formatting types |
proc-macro2 |
no | Conversions between moxy and proc_macro2 tokens |
full |
no | Every feature above |
Choose only the layers you need:
cargo add moxy --no-default-features --features token,astThe token feature is the foundation, similar in role to proc-macro2.
use moxy::Token;
use moxy::token::ident;
let name = ident!(Generated, "_", Item);
let comma: Token![,] = Default::default();
assert_eq!(name.to_string(), "Generated_Item");
assert_eq!(comma.as_str(), ",");The ast feature provides typed entry points such as Item, Expr, and
Type, following the same parse-at-the-level-you-need style as syn.
use moxy::ast::{Expr, Item, Type};
let item: Item = moxy::parse!("pub struct User { id: u64 }").unwrap();
let ty: Type = moxy::parse!("Option<Result<T, E>>").unwrap();
let expr: Expr = moxy::parse!("items.next()?").unwrap();
assert!(item.is_struct());
assert!(ty.is_path());
assert!(expr.is_unary());The template feature builds token streams with interpolation and control
flow in the style of quote!.
let fields = ["id", "name"];
let tokens = moxy::template! {
struct User {
@for (field in fields) {
{{ field }}: String,
}
}
};
assert!(tokens.to_string().contains("struct User"));paste! creates identifiers at expansion time:
moxy::paste! {
fn {{ read_ value }}() -> u32 { 7 }
}
assert_eq!(read_value(), 7);The fmt feature formats parsed syntax trees with configurable width,
indentation, and newlines.
use moxy::ast::Item;
use moxy::fmt::{FmtConfig, Indent};
let item: Item = moxy::parse!("struct User { id: u64, name: String }").unwrap();
let config = FmtConfig::default().with_indent(Indent::space(2));
let output = moxy::fmt!(&item, config).unwrap();
assert_eq!(output, "struct User {\n id: u64,\n name: String,\n}");The diagnostic feature builds span-aware diagnostics with a stable
compile_error! fallback.
let tokens = moxy::error!(
"missing template",
[moxy::help!("add #[template { ... }]")],
)
.emit();
assert!(tokens.to_string().contains("compile_error"));Enable parser trace output to stdout by passing trace = true to parse!.
use moxy::ast::Item;
let _: Item = moxy::parse!("struct Widget;", trace = true).unwrap();Enable build as a build dependency for typed Cargo directives and rustc
version checks.
cargo add moxy --build --no-default-features --features build// build.rs
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = moxy::build::rustc::Config::read()?;
config
.min_version("1.85.0")
.check_cfg("cfg(nightly)")
.rerun_if_changed("build.rs");
if config.version().channel.is_nightly() {
config.cfg("nightly");
}
config.emit();
Ok(())
}Enable derive to implement ToTokens from an inline template.
cargo add moxy --features deriveuse moxy::token::ToTokenStream;
#[derive(moxy::ToTokens)]
#[moxy(template { const VALUE: &str = {{ self.value }}; })]
struct Generated {
value: String,
}
let tokens = Generated { value: "seven".into() }.to_token_stream();
assert!(tokens.to_string().contains("VALUE"));Add #[moxy(debug)] beside #[moxy(template { ... })] to print the parsed
declaration and generated implementation as compiler notes.
serde adds serialization for supported token, AST, and formatter types.
proc-macro2 adds token conversions for interoperability with the wider
procedural-macro ecosystem.