From 6858108f9c4c8856ac70ce749faa117ab3a4ff2a Mon Sep 17 00:00:00 2001
From: Wim Looman <wim@nemo157.com>
Date: Mon, 1 Feb 2016 18:03:50 +0100
Subject: [PATCH] Allow tuple attribute lookups

---
 maud_macros/src/parse.rs   | 11 ++++++++++-
 maud_macros/tests/tests.rs |  9 +++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/maud_macros/src/parse.rs b/maud_macros/src/parse.rs
index 03d110e..4a048db 100644
--- a/maud_macros/src/parse.rs
+++ b/maud_macros/src/parse.rs
@@ -6,7 +6,7 @@ use syntax::errors::{DiagnosticBuilder, FatalError};
 use syntax::ext::base::ExtCtxt;
 use syntax::parse;
 use syntax::parse::parser::Parser as RustParser;
-use syntax::parse::token::{BinOpToken, DelimToken, IdentStyle, Token};
+use syntax::parse::token::{BinOpToken, DelimToken, IdentStyle, Token, Lit as LitToken};
 use syntax::parse::token::keywords::Keyword;
 use syntax::ptr::P;
 
@@ -53,6 +53,9 @@ macro_rules! slash {
 macro_rules! literal {
     () => (TokenTree::Token(_, Token::Literal(..)))
 }
+macro_rules! integer {
+    () => (TokenTree::Token(_, Token::Literal(LitToken::Integer(_), _)))
+}
 macro_rules! ident {
     ($sp:pat, $x:pat) => (TokenTree::Token($sp, Token::Ident($x, IdentStyle::Plain)))
 }
@@ -328,6 +331,12 @@ impl<'cx, 'i> Parser<'cx, 'i> {
                 tts.push(dot.clone());
                 tts.push(ident.clone());
             },
+            // Munch tuple attribute lookups e.g. `$person.1.2`
+            [ref dot @ dot!(), ref num @ integer!(), ..] => {
+                self.shift(2);
+                tts.push(dot.clone());
+                tts.push(num.clone());
+            },
             // Munch function calls `()` and indexing operations `[]`
             [TokenTree::Delimited(sp, ref d), ..] if d.delim != DelimToken::Brace => {
                 self.shift(1);
diff --git a/maud_macros/tests/tests.rs b/maud_macros/tests/tests.rs
index 42eb731..9973f8f 100644
--- a/maud_macros/tests/tests.rs
+++ b/maud_macros/tests/tests.rs
@@ -309,3 +309,12 @@ fn issue_23() {
     let s = to_string!(p { "Hi, " $name "!" });
     assert_eq!(s, "<p>Hi, Lyra!</p>");
 }
+
+#[test]
+fn tuple_accessors() {
+    let mut s = String::new();
+    let a = ("ducks", "geese");
+    html!(s, { $a.0 }).unwrap();
+    assert_eq!(s, "ducks");
+}
+