1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
use proc_macro::TokenStream; use crate::gxi_parser::*; use crate::init_type::*; use crate::tree_parser::*; mod gxi_parser; mod init_type; mod tree_parser; /// proc-macro for writing gxi components /// /// ## Syntax /// /// ```rust /// gxi! { /// NameOfComponent { // Constructor block /// count : u32 = 0 // property : type = default value ; (optional) /// } /// update { // gxi_update_macro function (Optional) /// // The business logic goes here /// } /// render { // render function (Optional) /// { /* Component tree goes here */ } /// Component /// } /// }; /// ``` /// ## Render Block /// The component tree is written in this block. It produces the render function as follows. /// /// ```rust ///# use std::rc::Rc; /// fn render(this: NodeRc) { /// let cont = Rc::clone(&this); /// let node = cont.clone(); /// let state = { /// let mut node_borrow = this.as_ref().borrow_mut(); /// let node = node_borrow.as_any_mut().downcast_mut::<Self>().unwrap(); /// if !node.is_dirty() { /// return; /// } /// node.mark_clean(); /// node.state.clone() /// }; /// let state = state.lock().unwrap(); /// // the content of the render block is moved here /// } /// ``` /// /// It is recommended not to write the render function manually. Use the render block instead. /// Synctax for the render block can be found [here](../gxi_c_macro/macro.gxi_c_macro.html#Syntax) /// ## Update Block /// *The gxi_update_macro block produces* /// /// ```rust /// #[update(NameOfComponent)] /// async fn update<F: Fn() + 'static>(state: State, msg: Msg, render: F) -> AsyncResult<ShouldRender> { /// // the content of the gxi_update_macro block is moved here /// } /// ``` /// /// In this block values `state: State, msg: Msg, render: F` are present which can be used as follows -> /// /// * `state` - is of `type State = Arc<Mutex<ComponentState>>;` where `ComponentState` has all the fields defined in the /// constructor block. It must be used to manipulate the state of the component. For efficient renders, the dev should drop the lock /// on the mutex before awaiting an async call. /// /// * `msg` - This is the enum defined by the user outside the macro. /// `Example` /// ```rust /// enum Msg { /// Task /// } /// ``` /// /// * `render`- is a closure that can be called to pre-render the component. This can be used in situations where /// the final value of an async function is not yet received but the user has to be notified about the progress. /// A popular example is progress bars. /// #[proc_macro] pub fn gxi(item: TokenStream) -> TokenStream { let GxiParser { tree } = syn::parse_macro_input!(item as GxiParser); tree.into() }