zyn/lib.rs
1//! A template engine and framework for Rust procedural macros.
2//!
3//! zyn replaces the typical `syn` + `quote` + `heck` + `proc-macro-error` stack with
4//! a single dependency. It provides a `zyn!` template macro with interpolation, control
5//! flow, and pipes — plus reusable elements, typed attribute parsing, and proc macro
6//! entry points.
7//!
8//! # Quick start
9//!
10//! ```sh
11//! cargo add zyn
12//! ```
13//!
14//! A derive macro that generates getters:
15//!
16//! ```ignore
17//! #[zyn::derive]
18//! fn my_getters(
19//! #[zyn(input)] ident: zyn::Extract<zyn::syn::Ident>,
20//! #[zyn(input)] fields: zyn::Fields<zyn::syn::FieldsNamed>,
21//! ) -> zyn::TokenStream {
22//! zyn::zyn! {
23//! impl {{ ident }} {
24//! @for (field in fields.named.iter()) {
25//! pub fn {{ field.ident | snake | ident:"get_{}" }}(&self) -> &{{ field.ty }} {
26//! &self.{{ field.ident }}
27//! }
28//! }
29//! }
30//! }
31//! }
32//! ```
33//!
34//! Applied to `struct User { first_name: String, age: u32 }` generates:
35//!
36//! ```ignore
37//! impl User {
38//! pub fn get_first_name(&self) -> &String { &self.first_name }
39//! pub fn get_age(&self) -> &u32 { &self.age }
40//! }
41//! ```
42//!
43//! # Template syntax
44//!
45//! | Syntax | Purpose |
46//! |--------|---------|
47//! | `{{ expr }}` | Interpolate any [`quote::ToTokens`] value |
48//! | `{{ expr \| pipe }}` | Transform value through a pipe before inserting |
49//! | `@if (cond) { ... }` | Conditional token emission |
50//! | `@for (x in iter) { ... }` | Loop over an iterator |
51//! | `@for (N) { ... }` | Repeat N times |
52//! | `@match (expr) { pat => { ... }}` | Pattern-based code generation |
53//! | `@element_name(prop = val)` | Invoke a `#[zyn::element]` component |
54//!
55//! See [`zyn!`] for the full syntax reference with examples.
56//!
57//! # Pipes
58//!
59//! 13 built-in pipes: `snake`, `pascal`, `camel`, `screaming`, `kebab`, `upper`,
60//! `lower`, `str`, `trim`, `plural`, `singular`, `ident`, `fmt`. They chain:
61//!
62//! ```ignore
63//! zyn::zyn! { fn {{ name | snake | ident:"get_{}" }}() {} }
64//! // name = "HelloWorld" → fn get_hello_world() {}
65//! ```
66//!
67//! Custom pipes via [`pipe`].
68//!
69//! # Elements
70//!
71//! ```ignore
72//! #[zyn::element]
73//! fn getter(name: syn::Ident, ty: syn::Type) -> zyn::TokenStream {
74//! zyn::zyn! {
75//! pub fn {{ name | snake | ident:"get_{}" }}(&self) -> &{{ ty }} {
76//! &self.{{ name }}
77//! }
78//! }
79//! }
80//!
81//! // invoked as:
82//! zyn::zyn! { @getter(name = field.ident.clone().unwrap(), ty = field.ty.clone()) }
83//! ```
84//!
85//! # Typed attribute parsing
86//!
87//! ```ignore
88//! #[derive(zyn::Attribute)]
89//! #[zyn("builder")]
90//! struct BuilderConfig {
91//! #[zyn(default)]
92//! skip: bool,
93//! #[zyn(default = "build".to_string())]
94//! method: String,
95//! }
96//! // users write: #[builder(skip)] or #[builder(method = "create")]
97//! ```
98
99pub use zyn_core::*;
100
101#[cfg(feature = "derive")]
102pub use zyn_derive::*;
103
104/// The zyn prelude. Re-exports all built-in pipes, core traits, and proc macros.
105pub mod prelude {
106 pub use crate::pipes::*;
107 pub use crate::{Pipe, Render};
108
109 #[cfg(feature = "derive")]
110 pub use zyn_derive::*;
111
112 #[cfg(feature = "ext")]
113 pub use zyn_core::ext::*;
114}