diff --git a/mox/src/lib.rs b/mox/src/lib.rs
index 528ac525..60538a1e 100644
--- a/mox/src/lib.rs
+++ b/mox/src/lib.rs
@@ -58,6 +58,13 @@ use syn_rsx::{punctuation::Dash, NodeName, NodeType};
/// If the attribute's name is `async`, `for`, `loop`, or `type` an underscore
/// is appended to avoid colliding with the Rust keyword.
///
+/// #### Alternate syntax
+///
+/// To allow calling methods with 0 or more than 1 arguments,
+/// an inline method call syntax is available
+///
+/// e.g. `` expands to `foo().bar().baz(123).build()`
+///
/// ### Children
///
/// Tags have zero or more nested items (tags, fragments, content) as children.
@@ -90,6 +97,7 @@ use syn_rsx::{punctuation::Dash, NodeName, NodeType};
/// #[derive(Debug, PartialEq)]
/// struct Tag {
/// name: String,
+/// is_optional: bool,
/// children: Vec,
/// }
///
@@ -100,6 +108,7 @@ use syn_rsx::{punctuation::Dash, NodeName, NodeType};
/// #[derive(Default)]
/// struct TagBuilder {
/// name: Option,
+/// is_optional: bool,
/// children: Vec,
/// }
///
@@ -114,21 +123,31 @@ use syn_rsx::{punctuation::Dash, NodeName, NodeType};
/// self
/// }
///
+/// fn optional(mut self) -> Self {
+/// self.is_optional = true;
+/// self
+/// }
+///
/// fn build(self) -> Tag {
-/// Tag { name: self.name.unwrap(), children: self.children }
+/// Tag {
+/// name: self.name.unwrap(),
+/// children: self.children,
+/// is_optional: self.is_optional,
+/// }
/// }
/// }
///
/// assert_eq!(
/// mox! {
-///
+///
///
///
///
/// },
/// Tag {
/// name: String::from("alice"),
-/// children: vec![Tag { name: String::from("bob"), children: vec![] }],
+/// is_optional: true,
+/// children: vec![Tag { name: String::from("bob"), is_optional: false, children: vec![] }],
/// },
/// );
/// ```
@@ -140,6 +159,32 @@ pub fn mox(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
quote!(#item .build()).into()
}
+enum MoxBlock {
+ /// {% ...format_args }
+ FormatExpr(Punctuated),
+ /// Arbitrary Rust expression
+ Block,
+}
+
+impl<'a> TryFrom> for MoxBlock {
+ type Error = syn::Error;
+
+ fn try_from(parse_stream: ParseStream) -> syn::Result {
+ if parse_stream.peek(syn::Token![%]) {
+ parse_stream.parse::()?;
+ let arguments: Punctuated =
+ Punctuated::parse_separated_nonempty(parse_stream)?;
+ if parse_stream.is_empty() {
+ Ok(MoxBlock::FormatExpr(arguments))
+ } else {
+ Err(parse_stream.error(format!("Expected the end, found `{}`", parse_stream)))
+ }
+ } else {
+ Ok(MoxBlock::Block)
+ }
+ }
+}
+
enum MoxItem {
Tag(MoxTag),
Expr(MoxExpr),
@@ -148,24 +193,16 @@ enum MoxItem {
impl Parse for MoxItem {
fn parse(input: ParseStream) -> syn::Result {
- fn parse_fmt_expr(parse_stream: ParseStream) -> syn::Result