ez-tui-derive 0.0.3-alpha

A framework to create terminal user interfaces in Rust with Ratatui
Documentation
use proc_macro::{self, TokenStream};
use quote::quote;
use syn::{DeriveInput, parse_macro_input};

use crate::utils::{assert_field, crate_ref};

/// Derives the [`ez_tui::MockComponent`] trait for structs by proxying calls to a field named `component`.
pub(crate) fn mock_component(input: TokenStream) -> TokenStream {
    let DeriveInput {
        ident,
        generics,
        data,
        ..
    } = parse_macro_input!(input);

    let crate_name = crate_ref();
    if let syn::Data::Struct(s) = data {
        assert_field(&ident, s, "component");
        let (impl_generics, type_generics, where_clause) = generics.split_for_impl();

        let output = quote! {
            const _: () = {
                use #crate_name::*;
                use ratatui::layout::Rect;
                use ratatui::buffer::Buffer;
                use ratatui::widgets::{Block, List, ListState, StatefulWidgetRef};

                impl #impl_generics MockComponent for #ident #type_generics #where_clause {
                    fn draw(&mut self, area: Rect, buf: &mut Buffer, theme: &Theme) {
                        self.component.draw(area, buf, theme)
                    }
                }
                impl #impl_generics MockProps for #ident #type_generics #where_clause {
                    fn props(&self) -> Option<&Props> {
                        self.component.props()
                    }

                    fn props_mut(&mut self) -> Option<&mut Props> {
                        self.component.props_mut()
                    }
                }
            };
        };

        output.into()
    } else {
        panic!("MockComponent must be derived by a `Struct`");
    }
}