diff options
| author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-10-23 01:36:39 +0200 |
|---|---|---|
| committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-10-23 01:36:39 +0200 |
| commit | 7bff22756beec82b4a1470e2d325b706dc56e5f2 (patch) | |
| tree | 1566965125cfd5fbd73d654e9ee6ca8256301411 /rocie-macros/src/form/parse.rs | |
| parent | feat(form): Re-write the form macro as a proc macro (diff) | |
| download | web-client-7bff22756beec82b4a1470e2d325b706dc56e5f2.zip | |
feat(buy): Provide basic buy interface
Diffstat (limited to 'rocie-macros/src/form/parse.rs')
| -rw-r--r-- | rocie-macros/src/form/parse.rs | 93 |
1 files changed, 64 insertions, 29 deletions
diff --git a/rocie-macros/src/form/parse.rs b/rocie-macros/src/form/parse.rs index ef2087b..b0ca58c 100644 --- a/rocie-macros/src/form/parse.rs +++ b/rocie-macros/src/form/parse.rs @@ -1,7 +1,10 @@ use quote::format_ident; -use syn::{bracketed, parenthesized, parse::{Parse, ParseStream}, Expr, Ident, LitStr, Token, Type}; +use syn::{ + Expr, Ident, LitStr, Token, Type, + parse::{Parse, ParseStream}, +}; -use crate::form::{ParsedChild, ParsedInput, ParsedOnSubmit, SelectOptions}; +use crate::form::{ParsedChild, ParsedInput, ParsedOnSubmit}; macro_rules! parse_key_value { ($input:expr, $name:ident as $ty:ty) => {{ @@ -19,27 +22,13 @@ macro_rules! parse_key_value { value }}; -} - -impl Parse for SelectOptions { - fn parse(input: ParseStream) -> syn::Result<Self> { - let content; - bracketed!(content in input); - let inner = content.parse_terminated( - |arg| { - let paren; - parenthesized!(paren in arg); - let lit = paren.parse::<LitStr>()?; - paren.parse::<Token![,]>()?; - let expr = paren.parse::<Expr>()?; - - Ok((lit, expr)) - }, - Token![,], - )?; - - Ok(Self(inner.into_iter().collect())) - } + (@option $input:expr, $name:ident as $ty:ty) => {{ + if $input.peek(Ident) { + Some(parse_key_value!($input, $name as $ty)) + } else { + None + } + }}; } impl Parse for ParsedInput { @@ -78,19 +67,33 @@ impl Parse for ParsedChild { let rust_type = parse_key_value!(input, rust_type as Type); let html_type = parse_key_value!(input, html_type as LitStr); let label = parse_key_value!(input, label as LitStr); + let reactive = parse_key_value!(@option input, reactive as Ident); + let auto_complete = parse_key_value!(@option input, auto_complete as Ident); + + if auto_complete.is_some() && reactive.is_none() { + panic!("Cannot provide an autocomplet, without registering an reactive signal") + } + + input.parse::<Token![/]>()?; + input.parse::<Token![>]>()?; ParsedChild::Input { name, rust_type, html_type, label, + reactive, + auto_complete, } } variant if variant == format_ident!("Select") => { let name = parse_key_value!(input, name as Ident); let rust_type = parse_key_value!(input, rust_type as Type); let label = parse_key_value!(input, label as LitStr); - let options = parse_key_value!(input, options as SelectOptions); + let options = parse_key_value!(input, options as Expr); + + input.parse::<Token![/]>()?; + input.parse::<Token![>]>()?; ParsedChild::Select { name, @@ -99,11 +102,36 @@ impl Parse for ParsedChild { rust_type, } } - _ => panic!("Unkown form child variant: {variant}"), - }; + variant if variant == format_ident!("Show") => { + let when = parse_key_value!(input, when as Expr); - input.parse::<Token![/]>()?; - input.parse::<Token![>]>()?; + input.parse::<Token![>]>()?; + + let children = { + let mut children = vec![]; + + while !(input.peek(Token![<]) && input.peek2(Token![/])) { + children.push(input.parse::<ParsedChild>()?); + } + + { + input.parse::<Token![<]>()?; + input.parse::<Token![/]>()?; + let show_ident = input.parse::<Ident>()?; + + if show_ident != format_ident!("Show") { + panic!("Expected key name to be 'Show', but found: '{show_ident}'",); + } + input.parse::<Token![>]>()?; + + children + } + }; + + ParsedChild::Show { when, children } + } + _ => panic!("Unknown form child variant: {variant}"), + }; Ok(output) } @@ -113,6 +141,13 @@ impl Parse for ParsedOnSubmit { fn parse(input: ParseStream) -> syn::Result<Self> { let mut inputs = Vec::new(); + let should_use_move = if input.peek(Token![move]) { + input.parse::<Token![move]>()?; + true + } else { + false + }; + input.parse::<Token![|]>()?; while !input.peek(Token![|]) { inputs.push(input.parse::<Ident>()?); @@ -127,6 +162,6 @@ impl Parse for ParsedOnSubmit { input.parse::<Token![;]>()?; - Ok(Self { inputs, block }) + Ok(Self { inputs, block, should_use_move }) } } |
