mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-02 07:20:55 +00:00
implement basic match functionality
This commit is contained in:
parent
14beb21d0c
commit
468f376bfc
@ -1,6 +1,6 @@
|
||||
use filters;
|
||||
use input::TemplateInput;
|
||||
use parser::{self, Cond, Expr, Macro, Node, Target, WS};
|
||||
use parser::{self, Cond, Expr, Macro, Node, Target, When, WS};
|
||||
use path;
|
||||
|
||||
use quote::{Tokens, ToTokens};
|
||||
@ -339,6 +339,9 @@ impl<'a> Generator<'a> {
|
||||
Node::Cond(ref conds, ref ws) => {
|
||||
self.write_cond(state, conds, ws);
|
||||
},
|
||||
Node::Match(ref ws1, ref expr, ref inter, ref arms, ref ws2) => {
|
||||
self.write_match(state, ws1, expr, inter, arms, ws2);
|
||||
},
|
||||
Node::Loop(ref ws1, ref var, ref iter, ref body, ref ws2) => {
|
||||
self.write_loop(state, ws1, var, iter, body, ws2);
|
||||
},
|
||||
@ -428,6 +431,43 @@ impl<'a> Generator<'a> {
|
||||
self.writeln("}");
|
||||
}
|
||||
|
||||
fn write_match(&mut self, state: &'a State, ws1: &WS, expr: &Expr, inter: &'a str, arms:
|
||||
&'a [When], ws2: &WS) {
|
||||
self.flush_ws(ws1);
|
||||
if !inter.is_empty() {
|
||||
self.next_ws = Some(inter);
|
||||
}
|
||||
|
||||
self.write("match ");
|
||||
self.visit_expr(expr);
|
||||
self.writeln(" {");
|
||||
|
||||
for arm in arms {
|
||||
let &(ref ws, ref variant, ref params, ref body) = arm;
|
||||
self.locals.push();
|
||||
self.write(variant);
|
||||
if params.len() > 0 {
|
||||
self.write("(");
|
||||
for (i, param) in params.iter().enumerate() {
|
||||
self.locals.insert(param);
|
||||
if i > 0 {
|
||||
self.write(", ");
|
||||
}
|
||||
self.write(param);
|
||||
}
|
||||
self.write(")");
|
||||
}
|
||||
self.writeln(" => {");
|
||||
self.handle_ws(ws);
|
||||
self.handle(state, body, AstLevel::Nested);
|
||||
self.writeln("}");
|
||||
self.locals.pop();
|
||||
}
|
||||
|
||||
self.writeln("}");
|
||||
self.handle_ws(ws2);
|
||||
}
|
||||
|
||||
fn write_loop(&mut self, state: &'a State, ws1: &WS, var: &'a Target, iter: &Expr,
|
||||
body: &'a [Node], ws2: &WS) {
|
||||
self.handle_ws(ws1);
|
||||
|
@ -40,6 +40,7 @@ pub enum Node<'a> {
|
||||
LetDecl(WS, Target<'a>),
|
||||
Let(WS, Target<'a>, Expr<'a>),
|
||||
Cond(Vec<(WS, Option<Expr<'a>>, Vec<Node<'a>>)>, WS),
|
||||
Match(WS, Expr<'a>, &'a str, Vec<When<'a>>, WS),
|
||||
Loop(WS, Target<'a>, Expr<'a>, Vec<Node<'a>>, WS),
|
||||
Extends(Expr<'a>),
|
||||
BlockDef(WS, &'a str, Vec<Node<'a>>, WS),
|
||||
@ -49,6 +50,7 @@ pub enum Node<'a> {
|
||||
}
|
||||
|
||||
pub type Cond<'a> = (WS, Option<Expr<'a>>, Vec<Node<'a>>);
|
||||
pub type When<'a> = (WS, &'a str, Vec<&'a str>, Vec<Node<'a>>);
|
||||
|
||||
fn split_ws_parts(s: &[u8]) -> Node {
|
||||
if s.is_empty() {
|
||||
@ -210,6 +212,12 @@ named!(parameters<Vec<&'a str>>, do_parse!(
|
||||
(vals.unwrap_or_default())
|
||||
));
|
||||
|
||||
named!(with_parameters<Vec<&'a str>>, do_parse!(
|
||||
tag_s!("with") >>
|
||||
params: ws!(parameters) >>
|
||||
(params)
|
||||
));
|
||||
|
||||
named!(expr_group<Expr>, map!(
|
||||
delimited!(char!('('), expr_any, char!(')')),
|
||||
|s| Expr::Group(Box::new(s))
|
||||
@ -359,6 +367,51 @@ named!(block_if<Node>, do_parse!(
|
||||
})
|
||||
));
|
||||
|
||||
named!(when_block<When>, do_parse!(
|
||||
tag_s!("{%") >>
|
||||
pws: opt!(tag_s!("-")) >>
|
||||
ws!(tag_s!("when")) >>
|
||||
variant: ws!(identifier) >>
|
||||
params: opt!(ws!(with_parameters)) >>
|
||||
nws: opt!(tag_s!("-")) >>
|
||||
tag_s!("%}") >>
|
||||
block: parse_template >>
|
||||
(WS(pws.is_some(), nws.is_some()), variant, params.unwrap_or_default(), block)
|
||||
));
|
||||
|
||||
named!(block_match<Node>, do_parse!(
|
||||
pws1: opt!(tag_s!("-")) >>
|
||||
ws!(tag_s!("match")) >>
|
||||
expr: ws!(expr_any) >>
|
||||
nws1: opt!(tag_s!("-")) >>
|
||||
tag_s!("%}") >>
|
||||
inter: take_content >>
|
||||
arms: many1!(when_block) >>
|
||||
ws!(tag_s!("{%")) >>
|
||||
pws2: opt!(tag_s!("-")) >>
|
||||
ws!(tag_s!("endmatch")) >>
|
||||
nws2: opt!(tag_s!("-")) >>
|
||||
({
|
||||
let inter = match inter {
|
||||
Node::Lit(lws, val, rws) => {
|
||||
assert!(val.is_empty(),
|
||||
"only whitespace allowed between match and first when, found {}", val);
|
||||
assert!(rws.is_empty(),
|
||||
"only whitespace allowed between match and first when, found {}", rws);
|
||||
lws
|
||||
},
|
||||
_ => panic!("only literals allowed between match and first when"),
|
||||
};
|
||||
Node::Match(
|
||||
WS(pws1.is_some(), nws1.is_some()),
|
||||
expr,
|
||||
inter,
|
||||
arms,
|
||||
WS(pws2.is_some(), nws2.is_some()),
|
||||
)
|
||||
})
|
||||
));
|
||||
|
||||
named!(block_let<Node>, do_parse!(
|
||||
pws: opt!(tag_s!("-")) >>
|
||||
ws!(tag_s!("let")) >>
|
||||
@ -471,6 +524,7 @@ named!(block_node<Node>, do_parse!(
|
||||
block_let |
|
||||
block_if |
|
||||
block_for |
|
||||
block_match |
|
||||
block_extends |
|
||||
block_include |
|
||||
block_import |
|
||||
|
6
testing/templates/match.html
Normal file
6
testing/templates/match.html
Normal file
@ -0,0 +1,6 @@
|
||||
{% match item %}
|
||||
{% when Some with (val) %}
|
||||
Found {{val}}
|
||||
{% when None %}
|
||||
Not Found
|
||||
{% endmatch %}
|
18
testing/tests/matches.rs
Normal file
18
testing/tests/matches.rs
Normal file
@ -0,0 +1,18 @@
|
||||
#[macro_use]
|
||||
extern crate askama;
|
||||
|
||||
use askama::Template;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "match.html")]
|
||||
struct MatchTemplate<'a> {
|
||||
item: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_match_option() {
|
||||
let s = MatchTemplate {
|
||||
item: Some("foo"),
|
||||
};
|
||||
assert_eq!(s.render().unwrap(), "\n\nFound foo\n");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user