From e7ed953b88c7f6383085c88dd5f761bb2875c02b Mon Sep 17 00:00:00 2001
From: bott <mhpoin@gmail.com>
Date: Sun, 11 Nov 2018 20:22:53 +0100
Subject: Add write! named arguments

---
 askama_derive/src/generator.rs | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

(limited to 'askama_derive/src')

diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index f40b094..947d88f 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -43,6 +43,8 @@ struct Generator<'a> {
     super_block: Option<(&'a str, usize)>,
     // buffer for writable
     buf_writable: Vec<Writable<'a>>,
+    // Counter for write! hash named arguments
+    named: usize,
 }
 
 impl<'a> Generator<'a> {
@@ -61,6 +63,7 @@ impl<'a> Generator<'a> {
             skip_ws: false,
             super_block: None,
             buf_writable: vec![],
+            named: 0,
         }
     }
 
@@ -628,6 +631,7 @@ impl<'a> Generator<'a> {
             } else {
                 let mut buf_format = Buffer::new(0);
                 let mut buf_expr = Buffer::new(buf.indent + 1);
+                let mut expr_cache = HashMap::with_capacity(self.buf_writable.len());
                 for s in mem::replace(&mut self.buf_writable, vec![]) {
                     match s {
                         Writable::Lit(s) => {
@@ -638,18 +642,31 @@ impl<'a> Generator<'a> {
                             use super::input::EscapeMode::*;
                             let mut expr_buf = Buffer::new(0);
                             let wrapped = self.visit_expr(&mut expr_buf, s);
-
-                            buf_format.write("{}");
-                            buf_expr.write("&");
-                            buf_expr.write(&match (wrapped, &self.input.escaping) {
+                            let expression = match (wrapped, &self.input.escaping) {
                                 (Wrapped, &Html) | (Wrapped, &None) | (Unwrapped, &None) => {
-                                    expr_buf.buf
+                                    expr_buf.buf.clone()
                                 }
                                 (Unwrapped, &Html) => {
-                                    format!("::askama::MarkupDisplay::from(&{})", expr_buf.buf)
+                                    format!(
+                                        "::askama::MarkupDisplay::from(&{})",
+                                        expr_buf.buf.clone()
+                                    )
                                 }
+                            };
+
+                            let id = expr_cache.entry(expression).or_insert_with(|| {
+                                let id = self.named;
+                                self.named += 1;
+
+                                buf_expr.write(&format!("a{}=", id));
+                                buf_expr.write("&");
+                                buf_expr.write(&expr_buf.buf);
+                                buf_expr.writeln(",");
+
+                                id
                             });
-                            buf_expr.writeln(",");
+
+                            buf_format.write(&format!("{{a{}}}", id));
                         }
                     }
                 }
-- 
cgit