Skip to main content

tui_lipan_macro/
lib.rs

1use proc_macro::TokenStream;
2use proc_macro_crate::{FoundCrate, crate_name};
3use proc_macro2::{Span, TokenStream as TokenStream2};
4use quote::quote;
5use syn::{Ident, parse_macro_input};
6
7mod rsx_ast;
8mod rsx_expand;
9mod ui_ast;
10mod ui_expand;
11
12use crate::rsx_ast::RsxInput;
13use crate::ui_ast::UiInput;
14
15#[proc_macro]
16pub fn rsx(input: TokenStream) -> TokenStream {
17    let input = parse_macro_input!(input as RsxInput);
18    let lipan = lipan_crate_path();
19    input.expand(&lipan).into()
20}
21
22/// Autocomplete-friendly alternative to [`rsx!`].
23///
24/// Uses standard Rust builder chains with `=> { children }` sugar:
25///
26/// ```ignore
27/// ui! {
28///     Frame::new().title("Panel").border(true) => {
29///         Text::new("Hello"),
30///         Button::new("Click").on_click(handler),
31///     }
32/// }
33/// ```
34///
35/// Everything before `=>` is a normal Rust expression (full autocomplete).
36/// `=> { child1, child2, ... }` desugars to `.child(child1).child(child2)...`.
37#[proc_macro]
38pub fn ui(input: TokenStream) -> TokenStream {
39    let input = parse_macro_input!(input as UiInput);
40    let lipan = lipan_crate_path();
41    input.expand(&lipan).into()
42}
43
44fn lipan_crate_path() -> TokenStream2 {
45    match crate_name("tui-lipan") {
46        Ok(FoundCrate::Itself) => quote!(crate),
47        Ok(FoundCrate::Name(name)) => {
48            let ident = Ident::new(&name, Span::call_site());
49            quote!(::#ident)
50        }
51        Err(_) => quote!(::tui_lipan),
52    }
53}