Make splices a bit nicer to use

This commit is contained in:
Chris Wong 2015-01-18 20:18:21 +13:00
parent 40424e283c
commit 2250c2e961
2 changed files with 58 additions and 11 deletions
maud_macros

View file

@ -11,6 +11,9 @@ use super::render::{Escape, Renderer};
macro_rules! dollar {
() => (TtToken(_, token::Dollar))
}
macro_rules! dot {
() => (TtToken(_, token::Dot))
}
macro_rules! eq {
() => (TtToken(_, token::Eq))
}
@ -125,17 +128,34 @@ impl<'cx, 's, 'i, 'r, 'o> Parser<'cx, 's, 'i, 'r, 'o> {
}
fn splice(&mut self, escape: Escape, sp: Span) {
let tt = match self.input {
[ref tt, ..] => {
self.shift(1);
self.new_rust_parser(vec![tt.clone()]).parse_expr()
},
_ => {
self.render.cx.span_err(sp, "expected expression for this splice");
return;
},
};
self.render.splice(tt, escape);
let mut tts = vec![];
// First, munch a single token tree
if let [ref tt, ..] = self.input {
self.shift(1);
tts.push(tt.clone());
}
loop {
match self.input {
// Munch attribute lookups e.g. `$person.address.street`
[ref dot @ dot!(), ref ident @ ident!(_), ..] => {
self.shift(2);
tts.push(dot.clone());
tts.push(ident.clone());
},
// Munch function calls `()` and indexing operations `[]`
[TtDelimited(sp, ref d), ..] if d.delim != token::DelimToken::Brace => {
self.shift(1);
tts.push(TtDelimited(sp, d.clone()));
},
_ => break,
}
}
if tts.is_empty() {
self.render.cx.span_err(sp, "expected expression for this splice");
} else {
let expr = self.new_rust_parser(tts).parse_expr();
self.render.splice(expr, escape);
}
}
fn element(&mut self, name: &str, sp: Span) {

View file

@ -123,6 +123,33 @@ mod splices {
assert_eq!(s, "Pinkie Pie");
}
/// An example struct, for testing purposes only
struct Creature {
name: &'static str,
/// Rating out of 10, where:
/// * 0 is a naked mole rat with dysentery
/// * 10 is Sweetie Belle in a milkshake
adorableness: u8,
}
impl Creature {
fn repugnance(&self) -> u8 {
10 - self.adorableness
}
}
#[test]
fn structs() {
let pinkie = Creature {
name: "Pinkie Pie",
adorableness: 9,
};
let s = html! {
"Name: " $pinkie.name ". Rating: " $pinkie.repugnance()
}.render();
assert_eq!(s, "Name: Pinkie Pie. Rating: 1");
}
// FIXME: See <https://github.com/rust-lang/rust/issues/16617>
// for why this is commented out
/*