gpui_markup/lib.rs
1//! gpui-markup - A declarative markup DSL for building GPUI applications.
2//!
3//! This crate provides a JSX-like syntax for building GPUI UIs:
4//!
5//! ```ignore
6//! ui! {
7//! <div flex flex_col w={px(200.0)} bg={theme.secondary}>
8//! <div text_size={px(16.0)}>
9//! {"Hello World"}
10//! </div>
11//! </div>
12//! }
13//! ```
14//!
15//! Which expands to:
16//!
17//! ```ignore
18//! div()
19//! .flex()
20//! .flex_col()
21//! .w(px(200.0))
22//! .bg(theme.secondary)
23//! .child(
24//! div()
25//! .text_size(px(16.0))
26//! .child("Hello World")
27//! )
28//! ```
29
30mod ast;
31mod codegen;
32mod parser;
33
34use proc_macro::TokenStream;
35use proc_macro_error2::proc_macro_error;
36use quote::quote;
37use syn::parse_macro_input;
38
39use crate::ast::Markup;
40
41/// A declarative markup macro for building GPUI UIs.
42///
43/// # Syntax
44///
45/// ## Basic Elements
46///
47/// ```ignore
48/// ui! { <div/> } // -> div()
49/// ui! { <div flex/> } // -> div().flex()
50/// ui! { <div w={px(200.0)}/> } // -> div().w(px(200.0))
51/// ```
52///
53/// ## Children
54///
55/// ```ignore
56/// // Single child uses .child()
57/// ui! {
58/// <div>
59/// {"Hello"}
60/// </div>
61/// }
62/// // -> div().child("Hello")
63///
64/// // Multiple children use .children([...])
65/// ui! {
66/// <div>
67/// {"First"}
68/// {"Second"}
69/// </div>
70/// }
71/// // -> div().children(["First", "Second"])
72/// ```
73///
74/// ## Components
75///
76/// ```ignore
77/// ui! { <Header/> } // -> Header::new()
78/// ui! { <{NavItem::new(path)}/> } // -> NavItem::new(path)
79/// ```
80///
81/// ## Expression Tags
82///
83/// ```ignore
84/// // Self-closing expression tag
85/// ui! { <{Container::new(title)}/> }
86///
87/// // Expression tag with attributes and children
88/// ui! {
89/// <{Container::new(title)} flex>
90/// {"Content"}
91/// </{}>
92/// }
93/// ```
94#[proc_macro]
95#[proc_macro_error]
96pub fn ui(input: TokenStream) -> TokenStream {
97 let markup = parse_macro_input!(input as Markup);
98 let output = quote! { #markup };
99 output.into()
100}