Add support for optional unwrapping conditionals
This commit is contained in:
parent
86e203730c
commit
06b8483a8a
2 changed files with 82 additions and 2 deletions
|
@ -15,6 +15,8 @@ pub fn main() !void {
|
|||
.bar = .{ .x = "x" },
|
||||
.qux = false,
|
||||
.quxx = true,
|
||||
.maybe_foo = @as(?[]const u8, "foo"),
|
||||
.maybe_bar = @as(?[]const u8, null),
|
||||
},
|
||||
.{
|
||||
.context_foo = "foo",
|
||||
|
@ -83,9 +85,33 @@ fn executeStatement(
|
|||
.@"if" => |if_stmt| {
|
||||
const condition = evaluateExpression(if_stmt.header.condition, args, captures, context);
|
||||
const subtemplate = if_stmt.subtemplate;
|
||||
if (condition) {
|
||||
try executeTemplate(writer, templates, subtemplate, args, captures, context);
|
||||
var was_true: bool = false;
|
||||
if (if_stmt.header.capture) |capture| {
|
||||
if (condition) |val| {
|
||||
was_true = true;
|
||||
try executeTemplate(
|
||||
writer,
|
||||
templates,
|
||||
subtemplate,
|
||||
args,
|
||||
addCapture(captures, capture, val),
|
||||
context,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (condition) {
|
||||
was_true = true;
|
||||
try executeTemplate(
|
||||
writer,
|
||||
templates,
|
||||
subtemplate,
|
||||
args,
|
||||
captures,
|
||||
context,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!was_true) {
|
||||
if (if_stmt.else_branch) |branch| switch (branch) {
|
||||
.@"else" => |subtmpl| try executeTemplate(writer, templates, subtmpl, args, captures, context),
|
||||
.elif => |elif| try executeStatement(writer, templates, .{ .@"if" = elif.* }, args, captures, context),
|
||||
|
@ -359,6 +385,7 @@ fn parseTemplateTokens(comptime tokens: ControlTokenIter) []const TemplateToken
|
|||
.slash => items = items ++ [_]TemplateToken{.{ .text = "/" }},
|
||||
.equals => items = items ++ [_]TemplateToken{.{ .text = "=" }},
|
||||
.at => items = items ++ [_]TemplateToken{.{ .text = "@" }},
|
||||
.comma => items = items ++ [_]TemplateToken{.{ .text = "," }},
|
||||
};
|
||||
|
||||
return items;
|
||||
|
@ -551,15 +578,62 @@ fn parseForHeader(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIte
|
|||
}
|
||||
}
|
||||
|
||||
fn tryParseCapture(comptime tokens: ControlTokenIter) ?ParseResult(ControlTokenIter, []const []const u8) {
|
||||
comptime {
|
||||
var iter = tokens;
|
||||
|
||||
iter = skipWhitespace(iter);
|
||||
if ((iter.next() orelse return null) != .pipe) return null;
|
||||
iter = skipWhitespace(iter);
|
||||
var captures: []const []const u8 = &.{};
|
||||
while (true) {
|
||||
if ((iter.next() orelse return null) != .dollar) return null;
|
||||
iter = skipWhitespace(iter);
|
||||
const name = switch (iter.next() orelse return null) {
|
||||
.text => |text| text,
|
||||
else => return null,
|
||||
};
|
||||
iter = skipWhitespace(iter);
|
||||
captures = captures ++ &[_][]const u8{name};
|
||||
|
||||
switch (iter.next() orelse return null) {
|
||||
.pipe => break,
|
||||
.comma => {},
|
||||
else => return null,
|
||||
}
|
||||
iter = skipWhitespace(iter);
|
||||
}
|
||||
|
||||
return .{
|
||||
.new_iter = iter,
|
||||
.item = captures,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn parseIfHeader(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIter, IfHeader) {
|
||||
comptime {
|
||||
const condition = parseExpression(tokens);
|
||||
var iter = condition.new_iter;
|
||||
|
||||
const captures = tryParseCapture(iter);
|
||||
if (captures) |cap| {
|
||||
if (cap.item.len == 1) {
|
||||
return .{
|
||||
.new_iter = cap.new_iter,
|
||||
.item = IfHeader{
|
||||
.condition = condition.item,
|
||||
.capture = cap.item[0],
|
||||
},
|
||||
};
|
||||
} else @compileError("Only one capture allowed for if statements");
|
||||
}
|
||||
|
||||
return .{
|
||||
.new_iter = iter,
|
||||
.item = .{
|
||||
.condition = condition.item,
|
||||
.capture = null,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -657,6 +731,7 @@ const CallTemplate = struct {
|
|||
|
||||
const IfHeader = struct {
|
||||
condition: Expression,
|
||||
capture: ?[]const u8,
|
||||
};
|
||||
|
||||
const Statement = union(enum) {
|
||||
|
@ -707,6 +782,7 @@ const ControlToken = union(enum) {
|
|||
slash: void,
|
||||
equals: void,
|
||||
at: void,
|
||||
comma: void,
|
||||
};
|
||||
|
||||
const ControlTokenIter = struct {
|
||||
|
@ -737,6 +813,7 @@ const ControlTokenIter = struct {
|
|||
'/' => return .{ .slash = {} },
|
||||
'=' => return .{ .equals = {} },
|
||||
'@' => return .{ .at = {} },
|
||||
',' => return .{ .comma = {} },
|
||||
' ', '\t', '\n', '\r' => {
|
||||
var idx: usize = 0;
|
||||
while (idx < remaining.len and std.mem.indexOfScalar(u8, " \t\n\r", remaining[idx]) != null) : (idx += 1) {}
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
neither
|
||||
{=/if}
|
||||
|
||||
{#if .maybe_foo |$v|}{$v}{#else}null{/if}
|
||||
{#if .maybe_bar |$v|}{$v}{#else}null{/if}
|
||||
|
||||
<template>{#template test_tmpl .bar}</template>
|
||||
|
||||
{@context_foo}
|
||||
|
|
Loading…
Reference in a new issue