aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askama_derive/src/generator.rs20
-rw-r--r--askama_derive/src/parser.rs37
2 files changed, 44 insertions, 13 deletions
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index dd34bec..6eb16e8 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -317,6 +317,25 @@ impl<'a> Generator<'a> {
self.writeln("))?;");
}
+ fn write_call(&mut self, ws: &WS, name: &str, args: &[Expr]) {
+ self.handle_ws(ws);
+ let def = self.macros.get(name).expect(&format!("macro '{}' not found", name));
+ self.locals.push();
+ self.writeln("{");
+ self.prepare_ws(&def.0);
+ for (i, arg) in def.2.iter().enumerate() {
+ self.write(&format!("let {} = &", arg));
+ self.locals.insert(arg);
+ self.visit_expr(&args.get(i)
+ .expect(&format!("macro '{}' takes more than {} arguments", name, i)));
+ self.writeln(";");
+ }
+ self.handle(&def.3);
+ self.flush_ws(&def.4);
+ self.writeln("}");
+ self.locals.pop();
+ }
+
fn write_let_decl(&mut self, ws: &WS, var: &'a Target) {
self.handle_ws(ws);
self.write("let ");
@@ -453,6 +472,7 @@ impl<'a> Generator<'a> {
Node::Include(ref ws, ref path) => {
self.handle_include(ws, path);
},
+ Node::Call(ref ws, name, ref args) => self.write_call(ws, name, args),
Node::Macro(_, _, _, _, _) |
Node::Extends(_) => {
panic!("no extends or macros allowed in content");
diff --git a/askama_derive/src/parser.rs b/askama_derive/src/parser.rs
index dad7e84..491a5d7 100644
--- a/askama_derive/src/parser.rs
+++ b/askama_derive/src/parser.rs
@@ -26,6 +26,7 @@ pub enum Node<'a> {
Lit(&'a str, &'a str, &'a str),
Comment(),
Expr(WS, Expr<'a>),
+ Call(WS, &'a str, Vec<Expr<'a>>),
LetDecl(WS, Target<'a>),
Let(WS, Target<'a>, Expr<'a>),
Cond(Vec<(WS, Option<Expr<'a>>, Vec<Node<'a>>)>, WS),
@@ -129,21 +130,21 @@ named!(target_single<Target>, map!(identifier,
named!(arguments<Vec<Expr>>, do_parse!(
tag_s!("(") >>
- arg0: ws!(opt!(expr_any)) >>
- args: many0!(do_parse!(
- tag_s!(",") >>
- argn: ws!(expr_any) >>
- (argn)
+ args: opt!(do_parse!(
+ arg0: ws!(expr_any) >>
+ args: many0!(do_parse!(
+ tag_s!(",") >>
+ argn: ws!(expr_any) >>
+ (argn)
+ )) >>
+ ({
+ let mut res = vec![arg0];
+ res.extend(args);
+ res
+ })
)) >>
tag_s!(")") >>
- ({
- let mut res = Vec::new();
- if arg0.is_some() {
- res.push(arg0.unwrap());
- }
- res.extend(args);
- res
- })
+ (args.unwrap_or(Vec::new()))
));
named!(parameters<Vec<&'a str>>, do_parse!(
@@ -261,6 +262,15 @@ named!(expr_node<Node>, do_parse!(
(Node::Expr(WS(pws.is_some(), nws.is_some()), expr))
));
+named!(block_call<Node>, do_parse!(
+ pws: opt!(tag_s!("-")) >>
+ ws!(tag_s!("call")) >>
+ name: ws!(identifier) >>
+ args: ws!(arguments) >>
+ nws: opt!(tag_s!("-")) >>
+ (Node::Call(WS(pws.is_some(), nws.is_some()), name, args))
+));
+
named!(cond_if<Expr>, do_parse!(
ws!(tag_s!("if")) >>
cond: ws!(expr_any) >>
@@ -389,6 +399,7 @@ named!(block_macro<Node>, do_parse!(
named!(block_node<Node>, do_parse!(
tag_s!("{%") >>
contents: alt!(
+ block_call |
block_let |
block_if |
block_for |