aacebo/moxy

A modular Rust syntax toolkit for tokenization, parsing, formatting, diagnostics, and quasi-quoting.

Rust

27

273 commits

updated Sep 26, 2026

See the code

See what people are saying

SourceMessageScoreDate

Moxy - a Rust syntax toolkit designed to bring more cohesion to Rust parsing, tokenization, formatting, diagnostics, and quasi-quoting. (r/rust)

Last year I published [zyn](https://github.com/aacebo/zyn), a template engine for Rust proc macros. I got a lot of great constructive feedback from the community, which inspired me to take the ideas behind it a step further. `moxy` has been written from the ground up with a few goals in mind: # 1.…

34

Sep 26, 2026

README

moxy Bencher

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.

Quick Start

cargo add moxy --features template,fmt
use 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;");

Features

Default features are token and ast.

FeatureDefaultEnables
tokenyesToken streams, spans, parsing, and token construction
astyesTyped Rust syntax trees; implies token
templatenotemplate! and paste!; implies token
fmtnoAST formatting with fmt!; implies ast
diagnosticnoSpan-aware error, warning, note, and help diagnostics
buildnoCargo build-script and rustc-version helpers
deriveno#[derive(ToTokens)] and its supporting pipeline
serdenoSerialization for supported token, AST, and formatting types
proc-macro2noConversions between moxy and proc_macro2 tokens
fullnoEvery feature above

Choose only the layers you need:

cargo add moxy --no-default-features --features token,ast

Feature guide

Tokens

The 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(), ",");

Abstract Syntax Tree

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());

Templates

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);

Formatting

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}");

Diagnostics

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"));

Build

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(())
}

Derive

Enable derive to implement ToTokens from an inline template.

cargo add moxy --features derive
use 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.

Integrations

serde adds serialization for supported token, AST, and formatter types. proc-macro2 adds token conversions for interoperability with the wider procedural-macro ecosystem.

diagnostics
formatting
parsing
quasi-quote
rust
rustlang
syntax
tokenization

Contributors

aacebo

272 commits

faysou

1 commits

aacebo/moxy

A modular Rust syntax toolkit for tokenization, parsing, formatting, diagnostics, and quasi-quoting.

Rust

27

273 commits

updated Sep 26, 2026

See the code

See what people are saying

SourceMessageScoreDate

Moxy - a Rust syntax toolkit designed to bring more cohesion to Rust parsing, tokenization, formatting, diagnostics, and quasi-quoting. (r/rust)

Last year I published [zyn](https://github.com/aacebo/zyn), a template engine for Rust proc macros. I got a lot of great constructive feedback from the community, which inspired me to take the ideas behind it a step further. `moxy` has been written from the ground up with a few goals in mind: # 1.…

34

Sep 26, 2026

README

moxy Bencher

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.

Quick Start

cargo add moxy --features template,fmt
use 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;");

Features

Default features are token and ast.

FeatureDefaultEnables
tokenyesToken streams, spans, parsing, and token construction
astyesTyped Rust syntax trees; implies token
templatenotemplate! and paste!; implies token
fmtnoAST formatting with fmt!; implies ast
diagnosticnoSpan-aware error, warning, note, and help diagnostics
buildnoCargo build-script and rustc-version helpers
deriveno#[derive(ToTokens)] and its supporting pipeline
serdenoSerialization for supported token, AST, and formatting types
proc-macro2noConversions between moxy and proc_macro2 tokens
fullnoEvery feature above

Choose only the layers you need:

cargo add moxy --no-default-features --features token,ast

Feature guide

Tokens

The 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(), ",");

Abstract Syntax Tree

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());

Templates

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);

Formatting

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}");

Diagnostics

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"));

Build

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(())
}

Derive

Enable derive to implement ToTokens from an inline template.

cargo add moxy --features derive
use 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.

Integrations

serde adds serialization for supported token, AST, and formatter types. proc-macro2 adds token conversions for interoperability with the wider procedural-macro ecosystem.

diagnostics
formatting
parsing
quasi-quote
rust
rustlang
syntax
tokenization

Contributors

aacebo

272 commits

faysou

1 commits

Languages

Rust

99.9%