diff options
| author | 2017-10-15 13:09:07 +0200 | |
|---|---|---|
| committer | 2017-10-15 14:04:52 +0200 | |
| commit | a32532d5ae339cf3dcde1bd0b684e7bd7f8c51fc (patch) | |
| tree | 3f60765d9a7d84d687e95ae100c00eb0a0a5ae84 /askama_shared | |
| parent | 5333a52ca2da1a18bb856be8ef27a23c1c1543ad (diff) | |
| download | askama-a32532d5ae339cf3dcde1bd0b684e7bd7f8c51fc.tar.gz askama-a32532d5ae339cf3dcde1bd0b684e7bd7f8c51fc.tar.bz2 askama-a32532d5ae339cf3dcde1bd0b684e7bd7f8c51fc.zip | |
Add scope when importing macros
Diffstat (limited to '')
| -rw-r--r-- | askama_shared/src/generator.rs | 26 | ||||
| -rw-r--r-- | askama_shared/src/lib.rs | 22 | ||||
| -rw-r--r-- | askama_shared/src/parser.rs | 15 | 
3 files changed, 39 insertions, 24 deletions
| diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs index df01dfe..544d336 100644 --- a/askama_shared/src/generator.rs +++ b/askama_shared/src/generator.rs @@ -12,7 +12,7 @@ use std::collections::{HashMap, HashSet};  use syn; -pub fn generate(input: &TemplateInput, nodes: &[Node], imported: &HashMap<&str, Macro>) -> String { +pub fn generate(input: &TemplateInput, nodes: &[Node], imported: &HashMap<(&str, &str), Macro>) -> String {      Generator::default().build(&State::new(input, nodes, imported))  } @@ -26,7 +26,7 @@ struct State<'a> {  }  impl<'a> State<'a> { -    fn new<'n>(input: &'n TemplateInput, nodes: &'n [Node], imported: &'n HashMap<&'n str, Macro<'n>>) -> State<'n> { +    fn new<'n>(input: &'n TemplateInput, nodes: &'n [Node], imported: &'n HashMap<(&'n str, &'n str), Macro<'n>>) -> State<'n> {          let mut base: Option<&Expr> = None;          let mut blocks = Vec::new();          let mut macros = HashMap::new(); @@ -42,13 +42,13 @@ impl<'a> State<'a> {                      blocks.push(def);                  },                  Node::Macro(name, ref m) => { -                    macros.insert(name, m); +                    macros.insert((None, name), m);                  },                  _ => {},              }          } -        for (name, ref m) in imported { -            macros.insert(name, m); +        for (&(scope, name), ref m) in imported { +            macros.insert((Some(scope), name), m);          }          State {              input, @@ -351,7 +351,7 @@ impl<'a> Generator<'a> {                  Node::Include(ref ws, path) => {                      self.handle_include(state, ws, path);                  }, -                Node::Call(ref ws, name, ref args) => self.write_call(state, ws, name, args), +                Node::Call(ref ws, scope, name, ref args) => self.write_call(state, ws, scope, name, args),                  Node::Macro(_, ref m) => {                      if let AstLevel::Nested = level {                          panic!("macro blocks only allowed at the top level"); @@ -359,7 +359,7 @@ impl<'a> Generator<'a> {                      self.flush_ws(&m.ws1);                      self.prepare_ws(&m.ws2);                  }, -                Node::Import(ref ws, _) => { +                Node::Import(ref ws, _, _) => {                      if let AstLevel::Nested = level {                          panic!("import blocks only allowed at the top level");                      } @@ -446,8 +446,14 @@ impl<'a> Generator<'a> {          self.locals.pop();      } -    fn write_call(&mut self, state: &'a State, ws: &WS, name: &str, args: &[Expr]) { -        let def = state.macros.get(name).expect(&format!("macro '{}' not found", name)); +    fn write_call(&mut self, state: &'a State, ws: &WS, scope: Option<&str>, name: &str, args: &[Expr]) { +        let def = state.macros.get(&(scope, name)).unwrap_or_else(|| { +            if let Some(ref s) = scope { +                panic!(format!("macro '{}::{}' not found", s, name)); +            } else { +                panic!(format!("macro '{}' not found", name)); +            } +        });          self.flush_ws(ws); // Cannot handle_ws() here: whitespace from macro definition comes first          self.locals.push();          self.writeln("{"); @@ -812,4 +818,4 @@ enum DisplayWrap {      Unwrapped,  } -type MacroMap<'a> = HashMap<&'a str, &'a Macro<'a>>; +type MacroMap<'a> = HashMap<(Option<&'a str>, &'a str), &'a Macro<'a>>; diff --git a/askama_shared/src/lib.rs b/askama_shared/src/lib.rs index 4e57a82..88439dc 100644 --- a/askama_shared/src/lib.rs +++ b/askama_shared/src/lib.rs @@ -50,17 +50,17 @@ pub fn build_template(ast: &syn::DeriveInput) -> String {  pub struct Imports<'a> { -    pub sources: Vec<Cow<'a, str>> +    pub sources: HashMap<&'a str, Cow<'a, str>>  }  impl <'a> Imports<'a> {      pub fn new(parent_nodes: &'a [Node], parent_path: &'a Path) -> Imports<'a> {          let sources = parent_nodes.iter().filter_map(|n| {              match *n { -                Node::Import(_, ref import_path) => { +                Node::Import(_, ref import_path, scope) => {                      let path = path::find_template_from_path(import_path, Some(parent_path));                      let src = path::get_template_source(&path); -                    Some(Cow::Owned(src)) +                    Some((scope, Cow::Owned(src)))                  },                  _ => None,              } @@ -68,15 +68,17 @@ impl <'a> Imports<'a> {          Imports { sources }      } -    pub fn macro_map(&'a self) -> HashMap<&'a str, Macro<'a>> { -        self.sources.iter() -            .flat_map(|s| parser::parse(s.as_ref())) -            .filter_map(|n| { +    pub fn macro_map(&'a self) -> HashMap<(&'a str, &'a str), Macro<'a>> { +        let mut macro_map = HashMap::new(); +        for (scope, s) in self.sources.iter() { +            for n in parser::parse(&s.as_ref()) {                  match n { -                    Node::Macro(name, m) => Some((name, m)), +                    Node::Macro(name, m) => macro_map.insert((*scope, name), m),                      _ => None, -                }}) -            .collect() +                }; +            } +        } +        macro_map      }  } diff --git a/askama_shared/src/parser.rs b/askama_shared/src/parser.rs index 495b68f..7cd8936 100644 --- a/askama_shared/src/parser.rs +++ b/askama_shared/src/parser.rs @@ -35,7 +35,7 @@ pub enum Node<'a> {      Lit(&'a str, &'a str, &'a str),      Comment(),      Expr(WS, Expr<'a>), -    Call(WS, &'a str, Vec<Expr<'a>>), +    Call(WS, Option<& 'a str>, &'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), @@ -43,7 +43,7 @@ pub enum Node<'a> {      Extends(Expr<'a>),      BlockDef(WS, &'a str, Vec<Node<'a>>, WS),      Include(WS, &'a str), -    Import(WS, &'a str), +    Import(WS, &'a str, &'a str),      Macro(&'a str, Macro<'a>),  } @@ -296,10 +296,15 @@ named!(expr_node<Node>, do_parse!(  named!(block_call<Node>, do_parse!(      pws: opt!(tag_s!("-")) >>      ws!(tag_s!("call")) >> +    scope: opt!(do_parse!( +        scope: ws!(identifier) >> +        ws!(tag_s!("::")) >> +        (scope) +    )) >>      name: ws!(identifier) >>      args: ws!(arguments) >>      nws: opt!(tag_s!("-")) >> -    (Node::Call(WS(pws.is_some(), nws.is_some()), name, args)) +    (Node::Call(WS(pws.is_some(), nws.is_some()), scope, name, args))  ));  named!(cond_if<Expr>, do_parse!( @@ -411,11 +416,13 @@ named!(block_import<Node>, do_parse!(      pws: opt!(tag_s!("-")) >>      ws!(tag_s!("import")) >>      name: ws!(expr_str_lit) >> +    ws!(tag_s!("as")) >> +    scope: ws!(identifier) >>      nws: opt!(tag_s!("-")) >>      (Node::Import(WS(pws.is_some(), nws.is_some()), match name {          Expr::StrLit(s) => s,          _ => panic!("import path must be a string literal"), -    })) +    }, scope))  ));  named!(block_macro<Node>, do_parse!( | 
