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

View File

@ -459,6 +459,8 @@ and is used as you might expect:
No users No users
{% else if users.len() == 1 %} {% else if users.len() == 1 %}
1 user 1 user
{% elif users.len() == 2 %}
2 users
{% else %} {% else %}
{{ users.len() }} users {{ users.len() }} users
{% endif %} {% 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"); 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)