appy_macros/
lib.rs

1//! # Appy - Declarative UI Framework for Native Application
2//!
3//! This crate contains macros for [Appy](https://github.com/limikael/appy).
4//!
5//! It is published as a separate crate  due to technical reasons. See
6//! this [stack overflow thread](https://stackoverflow.com/questions/56713877/why-do-proc-macros-have-to-be-defined-in-proc-macro-crate).
7//!
8//! If it is not the case any more that it needs to be separate, please let me know!
9use proc_macro::{*};
10
11mod function_component;
12/// Implement component renderer.
13///
14/// A component takes input in the form of props and children,
15/// and return elements describing what should appear on the screen.
16///
17/// # Example
18/// ```rust
19/// #[derive_component(Default,ComponentBuilder)]
20/// pub struct MyComp {
21///     param1: i32,
22///     param2: i32
23/// }
24///
25/// #[function_component]
26/// fn _my_comp_render(props:MyComp)->Elements {
27///     apx! {
28///         <bg col=0x000000/>
29///     }
30/// }
31/// ```
32///
33/// As should be evident by the _ prefix for the function, the actual function
34/// name is not important. Rather, the render function is tied to a specific
35/// type of element by type inference based on the parameter it takes.
36///
37/// The component declared above can be used together with the
38/// apx macro:
39/// ```rust
40/// apx!{
41///     <MyComp param1=123 param2=456/>
42///	}
43/// ```
44#[proc_macro_attribute]
45pub fn function_component(attr: TokenStream, input: TokenStream) -> TokenStream {
46	function_component::function_component(attr,input)
47}
48
49mod main_window;
50#[proc_macro_attribute]
51/// Application entry point.
52///
53/// The main window macro defines the main application entry point.
54/// It should be placed on a function that returns Elements. In this
55/// sense, it is similar to the render function of an Element, but it
56/// does not take any properties or children.
57///
58/// # Example
59/// ```rust
60/// use appy::*;
61///
62/// #[main_window]
63/// pub fn app()->Elements {
64///    apx!{
65///        <bg col=0x800000/>
66///        <text text="Hello World".to_string() align=Align::Center/>
67///    }
68/// }
69/// ```
70pub fn main_window(attr: TokenStream, input: TokenStream) -> TokenStream {
71	main_window::main_window(attr,input)
72}
73
74mod derive_component;
75/// Create component properties.
76///
77/// Used together with the `function_component` macro.
78#[proc_macro_attribute]
79pub fn derive_component(attr: TokenStream, input: TokenStream) -> TokenStream {
80	derive_component::derive_component(attr,input)
81}
82
83mod component_builder;
84/// Create builder.
85///
86/// Create a builder implementation. For example, when placed on the following struct:
87/// ```rust
88/// struct MyStruct {
89///     an_int:i32,
90///     an_optional_string:Option<String>
91/// }
92/// ```
93/// This macro will create the following implementation:
94/// ```rust
95/// impl MyStruct {
96///     pub fn new()->ElementWrap<Self> {
97///         // ...
98///     }
99///
100///     pub fn an_int(ElementWrap<Self>,v:i32)->ElementWrap<Self> {
101///         // ...
102///     }
103///
104///     pub fn an_optional_string(ElementWrap<Self>,v:String)->ElementWrap<Self> {
105///         // ...
106///     }
107///	}
108/// ```
109/// Notes:
110/// - For optional properties, e.g. fields wrapped in `Option<...>`, the setter in
111///   the builder will take the wrapped type as parameter and call `Some()` with the
112///   value.
113#[proc_macro_derive(ComponentBuilder)]
114pub fn component_builder(input: TokenStream) -> TokenStream {
115	component_builder::component_builder(input)
116}
117
118mod snake_factory;
119/// Produce snake cased factory function.
120///
121/// When placed on a `struct`, e.g. `MyStruct`, this derive macro
122/// will create a function `my_struct` defined as:
123/// ```rust
124/// fn my_struct() -> MyStruct {
125///     MyStruct::new()
126/// }
127/// ```
128#[proc_macro_derive(SnakeFactory)]
129pub fn snake_factory(input: TokenStream) -> TokenStream {
130	snake_factory::snake_factory(input)
131}
132
133mod apx;
134/// Process element fragment.
135///
136/// This macro takes XML, and produces an element fragment represented as
137/// `Elements`. For example, the following APX snippet:
138/// ```rust
139/// apx!{
140///     <my_component param1=123 param2=456/>
141///	}
142/// ```
143/// Is syntactical sugar for the following:
144/// ```rust
145/// vec![
146///     my_component().param1(123).param3(456)
147/// ]
148/// ```
149/// And it would be used together with a component defined like this:
150/// ```rust
151/// #[derive_component(ComponentBuilder,Default,SnakeFactory)]
152/// pub struct MyComponent {
153///     param1: i32,
154///     param2: i32
155/// }
156///
157/// impl Element for MyComponent {
158///     fn render(self:ElementWrap<Self>)->Elements {
159///         // ...
160///     }
161/// }
162#[proc_macro]
163pub fn apx(input: TokenStream) -> TokenStream {
164	apx::apx(input)
165}