Add support for elif (#1057)

Co-authored-by: René Kijewski <rene.kijewski@fu-berlin.de>
This commit is contained in:
Guillaume Gomez 2024-05-23 14:27:42 +02:00 committed by GitHub
parent 627d58bc3b
commit 34f84dc10f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 73 additions and 45 deletions

View File

@ -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 {
@ -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 }))
}
}

View File

@ -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 %}

26
testing/tests/if.rs Normal file
View File

@ -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");
}

View File

@ -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");
}

View File

@ -1,8 +0,0 @@
use askama::Template;
#[derive(Template)]
#[template(source = "{% if true %}{% elif false %}{% endif %}", ext = "html")]
struct UnknownElif;
fn main() {
}

View File

@ -1,9 +0,0 @@
error: unknown `elif` keyword; did you mean `else if`?
failed to parse template source at row 1, column 16 near:
"elif false %}{% endif %}"
--> tests/ui/elif.rs:3:10
|
3 | #[derive(Template)]
| ^^^^^^^^
|
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)