From 35bc0df2cd9965de1204add9d97d1766d820839d Mon Sep 17 00:00:00 2001 From: "Lucas F." Date: Sat, 3 Jan 2026 21:30:59 -0300 Subject: [PATCH] update: add regroup and resetcycle --- src/parser.zig | 78 +++++++++++++++++++++++++++++++++++++++++++++ src/parser_test.zig | 48 ++++++++++++++++++++++++++++ todo.md | 8 ++--- 3 files changed, 130 insertions(+), 4 deletions(-) diff --git a/src/parser.zig b/src/parser.zig index ad2021f..0a74076 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -25,6 +25,18 @@ pub const NodeType = enum { partialdef, partial, querystring, + regroup, + resetcycle, +}; + +pub const ResetCycleNode = struct { + cycle_name: ?[]const u8 = null, // null = reseta todos, ou nome específico +}; + +pub const RegroupNode = struct { + source: []const u8, + by: []const u8, + as_var: []const u8, }; pub const QueryStringNode = struct { @@ -178,6 +190,8 @@ pub const Node = struct { partialdef: ?PartialDefNode = null, partial: ?PartialNode = null, querystring: ?QueryStringNode = null, + regroup: ?RegroupNode = null, + resetcycle: ?ResetCycleNode = null, csrf_token: bool = false, debug: bool = false, @@ -287,6 +301,14 @@ pub const Node = struct { for (qs.modifications) |m| allocator.free(m); allocator.free(qs.modifications); }, + .regroup => if (self.regroup) |r| { + allocator.free(r.source); + allocator.free(r.by); + allocator.free(r.as_var); + }, + .resetcycle => if (self.resetcycle) |rc| { + if (rc.cycle_name) |name| allocator.free(name); + }, } } }; @@ -1715,6 +1737,62 @@ pub const Parser = struct { continue; } + if (std.mem.eql(u8, tag_name, "regroup")) { + const args = node.tag.?.args; + + // Esperado: lista by atributo as nome_grupo + const by_pos = std.mem.indexOf(u8, args, " by ") orelse return error.InvalidRegroupSyntax; + const as_pos = std.mem.indexOf(u8, args[by_pos + 4 ..], " as ") orelse return error.InvalidRegroupSyntax; + const as_pos_abs = by_pos + 4 + as_pos; + + const source_raw = std.mem.trim(u8, args[0..by_pos], " \t\r\n"); + const by_raw = std.mem.trim(u8, args[by_pos + 4 .. as_pos_abs], " \t\r\n"); + const as_raw = std.mem.trim(u8, args[as_pos_abs + 4 ..], " \t\r\n"); + + const source = try allocator.dupe(u8, source_raw); + const by = try allocator.dupe(u8, by_raw); + const as_var = try allocator.dupe(u8, as_raw); + + allocator.free(node.tag.?.name); + allocator.free(node.tag.?.args); + + std.debug.print("3.0 - na real sou um regroup\n", .{}); + std.debug.print("===================================\n", .{}); + + try list.append(allocator, Node{ + .type = .regroup, + .regroup = .{ + .source = source, + .by = by, + .as_var = as_var, + }, + }); + continue; + } + + if (std.mem.eql(u8, tag_name, "resetcycle")) { + const args = std.mem.trim(u8, node.tag.?.args, " \t\r\n"); + + var cycle_name: ?[]const u8 = null; + if (args.len > 0) { + cycle_name = try allocator.dupe(u8, args); + } + + allocator.free(node.tag.?.name); + allocator.free(node.tag.?.args); + + std.debug.print("3.0 - na real sou um resetcycle\n", .{}); + std.debug.print("===================================\n", .{}); + + try list.append(allocator, Node{ + .type = .resetcycle, + .resetcycle = .{ + .cycle_name = cycle_name, + }, + }); + continue; + } + if (std.mem.eql(u8, tag_name, "csrf_token")) { // Verifica se tem argumentos (não deve ter) if (node.tag.?.args.len > 0 and !std.mem.allEqual(u8, node.tag.?.args, ' ')) { diff --git a/src/parser_test.zig b/src/parser_test.zig index c51dc50..e687fc6 100644 --- a/src/parser_test.zig +++ b/src/parser_test.zig @@ -806,3 +806,51 @@ test "parse querystring múltiplos" { try testing.expectEqualStrings("pagina", qs.modifications[1]); try testing.expectEqualStrings("None", qs.modifications[2]); } + +test "parse regroup simples" { + const allocator = testing.allocator; + const template = "{% regroup pessoas by cidade as grupos_cidade %}"; + const nodes = try parser.parse(allocator, template); + defer { + for (nodes) |node| node.deinit(allocator); + allocator.free(nodes); + } + + try testing.expectEqual(@as(usize, 1), nodes.len); + try testing.expect(nodes[0].type == .regroup); + const r = nodes[0].regroup.?; + try testing.expectEqualStrings("pessoas", r.source); + try testing.expectEqualStrings("cidade", r.by); + try testing.expectEqualStrings("grupos_cidade", r.as_var); +} + +test "parse resetcycle simples" { + const allocator = testing.allocator; + const template = "{% resetcycle %}"; + const nodes = try parser.parse(allocator, template); + defer { + for (nodes) |node| node.deinit(allocator); + allocator.free(nodes); + } + + try testing.expectEqual(@as(usize, 1), nodes.len); + try testing.expect(nodes[0].type == .resetcycle); + const rc = nodes[0].resetcycle.?; + try testing.expect(rc.cycle_name == null); +} + +test "parse resetcycle com nome" { + const allocator = testing.allocator; + const template = "{% resetcycle rowclass %}"; + const nodes = try parser.parse(allocator, template); + defer { + for (nodes) |node| node.deinit(allocator); + allocator.free(nodes); + } + + try testing.expectEqual(@as(usize, 1), nodes.len); + try testing.expect(nodes[0].type == .resetcycle); + const rc = nodes[0].resetcycle.?; + try testing.expect(rc.cycle_name != null); + try testing.expectEqualStrings("rowclass", rc.cycle_name.?); +} diff --git a/todo.md b/todo.md index 190bc34..b279286 100644 --- a/todo.md +++ b/todo.md @@ -19,8 +19,8 @@ - [x] partial - [x] partialdef - [x] querystring -- [ ] regroup -- [ ] resetcycle +- [x] regroup +- [x] resetcycle - [x] spaceless - [ ] templatetag - [x] url @@ -112,8 +112,8 @@ ___ - [x] lorem - [x] partial / partialdef - [x] querystring -- [ ] regroup -- [ ] resetcycle +- [x] regroup +- [x] resetcycle - [ ] templatetag - [ ] widthratio