-
Notifications
You must be signed in to change notification settings - Fork 8
/
jq-template.awk
148 lines (130 loc) · 3.52 KB
/
jq-template.awk
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# this script assumes gawk! (busybox "awk" is not quite sufficient)
# see https://github.com/docker-library/php or https://github.com/docker-library/golang for examples of usage ("apply-templates.sh")
# escape an arbitrary string for passing back to jq as program input
function jq_escape(str, # parameters
prog, e, out) # locals
{
prog = "jq --raw-input --slurp ."
printf "%s", str |& prog
close(prog, "to")
prog |& getline out
e = close(prog)
if (e != 0) {
exit(e)
}
return out
}
# return the number of times needle appears in haystack
function num(haystack, needle, # parameters
ret, i ) # locals
{
ret = 0
while (i = index(haystack, needle)) {
ret++
haystack = substr(haystack, i + length(needle))
}
return ret
}
BEGIN {
jq_expr_defs = ""
jq_expr = ""
agg_jq = ""
agg_text = ""
if (ENVIRON["JQ_OPEN"]) {
OPEN = ENVIRON["JQ_OPEN"]
} else {
OPEN = "{{"
}
if (ENVIRON["JQ_CLOSE"]) {
CLOSE = ENVIRON["JQ_CLOSE"]
} else {
CLOSE = "}}"
}
CLOSE_EAT_EOL = "-" CLOSE ORS
}
function trim(str) {
sub(/^[[:space:]]+/, "", str)
sub(/[[:space:]]+$/, "", str)
return str
}
function append(str) {
if (jq_expr && jq_expr !~ /\($/ && str !~ /^\)/) {
jq_expr = jq_expr "\n+ "
} else if (jq_expr) {
jq_expr = jq_expr "\n"
}
jq_expr = jq_expr str
}
function append_string(str) {
if (!str) return
str = jq_escape(str)
append(str)
}
function append_jq(expr) {
if (!expr) return
expr = trim(expr)
if (!expr) return
if (expr ~ /^#[^\n]*$/) return # ignore pure comment lines {{ # ... -}}
if (expr ~ /^(def|include|import)[[:space:]]/) { # a few things need to go at the start of our "script"
jq_expr_defs = jq_expr_defs expr ";\n"
return
}
# if expr doesn't begin with ")" or end with "(", wrap it in parenthesis (so our addition chain works properly)
if (expr !~ /^\)/) expr = "(" expr
if (expr !~ /\($/) expr = expr ")"
append(expr)
}
{
line = $0 ORS
i = 0
if (agg_jq || (i = index(line, OPEN))) {
if (i) {
agg_text = agg_text substr(line, 1, i - 1)
line = substr(line, i)
}
append_string(agg_text)
agg_text = ""
agg_jq = agg_jq line
line = ""
if (num(agg_jq, OPEN) > num(agg_jq, CLOSE)) {
next
}
while (i = index(agg_jq, OPEN)) {
line = substr(agg_jq, 1, i - 1)
agg_jq = substr(agg_jq, i + length(OPEN))
if (i = index(agg_jq, CLOSE_EAT_EOL)) {
expr = substr(agg_jq, 1, i - 1)
agg_jq = substr(agg_jq, i + length(CLOSE_EAT_EOL))
}
else {
i = index(agg_jq, CLOSE)
expr = substr(agg_jq, 1, i - 1)
agg_jq = substr(agg_jq, i + length(CLOSE))
}
append_string(line)
append_jq(expr)
}
line = agg_jq
agg_jq = ""
}
if (line) {
agg_text = agg_text line
}
}
END {
append_string(agg_text)
agg_text = ""
append_jq(agg_jq)
agg_jq = ""
jq_expr = "if env.version then .[env.version] else . end | (\n" jq_expr "\n)"
jq_expr = jq_expr_defs jq_expr
if (ENVIRON["DEBUG"]) {
print jq_expr > "/dev/stderr"
}
prog = "jq --join-output --from-file /dev/stdin versions.json"
printf "%s", jq_expr | prog
e = close(prog)
if (e != 0) {
exit(e)
}
}