1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from itertools import product, chain, zip_longest, tee
IF, ELSE_IF, ELSE, END_IF = 0, 1, 2, 3
NL = "\\n"
dash = lambda ws: [" ", "-"][ws]
def cond_kind(i, n):
i += 1
if i == 1:
return IF # if
elif (i == n) and (i > 1):
return ELSE # else
elif i > n:
return END_IF # endif
else:
return ELSE_IF # else if
# From: https://docs.python.org/3/library/itertools.html#itertools-recipes
def pairwise(iterable):
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def write_cond(conds, active_branch):
n = len(conds) - 1
lits = []
for i in range(1, n + 2 + 1):
ws1 = "\\n" * i
ws2 = "\\r\\n" * i
lits.append((ws1, str(i), ws2))
conds = list(conds)
for i, (pws, nws) in enumerate(conds):
kind = cond_kind(i, n)
b = str(i == active_branch).lower()
cond = [f"if {b}", f"else if {b}", "else", "endif"][kind]
cond = f"{{%{dash(pws)} {cond} {dash(nws)}%}}"
conds[i] = cond
it = map("".join, lits)
it = filter(None, chain.from_iterable(zip_longest(it, conds)))
code = "".join(it)
expected = f"{lits[0][0]}{lits[0][1]}"
for i, (cond, (before, after)) in enumerate(zip(conds, pairwise(lits))):
kind = cond_kind(i, n)
pws = cond.startswith("{%-")
nws = cond.endswith("-%}")
cond = i == active_branch
prev_cond = i == (active_branch + 1)
if prev_cond or (kind == IF):
expected += before[2] * (not pws)
if cond or (kind == END_IF):
expected += after[0] * (not nws)
expected += after[1]
# FIXME: Askama does not include whitespace before eof
# expected += lits[-1][2]
return code, expected
if __name__ == "__main__":
# The amount of branches to generate
n = 2 # branches
with open("ws.rs", "w") as f:
f.write("""\
// This file is auto generated by gen_ws_tests.py
use askama::Template;
macro_rules! test_template {
($source:literal, $rendered:expr) => {{
#[derive(Template)]
#[template(source = $source, ext = "txt")]
struct CondWS;
assert_eq!(CondWS.render().unwrap(), $rendered);
}};
}
#[rustfmt::skip]
#[test]
fn test_cond_ws() {
""")
for branches in range(1, n + 1):
for x in product([False, True], repeat=(branches+1)*2):
# it = iter(x)
# conds = list(zip(it, it))
conds = list(zip(x[::2], x[1::2]))
for i in range(branches):
code, expected = write_cond(conds, i)
f.write(f' test_template!("{code}", "{expected}");\n')
if branches != n:
f.write("\n")
f.write("}\n")
|