ratatui_kit_macros/
lib.rs

1//! ratatui-kit-macros:核心 UI 宏定义,简化终端 UI 组件开发。
2//!
3//! ## 主要宏说明
4//!
5//! - `#[derive(Props)]`:为组件属性自动生成 Props trait 实现。
6//! - `element!`:声明式 UI 宏,极大提升终端 UI 组件开发效率。
7//!   - 语法风格类似 React JSX,但为 Rust 语法友好设计。
8//!   - 支持嵌套、props、children、条件渲染、列表渲染。
9//!   - 条件渲染、列表渲染、动态子组件等均需写在 `#(...expr)` 语法块中,表达式可返回 Option/Vec/impl Iterator。
10//!   - 通过 `$` 前缀可兼容任何实现 WidgetRef 的 ratatui 原生组件或自定义组件,便于无缝集成 ratatui 能力。
11//!   - 适用于声明式构建终端 UI 组件树。
12//!
13//! ## element! 宏语法
14//!
15//! 例如,声明式构建一个带条件渲染和 ratatui 原生组件的 UI:
16//!
17//! ```rust
18//! element!(Panel(title: "Demo") {
19//!     #(if show_title { element!(Title("Hello")) }),
20//!     #(for item in items { element!(ListItem(item)) }),
21//!     $Block::default().borders(Borders::ALL),
22//! })
23//! ```
24//!
25//! - 所有条件渲染、列表渲染、动态子组件都需包裹在 `#(...)` 表达式中,且条件渲染/循环渲染的子组件也需用 element! 宏包裹。
26//! - 通过 `$` 前缀可直接集成 ratatui 原生组件。
27//! - 语法风格类似 JSX,但为 Rust 语法友好设计。
28//! - 适用于声明式构建终端 UI 组件树。
29
30use element::ElementOrAdapter;
31use proc_macro::TokenStream;
32use props::ParsedProps;
33use quote::ToTokens;
34use syn::DeriveInput;
35
36use crate::with_layout_style::impl_layout_style;
37
38mod adapter;
39mod component;
40mod element;
41mod props;
42#[cfg(feature = "router")]
43mod router;
44#[cfg(feature = "store")]
45mod store;
46mod utils;
47mod with_layout_style;
48
49#[proc_macro_derive(Props, attributes(layout))]
50pub fn derive_props(item: TokenStream) -> TokenStream {
51    let props = syn::parse_macro_input!(item as ParsedProps);
52    props.to_token_stream().into()
53}
54
55/// 声明式 UI 宏,类似 JSX,支持嵌套、props、children、条件渲染、列表渲染等,极大提升终端 UI 组件开发效率。
56///
57/// - 语法风格类似 React JSX,但为 Rust 语法友好设计。
58/// - 支持 `if/else` 条件渲染、`#(for ...)` 列表渲染、props 传递、children 嵌套。
59/// - 通过 `$` 前缀可兼容任何实现 WidgetRef 的 ratatui 原生组件或自定义组件,便于无缝集成 ratatui 能力。
60/// - 适用于声明式构建终端 UI 组件树。
61///
62/// ## element! 宏语法
63///
64/// 例如,声明式构建一个带条件渲染和 ratatui 原生组件的 UI:
65///
66/// ```rust
67/// element!(Panel(title: "Demo") {
68///     #(if show_title { element!(Title("Hello")) }),
69///     #(for item in items { element!(ListItem(item)) }),
70///     $Block::default().borders(Borders::ALL),
71/// })
72/// ```
73#[proc_macro]
74pub fn element(input: TokenStream) -> TokenStream {
75    let element = syn::parse_macro_input!(input as ElementOrAdapter);
76    element.to_token_stream().into()
77}
78
79/// 简化组件函数定义,自动实现 Component trait。
80#[proc_macro_attribute]
81pub fn component(_attr: TokenStream, item: TokenStream) -> TokenStream {
82    let component = syn::parse_macro_input!(item as component::ParsedComponent);
83    component.to_token_stream().into()
84}
85
86#[cfg(feature = "router")]
87#[proc_macro]
88pub fn routes(input: TokenStream) -> TokenStream {
89    let routes = syn::parse_macro_input!(input as router::Routes);
90    routes.to_token_stream().into()
91}
92
93#[cfg(feature = "store")]
94#[proc_macro]
95pub fn use_stores(input: TokenStream) -> TokenStream {
96    let stores = syn::parse_macro_input!(input as store::UseStores);
97    stores.to_token_stream().into()
98}
99
100#[cfg(feature = "store")]
101#[proc_macro_derive(Store)]
102pub fn derive_store(item: TokenStream) -> TokenStream {
103    let store = syn::parse_macro_input!(item as store::Store);
104    store.to_token_stream().into()
105}
106
107/// 为属性结构体自动生成布局相关方法。
108#[proc_macro_attribute]
109pub fn with_layout_style(attr: TokenStream, item: TokenStream) -> TokenStream {
110    let layout_style = syn::parse_macro_input!(attr as with_layout_style::ParsedLayoutStyle);
111    let props = syn::parse_macro_input!(item as DeriveInput);
112    impl_layout_style(&layout_style, props).into()
113}