aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Anthony Nowell <anowell@gmail.com>2017-10-05 02:47:36 -0600
committerLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2017-11-02 14:58:46 +0100
commitcc51d201ab9e7ba958363d1f74b7bfd4dd12fecf (patch)
treef7c0c5ba23f1a6125846e248b73a8d273ebd7979
parent751dee3fbabb35a8ad30ebdaee8e4dd4120c289a (diff)
downloadaskama-cc51d201ab9e7ba958363d1f74b7bfd4dd12fecf.tar.gz
askama-cc51d201ab9e7ba958363d1f74b7bfd4dd12fecf.tar.bz2
askama-cc51d201ab9e7ba958363d1f74b7bfd4dd12fecf.zip
support literals in match arms
Diffstat (limited to '')
-rw-r--r--askama_shared/src/generator.rs24
-rw-r--r--askama_shared/src/parser.rs54
-rw-r--r--testing/templates/match-literal.html8
-rw-r--r--testing/templates/match-opt.html (renamed from testing/templates/match.html)2
-rw-r--r--testing/tests/matches.rs32
5 files changed, 103 insertions, 17 deletions
diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs
index 6fca3fb..0c8b1e2 100644
--- a/askama_shared/src/generator.rs
+++ b/askama_shared/src/generator.rs
@@ -1,6 +1,6 @@
use filters;
use input::TemplateInput;
-use parser::{self, Cond, Expr, Macro, Node, Target, When, WS};
+use parser::{self, Cond, Expr, Macro, MatchParameter, Node, Target, When, WS};
use path;
use quote::{Tokens, ToTokens};
@@ -445,15 +445,20 @@ impl<'a> Generator<'a> {
for arm in arms {
let &(ref ws, ref variant, ref params, ref body) = arm;
self.locals.push();
- self.write(variant);
+ match *variant {
+ Some(ref param) => { self.visit_match_param(param); },
+ None => self.write("_"),
+ };
if params.len() > 0 {
self.write("(");
for (i, param) in params.iter().enumerate() {
- self.locals.insert(param);
+ if let MatchParameter::Name(ref p) = *param {
+ self.locals.insert(p);
+ }
if i > 0 {
self.write(", ");
}
- self.write(param);
+ self.visit_match_param(param);
}
self.write(")");
}
@@ -624,6 +629,17 @@ impl<'a> Generator<'a> {
}
}
+ fn visit_match_param(&mut self, param: &MatchParameter) -> DisplayWrap {
+ match *param {
+ MatchParameter::NumLit(s) => self.visit_num_lit(s),
+ MatchParameter::StrLit(s) => self.visit_str_lit(s),
+ MatchParameter::Name(s) => {
+ self.write(s);
+ DisplayWrap::Unwrapped
+ }
+ }
+ }
+
fn visit_filter(&mut self, name: &str, args: &[Expr]) -> DisplayWrap {
if name == "format" {
self._visit_format_filter(args);
diff --git a/askama_shared/src/parser.rs b/askama_shared/src/parser.rs
index 6ea5ffd..76125ef 100644
--- a/askama_shared/src/parser.rs
+++ b/askama_shared/src/parser.rs
@@ -16,6 +16,13 @@ pub enum Expr<'a> {
}
#[derive(Debug)]
+pub enum MatchParameter<'a> {
+ Name(&'a str),
+ NumLit(&'a str),
+ StrLit(&'a str),
+}
+
+#[derive(Debug)]
pub enum Target<'a> {
Name(&'a str),
}
@@ -50,7 +57,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>>);
+pub type When<'a> = (WS, Option<MatchParameter<'a>>, Vec<MatchParameter<'a>>, Vec<Node<'a>>);
fn split_ws_parts(s: &[u8]) -> Node {
if s.is_empty() {
@@ -147,11 +154,20 @@ named!(expr_array_lit<Expr>, do_parse!(
})
));
+named!(param_num_lit<MatchParameter>, map!(num_lit,
+ |s| MatchParameter::NumLit(s)
+));
+
named!(expr_str_lit<Expr>, map!(
delimited!(char!('"'), take_until!("\""), char!('"')),
|s| Expr::StrLit(str::from_utf8(s).unwrap())
));
+named!(param_str_lit<MatchParameter>, map!(
+ delimited!(char!('"'), is_not!("\""), char!('"')),
+ |s| MatchParameter::StrLit(str::from_utf8(s).unwrap())
+));
+
named!(expr_var<Expr>, map!(identifier,
|s| Expr::Var(s))
);
@@ -174,6 +190,10 @@ named!(target_single<Target>, map!(identifier,
|s| Target::Name(s)
));
+named!(param_name<MatchParameter>, map!(identifier,
+ |s| MatchParameter::Name(s)
+));
+
named!(arguments<Vec<Expr>>, do_parse!(
tag_s!("(") >>
args: opt!(do_parse!(
@@ -212,10 +232,24 @@ named!(parameters<Vec<&'a str>>, do_parse!(
(vals.unwrap_or_default())
));
-named!(with_parameters<Vec<&'a str>>, do_parse!(
+named!(with_parameters<Vec<MatchParameter>>, do_parse!(
tag_s!("with") >>
- params: ws!(parameters) >>
- (params)
+ ws!(tag_s!("(")) >>
+ vals: opt!(do_parse!(
+ arg0: ws!(match_parameter) >>
+ args: many0!(do_parse!(
+ tag_s!(",") >>
+ argn: ws!(match_parameter) >>
+ (argn)
+ )) >>
+ ({
+ let mut res = vec![arg0];
+ res.extend(args);
+ res
+ })
+ )) >>
+ tag_s!(")") >>
+ (vals.unwrap_or_default())
));
named!(expr_group<Expr>, map!(
@@ -232,6 +266,12 @@ named!(expr_single<Expr>, alt!(
expr_group
));
+named!(match_parameter<MatchParameter>, alt!(
+ param_name |
+ param_num_lit |
+ param_str_lit
+));
+
named!(attr<(&str, Option<Vec<Expr>>)>, do_parse!(
tag_s!(".") >>
attr: alt!(num_lit | identifier) >>
@@ -374,19 +414,19 @@ named!(match_else_block<When>, do_parse!(
nws: opt!(tag_s!("-")) >>
tag_s!("%}") >>
block: parse_template >>
- (WS(pws.is_some(), nws.is_some()), "_", vec![], block)
+ (WS(pws.is_some(), nws.is_some()), None, vec![], block)
));
named!(when_block<When>, do_parse!(
tag_s!("{%") >>
pws: opt!(tag_s!("-")) >>
ws!(tag_s!("when")) >>
- variant: ws!(identifier) >>
+ variant: ws!(match_parameter) >>
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)
+ (WS(pws.is_some(), nws.is_some()), Some(variant), params.unwrap_or_default(), block)
));
named!(block_match<Node>, do_parse!(
diff --git a/testing/templates/match-literal.html b/testing/templates/match-literal.html
new file mode 100644
index 0000000..22203f4
--- /dev/null
+++ b/testing/templates/match-literal.html
@@ -0,0 +1,8 @@
+{% match item %}
+{% when "foo" %}
+Found literal foo
+{% when "bar" %}
+Found literal bar
+{% else %}
+Else found {{item}}
+{% endmatch %}
diff --git a/testing/templates/match.html b/testing/templates/match-opt.html
index 51950b4..c77a2a6 100644
--- a/testing/templates/match.html
+++ b/testing/templates/match-opt.html
@@ -1,4 +1,6 @@
{% match item %}
+{% when Some with ("foo") %}
+Found literal foo
{% when Some with (val) %}
Found {{val}}
{% when None %}
diff --git a/testing/tests/matches.rs b/testing/tests/matches.rs
index 4a55615..4f159ab 100644
--- a/testing/tests/matches.rs
+++ b/testing/tests/matches.rs
@@ -4,15 +4,35 @@ extern crate askama;
use askama::Template;
#[derive(Template)]
-#[template(path = "match.html")]
-struct MatchTemplate<'a> {
+#[template(path = "match-opt.html")]
+struct MatchOptTemplate<'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");
+ let s = MatchOptTemplate { item: Some("foo") };
+ assert_eq!(s.render().unwrap(), "\n\nFound literal foo\n");
+
+ let s = MatchOptTemplate { item: Some("bar") };
+ assert_eq!(s.render().unwrap(), "\n\nFound bar\n");
+
+ let s = MatchOptTemplate { item: None };
+ assert_eq!(s.render().unwrap(), "\n\nNot Found\n");
+}
+
+
+#[derive(Template)]
+#[template(path = "match-literal.html")]
+struct MatchLitTemplate<'a> {
+ item: &'a str,
+}
+
+#[test]
+fn test_match_literal() {
+ let s = MatchLitTemplate { item: "bar" };
+ assert_eq!(s.render().unwrap(), "\n\nFound literal bar\n");
+
+ let s = MatchLitTemplate { item: "qux" };
+ assert_eq!(s.render().unwrap(), "\n\nElse found qux\n");
}