aboutsummaryrefslogtreecommitdiffstats
path: root/askama_derive/src
diff options
context:
space:
mode:
authorLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2017-08-04 13:19:30 +0200
committerLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2017-08-04 13:21:55 +0200
commit51eee57b84adf7fe72b7aa9b23e3ef974baad5a4 (patch)
tree5a4e70a1a1fc73f95dc21bfef6ffb6a6f296c06a /askama_derive/src
parent02e0f783f93d6336015736d4adfd2cebca275b00 (diff)
downloadaskama-51eee57b84adf7fe72b7aa9b23e3ef974baad5a4.tar.gz
askama-51eee57b84adf7fe72b7aa9b23e3ef974baad5a4.tar.bz2
askama-51eee57b84adf7fe72b7aa9b23e3ef974baad5a4.zip
Add support for include blocks (see #25)
Diffstat (limited to 'askama_derive/src')
-rw-r--r--askama_derive/src/generator.rs30
-rw-r--r--askama_derive/src/parser.rs22
2 files changed, 47 insertions, 5 deletions
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index f055cb7..570ab06 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -1,4 +1,4 @@
-use parser::{Cond, Expr, Node, Target, WS};
+use parser::{self, Cond, Expr, Node, Target, WS};
use std::str;
use std::collections::HashSet;
use syn;
@@ -27,17 +27,25 @@ struct Generator<'a> {
impl<'a> Generator<'a> {
- fn new() -> Generator<'a> {
+ fn new(locals: HashSet<String>, indent: u8) -> Generator<'a> {
Generator {
buf: String::new(),
- indent: 0,
+ indent: indent,
start: true,
- locals: HashSet::new(),
+ locals: locals,
next_ws: None,
skip_ws: false,
}
}
+ fn default() -> Generator<'a> {
+ Self::new(HashSet::new(), 0)
+ }
+
+ fn child(&self) -> Generator<'a> {
+ Self::new(self.locals.clone(), self.indent)
+ }
+
fn indent(&mut self) {
self.indent += 1;
}
@@ -282,6 +290,15 @@ impl<'a> Generator<'a> {
self.writeln("}");
}
+ fn handle_include(&mut self, ws: &WS, src: &str) {
+ self.prepare_ws(ws);
+ let nodes = parser::parse(&src);
+ let mut gen = self.child();
+ gen.handle(&nodes);
+ self.buf.push_str(&gen.result());
+ self.flush_ws(ws);
+ }
+
fn handle(&mut self, nodes: &'a [Node]) {
for n in nodes {
match *n {
@@ -300,6 +317,9 @@ impl<'a> Generator<'a> {
Node::BlockDef(ref ws1, name, ref block_nodes, ref ws2) => {
self.write_block_def(ws1, name, block_nodes, ws2);
}
+ Node::Include(ref ws, ref src) => {
+ self.handle_include(ws, src);
+ },
Node::Extends(_) => {
panic!("no extends or block definition allowed in content");
},
@@ -446,7 +466,7 @@ pub fn generate(ast: &syn::DeriveInput, path: &str, mut nodes: Vec<Node>) -> Str
}
}
- let mut gen = Generator::new();
+ let mut gen = Generator::default();
if !blocks.is_empty() {
if base.is_none() {
gen.define_trait(path, &block_names);
diff --git a/askama_derive/src/parser.rs b/askama_derive/src/parser.rs
index 61ccb09..6a182d5 100644
--- a/askama_derive/src/parser.rs
+++ b/askama_derive/src/parser.rs
@@ -1,4 +1,5 @@
use nom::{self, IResult};
+use path;
use std::str;
#[derive(Debug)]
@@ -31,6 +32,7 @@ pub enum Node<'a> {
Extends(Expr<'a>),
BlockDef(WS, &'a str, Vec<Node<'a>>, WS),
Block(WS, &'a str, WS),
+ Include(WS, String),
}
pub type Cond<'a> = (WS, Option<Expr<'a>>, Vec<Node<'a>>);
@@ -324,6 +326,25 @@ named!(block_block<Node>, do_parse!(
WS(pws2.is_some(), pws2.is_some())))
));
+named!(block_include<Node>, do_parse!(
+ tag_s!("{%") >>
+ pws: opt!(tag_s!("-")) >>
+ ws!(tag_s!("include")) >>
+ name: ws!(expr_str_lit) >>
+ nws: opt!(tag_s!("-")) >>
+ tag_s!("%}") >>
+ ({
+ let mut src = match name {
+ Expr::StrLit(s) => path::get_template_source(s),
+ _ => panic!("include path must be a string literal"),
+ };
+ if src.ends_with('\n') {
+ let _ = src.pop();
+ }
+ Node::Include(WS(pws.is_some(), nws.is_some()), src)
+ })
+));
+
named!(block_comment<Node>, do_parse!(
tag_s!("{#") >>
take_until_s!("#}") >>
@@ -338,6 +359,7 @@ named!(parse_template<Vec<Node<'a>>>, many0!(alt!(
block_if |
block_for |
block_extends |
+ block_include |
block_block
)));