aboutsummaryrefslogtreecommitdiffstats
path: root/askama_shared/src/generator.rs
diff options
context:
space:
mode:
authorLibravatar René Kijewski <kijewski@library.vetmed.fu-berlin.de>2021-07-18 16:32:49 +0200
committerLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2021-11-11 15:35:45 +0100
commit10b2d9c615460c9dbb241b887d0e6e17e3c001ca (patch)
tree4ec234cf416f7bcdc0bc037f787ebbd7ac4cb67e /askama_shared/src/generator.rs
parenta8503e0fa2d6065b1c471becf76dde68571b7984 (diff)
downloadaskama-10b2d9c615460c9dbb241b887d0e6e17e3c001ca.tar.gz
askama-10b2d9c615460c9dbb241b887d0e6e17e3c001ca.tar.bz2
askama-10b2d9c615460c9dbb241b887d0e6e17e3c001ca.zip
Implement for-else
This PR implements for-else statements like in Jinja. They make it easy to print an alternative message if the loop iterator was empty. E.g. ```rs {% for result in result %} <li>{{ result }}</li> {% else %} <li><em>no results</em></li> {% endfor %} ```
Diffstat (limited to 'askama_shared/src/generator.rs')
-rw-r--r--askama_shared/src/generator.rs43
1 files changed, 26 insertions, 17 deletions
diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs
index 6c1b151..0c2e854 100644
--- a/askama_shared/src/generator.rs
+++ b/askama_shared/src/generator.rs
@@ -2,7 +2,7 @@ use super::{get_template_source, CompileError, Integrations};
use crate::filters;
use crate::heritage::{Context, Heritage};
use crate::input::{Source, TemplateInput};
-use crate::parser::{parse, Cond, CondTest, Expr, Node, Target, When, Ws};
+use crate::parser::{parse, Cond, CondTest, Expr, Loop, Node, Target, When, Ws};
use proc_macro2::Span;
@@ -420,8 +420,8 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
Node::Match(ws1, ref expr, ref arms, ws2) => {
self.write_match(ctx, buf, ws1, expr, arms, ws2)?;
}
- Node::Loop(ws1, ref var, ref iter, ref body, ws2) => {
- self.write_loop(ctx, buf, ws1, var, iter, body, ws2)?;
+ Node::Loop(ref loop_block) => {
+ self.write_loop(ctx, buf, loop_block)?;
}
Node::BlockDef(ws1, name, _, ws2) => {
self.write_block(buf, Some(name), Ws(ws1.0, ws2.1))?;
@@ -596,21 +596,19 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
&mut self,
ctx: &'a Context<'_>,
buf: &mut Buffer,
- ws1: Ws,
- var: &'a Target<'_>,
- iter: &Expr<'_>,
- body: &'a [Node<'_>],
- ws2: Ws,
+ loop_block: &'a Loop<'_>,
) -> Result<usize, CompileError> {
- self.handle_ws(ws1);
+ self.handle_ws(loop_block.ws1);
self.locals.push();
- let expr_code = self.visit_expr_root(iter)?;
+ let expr_code = self.visit_expr_root(&loop_block.iter)?;
let flushed = self.write_buf_writable(buf)?;
+ buf.writeln("{")?;
+ buf.writeln("let mut _did_not_loop = true;")?;
buf.write("for (");
- self.visit_target(buf, true, true, var);
- match iter {
+ self.visit_target(buf, true, true, &loop_block.var);
+ match loop_block.iter {
Expr::Range(_, _, _) => buf.writeln(&format!(
", _loop_item) in ::askama::helpers::TemplateLoop::new({}) {{",
expr_code
@@ -645,13 +643,24 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
)),
}?;
- let mut size_hint = self.handle(ctx, body, buf, AstLevel::Nested)?;
- self.handle_ws(ws2);
-
- size_hint += self.write_buf_writable(buf)?;
+ buf.writeln("_did_not_loop = false;")?;
+ let mut size_hint1 = self.handle(ctx, &loop_block.body, buf, AstLevel::Nested)?;
+ self.handle_ws(loop_block.ws2);
+ size_hint1 += self.write_buf_writable(buf)?;
+ self.locals.pop();
buf.writeln("}")?;
+
+ buf.writeln("if _did_not_loop {")?;
+ self.locals.push();
+ let mut size_hint2 = self.handle(ctx, &loop_block.else_block, buf, AstLevel::Nested)?;
+ self.handle_ws(loop_block.ws3);
+ size_hint2 += self.write_buf_writable(buf)?;
self.locals.pop();
- Ok(flushed + (size_hint * 3))
+ buf.writeln("}")?;
+
+ buf.writeln("}")?;
+
+ Ok(flushed + ((size_hint1 * 3) + size_hint2) / 2)
}
fn write_call(