aboutsummaryrefslogtreecommitdiffstats
path: root/askama_shared/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--askama_shared/src/generator.rs37
1 files changed, 30 insertions, 7 deletions
diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs
index f6d7cca..7500cc7 100644
--- a/askama_shared/src/generator.rs
+++ b/askama_shared/src/generator.rs
@@ -1278,15 +1278,38 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
method: &str,
args: &[Expr<'_>],
) -> Result<DisplayWrap, CompileError> {
- if let Expr::Var("self") = obj {
- buf.write("self");
+ if matches!(obj, Expr::Var("loop")) {
+ match method {
+ "cycle" => match args {
+ [arg] => {
+ if matches!(arg, Expr::Array(arr) if arr.is_empty()) {
+ panic!("loop.cycle(…) cannot use an empty array.");
+ }
+ buf.write("({");
+ buf.write("let _cycle = &(");
+ self.visit_expr(buf, arg)?;
+ buf.writeln(");")?;
+ buf.writeln("let _len = _cycle.len();")?;
+ buf.writeln("if _len == 0 {")?;
+ buf.writeln("return ::core::result::Result::Err(::askama::Error::Fmt(::core::fmt::Error));")?;
+ buf.writeln("}")?;
+ buf.writeln("_cycle[_loop_item.index % _len]")?;
+ buf.writeln("})")?;
+ }
+ _ => return Err("loop.cycle(…) expects exactly one argument".into()),
+ },
+ s => return Err(format!("unknown loop method: {:?}", s).into()),
+ }
} else {
- self.visit_expr(buf, obj)?;
+ if let Expr::Var("self") = obj {
+ buf.write("self");
+ } else {
+ self.visit_expr(buf, obj)?;
+ }
+ buf.write(&format!(".{}(", normalize_identifier(method)));
+ self._visit_args(buf, args)?;
+ buf.write(")");
}
-
- buf.write(&format!(".{}(", normalize_identifier(method)));
- self._visit_args(buf, args)?;
- buf.write(")");
Ok(DisplayWrap::Unwrapped)
}