From 9d74bce266090fc3f5caa954adb44c62c8163be5 Mon Sep 17 00:00:00 2001 From: jaina heartles Date: Tue, 15 Nov 2022 23:53:29 -0800 Subject: [PATCH] Add loop captures --- src/template/lib.zig | 72 ++++++++++++++++++++++++++++---------- src/template/test.tmp.html | 3 +- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src/template/lib.zig b/src/template/lib.zig index 3e014e5..07a93b5 100644 --- a/src/template/lib.zig +++ b/src/template/lib.zig @@ -33,8 +33,10 @@ fn executeStatement(writer: anytype, comptime stmt: Statement, args: anytype) !v .for_loop => |loop| { const fields = loop.iterable.arg_deref; const iterable = argDeref(args, fields); - for (iterable) |str| { - try writer.writeAll(str); + const subtemplate = loop.subtemplate; + try writer.writeAll("capture on " ++ loop.capture ++ ": "); + for (iterable) |_| { + try executeTemplate(writer, subtemplate, args); } }, else => @compileError("TODO"), @@ -102,6 +104,8 @@ fn parseTemplate(comptime tokens: TokenIter, comptime template_type: TemplateTyp }, .period => current_text = current_text ++ ".", .pound => current_text = current_text ++ "#", + .pipe => current_text = current_text ++ "|", + .dollar => current_text = current_text ++ "$", } } @@ -166,22 +170,56 @@ fn parseStatement(comptime tokens: TokenIter) ParseResult(Statement) { } } +fn skipWhitespace(comptime tokens: TokenIter) TokenIter { + comptime { + var iter = tokens; + while (iter.peek()) |token| switch (token) { + .whitespace => _ = iter.next(), + else => break, + }; + + return iter; + } +} + +fn endStatement(comptime tokens: TokenIter) TokenIter { + comptime { + var iter = skipWhitespace(tokens); + + const token = iter.next() orelse @compileError("Unexpected end of template"); + if (token != .close_bracket) @compileError("Unexpected token"); + return iter; + } +} + fn parseForLoop(comptime tokens: TokenIter) ParseResult(ForLoop) { comptime { const iterable = parseExpression(tokens); var iter = iterable.new_iter; - while (iter.next()) |token| switch (token) { - .whitespace => {}, - .close_bracket => break, - else => @compileError("Unexpected token"), + + iter = skipWhitespace(iter); + { + const token = iter.next() orelse @compileError("Unexpected end of template"); + if (token != .pipe) @compileError("Unexpected token"); + } + { + const token = iter.next() orelse @compileError("Unexpected end of template"); + if (token != .dollar) @compileError("Unexpected token"); + } + const capture = blk: { + const token = iter.next() orelse @compileError("Unexpected end of template"); + if (token != .text) @compileError("Unexpected token"); + break :blk token.text; }; + { + const token = iter.next() orelse @compileError("Unexpected end of template"); + if (token != .pipe) @compileError("Unexpected token"); + } + iter = endStatement(iter); const subtemplate = parseTemplate(iter, .subtemplate); - return .{ .new_iter = subtemplate.new_iter, .item = .{ - .iterable = iterable.item, - .subtemplate = subtemplate.item, - } }; + return .{ .new_iter = subtemplate.new_iter, .item = .{ .iterable = iterable.item, .subtemplate = subtemplate.item, .capture = capture } }; } } @@ -247,6 +285,7 @@ const Expression = union(enum) { const ForLoop = struct { subtemplate: []const TemplateItem, iterable: Expression, + capture: []const u8, }; const Statement = union(enum) { @@ -255,13 +294,6 @@ const Statement = union(enum) { end_for: void, }; -const State = enum { - text, - text_close_bracket, - template_start, - template, -}; - const Keyword = enum { @"for", end_for, @@ -274,6 +306,8 @@ const Token = union(enum) { period: void, whitespace: []const u8, pound: void, + pipe: void, + dollar: void, }; const TokenIter = struct { @@ -299,6 +333,8 @@ const TokenIter = struct { '}' => return .{ .close_bracket = {} }, '.' => return .{ .period = {} }, '#' => return .{ .pound = {} }, + '|' => return .{ .pipe = {} }, + '$' => return .{ .dollar = {} }, ' ', '\t', '\n', '\r' => { var idx: usize = 0; while (idx < remaining.len and std.mem.indexOfScalar(u8, " \t\n\r", remaining[idx]) != null) : (idx += 1) {} @@ -310,7 +346,7 @@ const TokenIter = struct { }, else => { var idx: usize = 0; - while (idx < remaining.len and std.mem.indexOfScalar(u8, "{}.# \t\n\r", remaining[idx]) == null) : (idx += 1) {} + while (idx < remaining.len and std.mem.indexOfScalar(u8, "{}.#|$ \t\n\r", remaining[idx]) == null) : (idx += 1) {} self.start += idx - 1; return .{ .text = remaining[0..idx] }; diff --git a/src/template/test.tmp.html b/src/template/test.tmp.html index c00d1c4..2f39f2a 100644 --- a/src/template/test.tmp.html +++ b/src/template/test.tmp.html @@ -9,8 +9,7 @@

{{ REAL BRACKETS }}

- {#for .foo} - {#end_for} + {#for .foo |$f|}a testing thing {#end_for} {{#for args.notes |$note, $i|}}

Note no. {{$i}}

{{#template note_display ($note)}}