summary refs log tree commit diff stats
path: root/rocie-macros/src/form/parse.rs
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-10-23 01:36:39 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-10-23 01:36:39 +0200
commit7bff22756beec82b4a1470e2d325b706dc56e5f2 (patch)
tree1566965125cfd5fbd73d654e9ee6ca8256301411 /rocie-macros/src/form/parse.rs
parentfeat(form): Re-write the form macro as a proc macro (diff)
downloadweb-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.rs93
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 })
     }
 }