Skip to content

Commit

Permalink
Add support for tuple
Browse files Browse the repository at this point in the history
  • Loading branch information
yossyX authored and djc committed Jan 4, 2019
1 parent 39e0832 commit bef88f1
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 14 deletions.
44 changes: 33 additions & 11 deletions askama_derive/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,11 +468,7 @@ impl<'a> Generator<'a> {

self.write_buf_writable(buf);
buf.write("for (_loop_index, ");
let targets = self.visit_target(var);
for name in &targets {
self.locals.insert(name);
buf.write(name);
}
self.visit_target(buf, var);
match iter {
Expr::Range(_, _, _) => buf.writeln(&format!(") in ({}).enumerate() {{", expr_code)),
_ => buf.writeln(&format!(") in (&{}).into_iter().enumerate() {{", expr_code)),
Expand Down Expand Up @@ -576,6 +572,15 @@ impl<'a> Generator<'a> {
self.locals.insert(name);
buf.write(name);
}
Target::Tuple(ref targets) => {
buf.write("(");
for name in targets {
self.locals.insert(name);
buf.write(name);
buf.write(",");
}
buf.write(")");
}
}
buf.writeln(";");
}
Expand All @@ -593,6 +598,15 @@ impl<'a> Generator<'a> {
}
buf.write(name);
}
Target::Tuple(ref targets) => {
buf.write("let (");
for name in targets {
self.locals.insert(name);
buf.write(name);
buf.write(",");
}
buf.write(")");
}
}
buf.writeln(&format!(" = {};", &expr_buf.buf));
}
Expand Down Expand Up @@ -1024,13 +1038,21 @@ impl<'a> Generator<'a> {
DisplayWrap::Unwrapped
}

fn visit_target_single<'t>(&mut self, name: &'t str) -> Vec<&'t str> {
vec![name]
}

fn visit_target<'t>(&mut self, target: &'t Target) -> Vec<&'t str> {
fn visit_target(&mut self, buf: &mut Buffer, target: &'a Target) {
match *target {
Target::Name(s) => self.visit_target_single(s),
Target::Name(name) => {
self.locals.insert(name);
buf.write(name);
}
Target::Tuple(ref targets) => {
buf.write("(");
for name in targets {
self.locals.insert(name);
buf.write(name);
buf.write(",");
}
buf.write(")");
}
}
}

Expand Down
24 changes: 22 additions & 2 deletions askama_derive/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub enum MatchParameter<'a> {
#[derive(Debug)]
pub enum Target<'a> {
Name(&'a str),
Tuple(Vec<&'a str>),
}

#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -275,6 +276,25 @@ named!(target_single<Input, Target>, map!(identifier,
|s| Target::Name(s)
));

named!(target_tuple<Input, Target>, do_parse!(
tag!("(") >>
args: opt!(do_parse!(
arg0: ws!(identifier) >>
args: many0!(do_parse!(
tag!(",") >>
argn: ws!(identifier) >>
(argn)
)) >>
({
let mut res = vec![arg0];
res.extend(args);
res
})
)) >>
tag!(")") >>
(Target::Tuple(args.unwrap_or_default()))
));

named!(variant_name<Input, MatchVariant>, map!(identifier,
|s| MatchVariant::Name(s)
));
Expand Down Expand Up @@ -703,7 +723,7 @@ named_args!(block_match<'a>(s: &'a Syntax<'a>) <Input<'a>, Node<'a>>, do_parse!(
named!(block_let<Input, Node>, do_parse!(
pws: opt!(tag!("-")) >>
ws!(tag!("let")) >>
var: ws!(target_single) >>
var: ws!(alt!(target_single | target_tuple)) >>
val: opt!(do_parse!(
ws!(tag!("=")) >>
val: ws!(expr_any) >>
Expand All @@ -720,7 +740,7 @@ named!(block_let<Input, Node>, do_parse!(
named_args!(block_for<'a>(s: &'a Syntax<'a>) <Input<'a>, Node<'a>>, do_parse!(
pws1: opt!(tag!("-")) >>
ws!(tag!("for")) >>
var: ws!(target_single) >>
var: ws!(alt!(target_single | target_tuple)) >>
ws!(tag!("in")) >>
iter: ws!(expr_any) >>
nws1: opt!(tag!("-")) >>
Expand Down
3 changes: 3 additions & 0 deletions testing/templates/for.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{% for s in strings %}
{{- loop.index0 }}. {{ s }}{% if loop.first %} (first){% endif %}
{% endfor %}
{% for (s1, s2) in tuple_strings %}
{{- loop.index0 }}. {{ s1 }},{{ s2 }}{% if loop.first %} (first){% endif %}
{% endfor %}
1 change: 1 addition & 0 deletions testing/templates/let.html
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
{% let v = s %}{{ v }}
{% let (v1,v2) = t %}{{ v1 }}{{ v2 }}
7 changes: 6 additions & 1 deletion testing/tests/loops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ use askama::Template;
#[template(path = "for.html")]
struct ForTemplate<'a> {
strings: Vec<&'a str>,
tuple_strings: Vec<(&'a str, &'a str)>,
}

#[test]
fn test_for() {
let s = ForTemplate {
strings: vec!["A", "alfa", "1"],
tuple_strings: vec![("B", "beta")],
};
assert_eq!(s.render().unwrap(), "0. A (first)\n1. alfa\n2. 1\n");
assert_eq!(
s.render().unwrap(),
"0. A (first)\n1. alfa\n2. 1\n\n0. B,beta (first)\n"
);
}

#[derive(Template)]
Expand Down
16 changes: 16 additions & 0 deletions testing/tests/vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@ fn test_let() {
assert_eq!(t.render().unwrap(), "foo");
}

#[derive(Template)]
#[template(path = "let.html")]
struct LetTupleTemplate<'a> {
s: &'a str,
t: (&'a str, &'a str),
}

#[test]
fn test_let_tuple() {
let t = LetTupleTemplate {
s: "foo",
t: ("bar", "bazz"),
};
assert_eq!(t.render().unwrap(), "foo\nbarbazz");
}

#[derive(Template)]
#[template(path = "let-decl.html")]
struct LetDeclTemplate<'a> {
Expand Down

0 comments on commit bef88f1

Please sign in to comment.