From 4da927249407a40a2658f492108cdaca1e052d55 Mon Sep 17 00:00:00 2001 From: Chris Wong <lambda.fairy@gmail.com> Date: Sat, 17 Jan 2015 20:43:51 +1300 Subject: [PATCH] Finally make splicing variables work --- maud/src/lib.rs | 10 ++++++++++ maud_macros/src/render.rs | 22 ++++++++++++++++------ maud_macros/tests/tests.rs | 13 ++++++++++--- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/maud/src/lib.rs b/maud/src/lib.rs index a823fa4..1bd5f66 100644 --- a/maud/src/lib.rs +++ b/maud/src/lib.rs @@ -61,6 +61,16 @@ pub mod rt { Markup { callback: f } } + /// rustc is a butt and doesn't let us quote macro invocations + /// directly. So we factor the `write!` call into a separate + /// function and use that instead. + /// + /// See <https://github.com/rust-lang/rust/issues/16617> + #[inline] + pub fn write_fmt<T: fmt::String>(w: &mut fmt::Writer, value: T) -> fmt::Result { + write!(w, "{}", value) + } + struct Escaper<'a, 'b: 'a> { inner: &'a mut (fmt::Writer + 'b), } diff --git a/maud_macros/src/render.rs b/maud_macros/src/render.rs index 2144d64..c0bfeb3 100644 --- a/maud_macros/src/render.rs +++ b/maud_macros/src/render.rs @@ -1,6 +1,7 @@ use std::borrow::IntoCow; use syntax::ast::{Expr, Ident, Stmt}; use syntax::ext::base::ExtCtxt; +use syntax::ext::build::AstBuilder; use syntax::parse::token; use syntax::ptr::P; @@ -40,10 +41,17 @@ impl<'cx, 's, 'o> Renderer<'cx, 's, 'o> { })) } + /// Push an expression statement, also wrapping it with `try!`. + fn push(&mut self, expr: P<Expr>) { + let expr = self.cx.stmt_expr(self.cx.expr_try(expr.span, expr)); + self.stmts.push(expr); + } + /// Append a literal pre-escaped string. fn write(&mut self, s: &str) { let w = self.w; - self.stmts.push(quote_stmt!(self.cx, try!($w.write_str($s)))); + let expr = quote_expr!(self.cx, $w.write_str($s)); + self.push(expr); } /// Append a literal string, with the specified escaping method. @@ -58,12 +66,14 @@ impl<'cx, 's, 'o> Renderer<'cx, 's, 'o> { /// Append the result of an expression, with the specified escaping method. pub fn splice(&mut self, expr: P<Expr>, escape: Escape) { let w = self.w; - self.stmts.push(match escape { - Escape::PassThru => quote_stmt!(self.cx, try!(write!($w, "{}", $expr))), + let expr = match escape { + Escape::PassThru => + quote_expr!(self.cx, ::maud::rt::write_fmt($w, $expr)), Escape::Escape => - quote_stmt!(self.cx, - try!(::maud::rt::escape($w, |w| write!(w, "{}", $expr)))), - }); + quote_expr!(self.cx, + ::maud::rt::escape($w, |w| ::maud::rt::write_fmt(w, $expr))), + }; + self.push(expr); } pub fn element_open_start(&mut self, name: &str) { diff --git a/maud_macros/tests/tests.rs b/maud_macros/tests/tests.rs index 2a729e6..2d94c2f 100644 --- a/maud_macros/tests/tests.rs +++ b/maud_macros/tests/tests.rs @@ -116,14 +116,21 @@ mod splices { assert_eq!(s, "Pinkie Pie"); } - // FIXME: See <https://github.com/rust-lang/rust/issues/15962> - // for why this is commented out - /* #[test] fn closures() { let best_pony = "Pinkie Pie"; let s = html! { $best_pony }.render(); assert_eq!(s, "Pinkie Pie"); } + + // FIXME: See <https://github.com/rust-lang/rust/issues/16617> + // for why this is commented out + /* + #[test] + fn nested_macro_invocation() { + let best_pony = "Pinkie Pie"; + let s = html! { $(format!("{}", best_pony)) }.render(); + assert_eq!(s, "Pinkie Pie"); + } */ }