| ... | ... | @@ -22,13 +22,16 @@ pub fn parse(comptime input: string) astgen.Value { |
| 22 | 22 | |
| 23 | 23 | pub fn compile(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, data: anytype) !void { |
| 24 | 24 | try writer.writeAll("<!DOCTYPE html>\n"); |
| 25 | | try do(Ctx, alloc, writer, value, data, data, 0, false); |
| 25 | try do(Ctx, alloc, writer, value, data, data, .{ |
| 26 | .indent = 0, |
| 27 | .flag1 = false, |
| 28 | }); |
| 26 | 29 | try writer.writeAll("\n"); |
| 27 | 30 | } |
| 28 | 31 | |
| 29 | 32 | pub const Writer = std.ArrayList(u8).Writer; |
| 30 | 33 | |
| 31 | | inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype, indent: usize, flag1: bool) anyerror!void { |
| 34 | inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype, opts: DoOptions) anyerror!void { |
| 32 | 35 | switch (comptime value) { |
| 33 | 36 | .element => |v| { |
| 34 | 37 | const hastext = for (v.children) |x| { |
| ... | ... | @@ -38,7 +41,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 38 | 41 | } |
| 39 | 42 | } else false; |
| 40 | 43 | |
| 41 | | if (flag1) for (range(indent)) |_| try writer.writeAll(" "); |
| 44 | if (opts.flag1) for (range(opts.indent)) |_| try writer.writeAll(" "); |
| 42 | 45 | try writer.writeAll("<"); |
| 43 | 46 | try writer.writeAll(v.name); |
| 44 | 47 | |
| ... | ... | @@ -47,7 +50,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 47 | 50 | .string => try writer.print(" {s}=\"{}\"", .{ it.key, std.zig.fmtEscapes(it.value.string[1 .. it.value.string.len - 1]) }), |
| 48 | 51 | .body => { |
| 49 | 52 | try writer.print(" {s}=\"", .{it.key}); |
| 50 | | try do(Ctx, alloc, writer, astgen.Value{ .body = it.value.body }, data, ctx, indent, flag1); |
| 53 | try do(Ctx, alloc, writer, astgen.Value{ .body = it.value.body }, data, ctx, opts); |
| 51 | 54 | try writer.print("\"", .{}); |
| 52 | 55 | }, |
| 53 | 56 | } |
| ... | ... | @@ -64,11 +67,14 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 64 | 67 | |
| 65 | 68 | if (!hastext) try writer.writeAll("\n"); |
| 66 | 69 | inline for (v.children) |it| { |
| 67 | | try do(Ctx, alloc, writer, it, data, ctx, indent + 1, !hastext); |
| 70 | try do(Ctx, alloc, writer, it, data, ctx, .{ |
| 71 | .indent = opts.indent + 1, |
| 72 | .flag1 = !hastext, |
| 73 | }); |
| 68 | 74 | } |
| 69 | | if (!hastext) for (range(indent)) |_| try writer.writeAll(" "); |
| 75 | if (!hastext) for (range(opts.indent)) |_| try writer.writeAll(" "); |
| 70 | 76 | try writer.print("</{s}>", .{v.name}); |
| 71 | | if (flag1) try writer.writeAll("\n"); |
| 77 | if (opts.flag1) try writer.writeAll("\n"); |
| 72 | 78 | } |
| 73 | 79 | }, |
| 74 | 80 | .string => |v| { |
| ... | ... | @@ -111,25 +117,25 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 111 | 117 | switch (v.name) { |
| 112 | 118 | .each => { |
| 113 | 119 | comptime assertEqual(v.args.len, 1); |
| 114 | | for (x) |item| try do(Ctx, alloc, writer, body, item, ctx, indent, flag1); |
| 120 | for (x) |item| try do(Ctx, alloc, writer, body, item, ctx, opts); |
| 115 | 121 | }, |
| 116 | 122 | .@"if" => { |
| 117 | 123 | comptime assertEqual(v.args.len, 1); |
| 118 | 124 | if (comptime std.meta.trait.isIndexable(T)) { |
| 119 | | try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, x.len > 0); |
| 125 | try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x.len > 0); |
| 120 | 126 | return; |
| 121 | 127 | } |
| 122 | 128 | switch (comptime TI) { |
| 123 | | .Bool => try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, x), |
| 124 | | .Optional => try docap(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, x), |
| 129 | .Bool => try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x), |
| 130 | .Optional => try docap(Ctx, alloc, writer, body, bottom, data, ctx, opts, x), |
| 125 | 131 | else => @compileError(std.fmt.comptimePrint("pek: unable to use '{s}' in an #if block", .{@typeName(T)})), |
| 126 | 132 | } |
| 127 | 133 | }, |
| 128 | 134 | .ifnot => { |
| 129 | 135 | comptime assertEqual(v.args.len, 1); |
| 130 | 136 | switch (comptime TI) { |
| 131 | | .Bool => try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, !x), |
| 132 | | .Optional => try docap(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, !x), |
| 137 | .Bool => try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, !x), |
| 138 | .Optional => try docap(Ctx, alloc, writer, body, bottom, data, ctx, opts, !x), |
| 133 | 139 | else => @compileError(std.fmt.comptimePrint("pek: unable to use '{s}' in an #ifnot block", .{@typeName(T)})), |
| 134 | 140 | } |
| 135 | 141 | }, |
| ... | ... | @@ -137,23 +143,23 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 137 | 143 | comptime assertEqual(v.args.len, 2); |
| 138 | 144 | const y = if (comptime std.mem.eql(u8, v.args[1][0], "this")) search(v.args[1][1..], data) else search(v.args[1], ctx); |
| 139 | 145 | if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) { |
| 140 | | return try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, std.mem.eql(u8, @tagName(x), y)); |
| 146 | return try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y)); |
| 141 | 147 | } |
| 142 | | try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, x == y); |
| 148 | try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x == y); |
| 143 | 149 | }, |
| 144 | 150 | .ifnotequal => { |
| 145 | 151 | comptime assertEqual(v.args.len, 2); |
| 146 | 152 | const y = if (comptime std.mem.eql(u8, v.args[1][0], "this")) search(v.args[1][1..], data) else search(v.args[1], ctx); |
| 147 | 153 | if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) { |
| 148 | | return try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, std.mem.eql(u8, @tagName(x), y)); |
| 154 | return try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y)); |
| 149 | 155 | } |
| 150 | | try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, x != y); |
| 156 | try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x != y); |
| 151 | 157 | }, |
| 152 | 158 | } |
| 153 | 159 | }, |
| 154 | 160 | .body => |v| { |
| 155 | 161 | inline for (v) |val| { |
| 156 | | try do(Ctx, alloc, writer, val, data, ctx, indent, flag1); |
| 162 | try do(Ctx, alloc, writer, val, data, ctx, opts); |
| 157 | 163 | } |
| 158 | 164 | }, |
| 159 | 165 | .function => |v| { |
| ... | ... | @@ -173,7 +179,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 173 | 179 | } |
| 174 | 180 | const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } }; |
| 175 | 181 | try @call(.auto, func, args); |
| 176 | | try do(Ctx, alloc, writer, repvalue, try list.toOwnedSlice(), ctx, indent, flag1); |
| 182 | try do(Ctx, alloc, writer, repvalue, try list.toOwnedSlice(), ctx, opts); |
| 177 | 183 | return; |
| 178 | 184 | } |
| 179 | 185 | @compileError("pek: unknown custom function: " ++ v.name); |
| ... | ... | @@ -182,6 +188,11 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 182 | 188 | } |
| 183 | 189 | } |
| 184 | 190 | |
| 191 | pub const DoOptions = struct { |
| 192 | indent: usize, |
| 193 | flag1: bool, |
| 194 | }; |
| 195 | |
| 185 | 196 | fn search(comptime args: []const string, ctx: anytype) FieldSearch(@TypeOf(ctx), args) { |
| 186 | 197 | if (args.len == 0) return ctx; |
| 187 | 198 | if (args[0][0] == '"') return std.mem.trim(u8, args[0], "\""); |
| ... | ... | @@ -289,18 +300,18 @@ fn contains(haystack: []const string, needle: string) bool { |
| 289 | 300 | return false; |
| 290 | 301 | } |
| 291 | 302 | |
| 292 | | fn doif(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime top: astgen.Value, comptime bottom: astgen.Value, data: anytype, ctx: anytype, indent: usize, flag1: bool, flag2: bool) anyerror!void { |
| 303 | fn doif(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime top: astgen.Value, comptime bottom: astgen.Value, data: anytype, ctx: anytype, opts: DoOptions, flag2: bool) anyerror!void { |
| 293 | 304 | if (flag2) { |
| 294 | | try do(Ctx, alloc, writer, top, data, ctx, indent, flag1); |
| 305 | try do(Ctx, alloc, writer, top, data, ctx, opts); |
| 295 | 306 | } else { |
| 296 | | try do(Ctx, alloc, writer, bottom, data, ctx, indent, flag1); |
| 307 | try do(Ctx, alloc, writer, bottom, data, ctx, opts); |
| 297 | 308 | } |
| 298 | 309 | } |
| 299 | 310 | |
| 300 | | fn docap(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime top: astgen.Value, comptime bottom: astgen.Value, data: anytype, ctx: anytype, indent: usize, flag1: bool, flag2: anytype) anyerror!void { |
| 311 | fn docap(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime top: astgen.Value, comptime bottom: astgen.Value, data: anytype, ctx: anytype, opts: DoOptions, flag2: anytype) anyerror!void { |
| 301 | 312 | if (flag2) |_| { |
| 302 | | try do(Ctx, alloc, writer, top, data, ctx, indent, flag1); |
| 313 | try do(Ctx, alloc, writer, top, data, ctx, opts); |
| 303 | 314 | } else { |
| 304 | | try do(Ctx, alloc, writer, bottom, data, ctx, indent, flag1); |
| 315 | try do(Ctx, alloc, writer, bottom, data, ctx, opts); |
| 305 | 316 | } |
| 306 | 317 | } |