Skip to content

Commit

Permalink
Add support for elif (#1057)
Browse files Browse the repository at this point in the history
Co-authored-by: René Kijewski <rene.kijewski@fu-berlin.de>
  • Loading branch information
GuillaumeGomez and Kijewski authored May 23, 2024
1 parent 627d58b commit 34f84dc
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 45 deletions.
52 changes: 24 additions & 28 deletions askama_parser/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,24 +369,20 @@ pub struct Cond<'a> {

impl<'a> Cond<'a> {
fn parse(i: &'a str, s: &State<'_>) -> ParseResult<'a, Self> {
let mut p = tuple((
let (i, (_, pws, cond, nws, _, nodes)) = tuple((
|i| s.tag_block_start(i),
opt(Whitespace::parse),
ws(alt((keyword("else"), |i| {
let _ = keyword("elif")(i)?;
Err(nom::Err::Failure(ErrorContext::new(
"unknown `elif` keyword; did you mean `else if`?",
i,
)))
}))),
cut(tuple((
opt(|i| CondTest::parse(i, s)),
opt(Whitespace::parse),
|i| s.tag_block_end(i),
cut(|i| Node::many(i, s)),
))),
));
let (i, (_, pws, _, (cond, nws, _, nodes))) = p(i)?;
alt((
preceded(ws(keyword("else")), opt(|i| CondTest::parse(i, s))),
preceded(
ws(keyword("elif")),
cut(map(|i| CondTest::parse_cond(i, s), Some)),
),
)),
opt(Whitespace::parse),
cut(|i| s.tag_block_end(i)),
cut(|i| Node::many(i, s)),
))(i)?;
Ok((
i,
Self {
Expand All @@ -406,18 +402,18 @@ pub struct CondTest<'a> {

impl<'a> CondTest<'a> {
fn parse(i: &'a str, s: &State<'_>) -> ParseResult<'a, Self> {
let mut p = preceded(
ws(keyword("if")),
cut(tuple((
opt(delimited(
ws(alt((keyword("let"), keyword("set")))),
ws(|i| Target::parse(i, s)),
ws(char('=')),
)),
ws(|i| Expr::parse(i, s.level.get())),
))),
);
let (i, (target, expr)) = p(i)?;
preceded(ws(keyword("if")), cut(|i| Self::parse_cond(i, s)))(i)
}

fn parse_cond(i: &'a str, s: &State<'_>) -> ParseResult<'a, Self> {
let (i, (target, expr)) = pair(
opt(delimited(
ws(alt((keyword("let"), keyword("set")))),
ws(|i| Target::parse(i, s)),
ws(char('=')),
)),
ws(|i| Expr::parse(i, s.level.get())),
)(i)?;
Ok((i, Self { target, expr }))
}
}
Expand Down
2 changes: 2 additions & 0 deletions book/src/template_syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ and is used as you might expect:
No users
{% else if users.len() == 1 %}
1 user
{% elif users.len() == 2 %}
2 users
{% else %}
{{ users.len() }} users
{% endif %}
Expand Down
26 changes: 26 additions & 0 deletions testing/tests/if.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use askama::Template;

#[derive(Template)]
#[template(
source = r#"{%- if s == "" -%}
empty
{%- else if s == "b" -%}
b
{%- elif s == "c" -%}
c
{%- else -%}
else
{%- endif -%}"#,
ext = "txt"
)]
struct If<'a> {
s: &'a str,
}

#[test]
fn test_if() {
assert_eq!(If { s: "" }.render().unwrap(), "empty");
assert_eq!(If { s: "b" }.render().unwrap(), "b");
assert_eq!(If { s: "c" }.render().unwrap(), "c");
assert_eq!(If { s: "d" }.render().unwrap(), "else");
}
21 changes: 21 additions & 0 deletions testing/tests/if_let.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,24 @@ fn test_if_let_else() {
};
assert_eq!(s.render().unwrap(), "fail");
}

#[derive(Template)]
#[template(
source = r#"{%- if s.is_none() -%}
empty
{%- elif let Some(a) = s -%}
{{a}}
{%- else -%}
else
{%- endif -%}"#,
ext = "txt"
)]
struct Elif<'a> {
s: Option<&'a str>,
}

#[test]
fn test_elif() {
assert_eq!(Elif { s: None }.render().unwrap(), "empty");
assert_eq!(Elif { s: Some("tada") }.render().unwrap(), "tada");
}
8 changes: 0 additions & 8 deletions testing/tests/ui/elif.rs

This file was deleted.

9 changes: 0 additions & 9 deletions testing/tests/ui/elif.stderr

This file was deleted.

0 comments on commit 34f84dc

Please sign in to comment.