mevy_ui/lib.rs
1use deki::*;
2use mevy_ui_syntax::*;
3use proc_macro::TokenStream as CompilerTokens;
4
5// Macro \\
6
7 /// Provides CSS-like syntax to either edit or create bevy_ui components.
8 ///
9 /// ## Available fields
10 /// To see a full list of built-in fields, see readme of mevy_ui, here are some examples:
11 /// ```rust
12 /// cmd.spawn(ui!((
13 /// size: 50px 50px;
14 /// background: #ff0000;
15 /// box_shadow: 0px 0px 5px 5px #ff0000;
16 /// border: 5px #00ff00;
17 /// )));
18 /// ```
19 /// The same, but 'slim':
20 /// ```rust
21 /// cmd.spawn(ui!( w:50 h:50 bg:#f00 shadow:0+0+5+5#f00 border:5#0f0 ));
22 /// ```
23 ///
24 /// ## Possible Modes
25 /// Depending on the delimiters & if there is a name defined, the function of this macro differs:
26 /// - 'Slim' Inline Tuple Mode | `ui!{ w:8 h:8 l:2 t:2 }`
27 /// - returns a tuple of mentioned UI components
28 /// - Inline Tuple Mode | `ui!{( width: 1px; )}`:
29 /// - returns a tuple of mentioned UI components
30 /// - Function Tuple Mode | `ui!{func_name( width: 1px; )}`:
31 /// - defines a function that returns a tuple of mentioned UI components
32 /// - these can then be used as fields like this: `ui!{( func_name; )}`
33 /// - Function Edit Mode | `ui!{func_name{ width: 2px; }}`
34 /// - defines a function, that edits mentioned UI components
35 /// - the parameters of this function = the needed mutable components
36 /// - using `_` will keep the original values: e.g. `border: _ #ff0000;`
37 ///
38 /// ## Custom Fields
39 /// Every function that returns any `Bundle` (even if it is just -> `impl Bundle`) can be used
40 /// as custom field.
41 #[proc_macro]
42 pub fn ui (tok:CompilerTokens) -> CompilerTokens {
43 let tok: TokenStream = tok.into();
44 let mut iter = tok.peek_iter();
45
46 match iter.peek().unwrap() {
47 TokenTree::Ident(ident) if ident.to_string().chars().next().unwrap().is_lowercase() => {
48 let ident = iter.next().unwrap().unwrap_ident();
49 match iter.peek().unwrap() {
50 TokenTree::Group(g) if g.delimiter().is_parenthesis() => {
51 let g = iter.next().unwrap().unwrap_group();
52 let bundle = bundle(g.stream().peek_iter(),iter.next());
53 qt!{pub fn #ident () -> impl Bundle {#bundle}}
54 }
55 TokenTree::Group(g) if g.delimiter().is_brace() => {
56 let g = iter.next().unwrap().unwrap_group();
57 let prep = UiPrep::from_stream(g.stream(),false,|a,_|a.is_punct(';'));
58 let (expected,edits) = prep.get_edits();
59 let attr = expected.into_iter()
60 .map(|(v,t)|qt!(#v: &mut #t))
61 .collect::<Vec<_>>();
62 qt!{pub fn #ident (#(#attr),*) {#edits}}
63 }
64 _ => {
65 let aa = qt![#ident #(#iter)*];
66 bundle_slim(aa.peek_iter(),None)
67 }
68 }
69 }
70
71 TokenTree::Group(_) => {
72 kill!{*Some(TokenTree::Group(group)) = iter.next()}
73 match group.delimiter() {
74 Delimiter::Parenthesis => bundle(group.stream().peek_iter(),iter.next()),
75 Delimiter::Bracket => bundle_slim(group.stream().peek_iter(),iter.next()),
76 _ => todo!{}
77 }
78 }
79
80 _ => bundle_slim(iter,None),
81
82 }.into()
83 }
84
85
86// EOF \\