Add a write_html!
macro
This handles the common case of wrapping the stream in a `Utf8Writer`.
This commit is contained in:
parent
44ca2aa82b
commit
ebbd5d2e54
3 changed files with 55 additions and 27 deletions
|
@ -7,35 +7,65 @@ extern crate syntax;
|
||||||
extern crate rustc;
|
extern crate rustc;
|
||||||
extern crate maud;
|
extern crate maud;
|
||||||
|
|
||||||
use syntax::ast::TokenTree;
|
use syntax::ast::{Expr, TokenTree, TtToken};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::{DUMMY_SP, Span};
|
||||||
use syntax::ext::base::{ExtCtxt, MacEager, MacResult};
|
use syntax::ext::base::{ExtCtxt, MacEager, MacResult};
|
||||||
|
use syntax::parse::token;
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
|
use syntax::ptr::P;
|
||||||
use rustc::plugin::Registry;
|
use rustc::plugin::Registry;
|
||||||
|
|
||||||
mod parse;
|
mod parse;
|
||||||
mod render;
|
mod render;
|
||||||
|
|
||||||
fn expand_html_common<'cx>(cx: &'cx mut ExtCtxt, sp: Span, args: &[TokenTree],
|
fn _expand_html(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> P<Expr> {
|
||||||
debug: bool) -> Box<MacResult + 'cx> {
|
let (write, input) = parse::split_comma(cx, sp, args);
|
||||||
let expr = parse::parse(cx, args, sp);
|
parse::parse(cx, sp, write, input)
|
||||||
if debug {
|
}
|
||||||
cx.span_note(sp, &format!("expansion:\n{}",
|
|
||||||
pprust::expr_to_string(&expr)));
|
fn _expand_write_html(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> P<Expr> {
|
||||||
|
let (io_write, input) = parse::split_comma(cx, sp, args);
|
||||||
|
let io_write = io_write.to_vec();
|
||||||
|
let fmt_write = token::gensym_ident("__maud_utf8_writer");
|
||||||
|
let fmt_write = vec![
|
||||||
|
TtToken(DUMMY_SP, token::Ident(fmt_write, token::IdentStyle::Plain))];
|
||||||
|
let expr = parse::parse(cx, sp, &fmt_write, input);
|
||||||
|
quote_expr!(cx,
|
||||||
|
match ::maud::Utf8Writer::new(&mut $io_write) {
|
||||||
|
mut $fmt_write => {
|
||||||
|
let _ = $expr;
|
||||||
|
$fmt_write.into_result()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! expand {
|
||||||
|
($name:ident $debug_name:ident $inner_fn:ident) => {
|
||||||
|
fn $name<'cx>(cx: &'cx mut ExtCtxt, sp: Span, args: &[TokenTree])
|
||||||
|
-> Box<MacResult + 'cx>
|
||||||
|
{
|
||||||
|
let expr = $inner_fn(cx, sp, args);
|
||||||
|
MacEager::expr(expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn $debug_name<'cx>(cx: &'cx mut ExtCtxt, sp: Span, args: &[TokenTree])
|
||||||
|
-> Box<MacResult + 'cx>
|
||||||
|
{
|
||||||
|
let expr = $inner_fn(cx, sp, args);
|
||||||
|
cx.span_note(sp, &format!("expansion:\n{}",
|
||||||
|
pprust::expr_to_string(&expr)));
|
||||||
|
MacEager::expr(expr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MacEager::expr(expr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_html<'cx>(cx: &'cx mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box<MacResult + 'cx> {
|
expand!(expand_html expand_html_debug _expand_html);
|
||||||
expand_html_common(cx, sp, args, false)
|
expand!(expand_write_html expand_write_html_debug _expand_write_html);
|
||||||
}
|
|
||||||
|
|
||||||
fn expand_html_debug<'cx>(cx: &'cx mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box<MacResult + 'cx> {
|
|
||||||
expand_html_common(cx, sp, args, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[plugin_registrar]
|
#[plugin_registrar]
|
||||||
pub fn plugin_registrar(reg: &mut Registry) {
|
pub fn plugin_registrar(reg: &mut Registry) {
|
||||||
reg.register_macro("html", expand_html);
|
reg.register_macro("html", expand_html);
|
||||||
reg.register_macro("html_debug", expand_html_debug);
|
reg.register_macro("html_debug", expand_html_debug);
|
||||||
|
reg.register_macro("write_html", expand_write_html);
|
||||||
|
reg.register_macro("write_html_debug", expand_write_html_debug);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,9 @@ macro_rules! ident {
|
||||||
($sp:pat, $x:pat) => (TtToken($sp, token::Ident($x, token::IdentStyle::Plain)))
|
($sp:pat, $x:pat) => (TtToken($sp, token::Ident($x, token::IdentStyle::Plain)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(cx: &ExtCtxt, input: &[TokenTree], sp: Span) -> P<Expr> {
|
pub fn parse(cx: &ExtCtxt, sp: Span, write: &[TokenTree], input: &[TokenTree])
|
||||||
let (write, input) = split_comma(cx, input, sp);
|
-> P<Expr>
|
||||||
|
{
|
||||||
let mut parser = Parser {
|
let mut parser = Parser {
|
||||||
in_attr: false,
|
in_attr: false,
|
||||||
input: input,
|
input: input,
|
||||||
|
@ -54,15 +55,15 @@ pub fn parse(cx: &ExtCtxt, input: &[TokenTree], sp: Span) -> P<Expr> {
|
||||||
parser.into_render().into_expr(write.to_vec())
|
parser.into_render().into_expr(write.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split_comma<'a>(cx: &ExtCtxt, input: &'a [TokenTree], sp: Span) -> (&'a [TokenTree], &'a [TokenTree]) {
|
pub fn split_comma<'a>(cx: &ExtCtxt, sp: Span, args: &'a [TokenTree]) -> (&'a [TokenTree], &'a [TokenTree]) {
|
||||||
fn is_comma(t: &TokenTree) -> bool {
|
fn is_comma(t: &TokenTree) -> bool {
|
||||||
match *t {
|
match *t {
|
||||||
TtToken(_, token::Comma) => true,
|
TtToken(_, token::Comma) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match input.iter().position(is_comma) {
|
match args.iter().position(is_comma) {
|
||||||
Some(i) => (&input[..i], &input[1+i..]),
|
Some(i) => (&args[..i], &args[1+i..]),
|
||||||
None => cx.span_fatal(sp, "expected two arguments to `html!`"),
|
None => cx.span_fatal(sp, "expected two arguments to `html!`"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,11 +250,8 @@ mod control {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn utf8_writer() {
|
fn write_html() {
|
||||||
use maud::Utf8Writer;
|
let mut buf = vec![];
|
||||||
let mut w = Utf8Writer::new(vec![]);
|
write_html!(buf, p "hello").unwrap();
|
||||||
let _ = html!(w, p "hello");
|
|
||||||
let (buf, r) = w.into_inner();
|
|
||||||
r.unwrap();
|
|
||||||
assert_eq!(buf, b"<p>hello</p>");
|
assert_eq!(buf, b"<p>hello</p>");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue