Add some juicy impl Trait niceness

This commit is contained in:
Chris Wong 2016-08-15 20:32:39 +12:00
parent d2bf70da9a
commit aded75f01f
3 changed files with 39 additions and 1 deletions
maud/src
maud_macros

View file

@ -151,3 +151,9 @@ impl<W: io::Write> fmt::Write for Utf8Writer<W> {
}
}
}
/// A template is a closure that, when invoked, outputs markup to a
/// `std::fmt::Write`.
pub trait Template: FnOnce(&mut fmt::Write) -> fmt::Result {}
impl<T> Template for T where T: FnOnce(&mut fmt::Write) -> fmt::Result {}

View file

@ -44,6 +44,17 @@ fn html_utf8(cx: &mut ExtCtxt, sp: Span, mac_name: &str, args: &[TokenTree]) ->
}))
}
fn template(cx: &mut ExtCtxt, sp: Span, _mac_name: &str, args: &[TokenTree]) -> PResult<P<Expr>> {
let write_ident = token::gensym_ident("__maud_writer");
let write = vec![TokenTree::Token(DUMMY_SP, token::Ident(write_ident))];
let star_write = vec![
TokenTree::Token(DUMMY_SP, token::BinOp(token::BinOpToken::Star)),
TokenTree::Token(DUMMY_SP, token::Ident(write_ident)),
];
let expr = parse::parse(cx, sp, &star_write, args)?;
Ok(quote_expr!(cx, move |$write: &mut ::std::fmt::Write| $expr))
}
macro_rules! generate_debug_wrappers {
($fn_name:ident $fn_debug_name:ident $mac_name:ident) => {
fn $fn_name<'cx>(cx: &'cx mut ExtCtxt, sp: Span, args: &[TokenTree])
@ -72,6 +83,7 @@ macro_rules! generate_debug_wrappers {
generate_debug_wrappers!(expand_html expand_html_debug html);
generate_debug_wrappers!(expand_html_utf8 expand_html_utf8_debug html_utf8);
generate_debug_wrappers!(expand_template expand_template_debug template);
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
@ -79,4 +91,6 @@ pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("html_debug", expand_html_debug);
reg.register_macro("html_utf8", expand_html_utf8);
reg.register_macro("html_utf8_debug", expand_html_utf8_debug);
reg.register_macro("template", expand_template);
reg.register_macro("template_debug", expand_template_debug);
}

View file

@ -1,4 +1,4 @@
#![feature(plugin)]
#![feature(conservative_impl_trait, plugin)]
#![plugin(maud_macros)]
extern crate maud;
@ -140,3 +140,21 @@ fn render_once_impl() {
html!(s, ^once).unwrap();
assert_eq!(s, "pinkie");
}
fn cute<'a>(name: &'a str) -> impl maud::Template + 'a {
template! {
p {
^name " is the cutest"
}
}
}
#[test]
fn call() {
let mut s = String::new();
html!(s, {
@call cute("Pinkie Pie")
@call cute("Rarity")
}).unwrap();
assert_eq!(s, "<p>Pinkie Pie is the cutest</p><p>Rarity is the cutest</p>");
}