Skip to content

Instantly share code, notes, and snippets.

@dhamidi
Created December 18, 2013 08:16
Show Gist options
  • Save dhamidi/8018923 to your computer and use it in GitHub Desktop.
Save dhamidi/8018923 to your computer and use it in GitHub Desktop.
ERB-like template processor in POSIX AWK. Usage: ./template.awk < input.esh | sh > output
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title><%= "$TITLE" %></title>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>
<p>It's alive!</p>
<ul>
<%- for i in 1 2 3; do %>
<li><%= "$i" %></li>
<%- done %>
</ul>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>
<p>It's alive!</p>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</body>
</html>
printf "%s\n" '<!doctype html>'
printf "%s\n" '<html>'
printf "%s\n" ' <head>'
printf "%s\n" ' <meta charset="utf-8">'
printf "%s" ' <title>'
printf "%s" "$TITLE"
printf "%s\n" '</title>'
printf "%s\n" ' <script type="text/javascript" src="jquery.js"></script>'
printf "%s\n" ' </head>'
printf "%s\n" ' <body>'
printf "%s\n" ' <p>It'\''s alive!</p>'
printf "%s\n" ' <ul>'
printf "%s" ''
for i in 1 2 3; do
printf "%s" ' <li>'
printf "%s" "$i"
printf "%s\n" '</li>'
printf "%s" ''
done
printf "%s\n" ' </ul>'
printf "%s\n" ' </body>'
printf "%s\n" '</html>'
#! awk -f
BEGIN {
template_re = "<%[-= %][^%]+ %>"
template_system_prefix["="] = "printf \"%s\" "
}
function shell_quote(text) {
gsub(/'/, "'\\''", text)
return sprintf("'%s'", text)
}
function emit_text_1(text, newline) {
printf("printf \"%%s%s\" %s\n", (newline ? "\\n" : ""), shell_quote(text))
}
function emit_text(text) {
emit_text_1(text, 0)
}
function emit_text_nl(text) {
emit_text_1(text, 1)
}
function emit_code(prefix, code) {
if (length(prefix) + length(code) > 0)
printf "%s%s\n", prefix, code
}
function compile_fragment(text) {
# everything up to <%
before_match = substr(text, 1, RSTART - 1)
# skip over <%, return [-= ]
prefix = substr(text, RSTART + 2, 1)
# skip over prefix and exclude postix ("%>")
command = substr(text, RSTART + 3, RLENGTH - 5)
# the rest of the line
after_match = substr(text, RSTART + RLENGTH)
if (prefix == "-") {
sub(/^[[:blank:]]+/, "", before_match)
} else if (prefix == "%") {
before_match = before_match "<%" command
command = ""
after_match = "%>" after_match
}
emit_text(before_match)
emit_code(template_system_prefix[prefix], command)
return after_match
}
$0 ~ template_re {
text = $0
found = match(text, template_re)
while (found) {
text = compile_fragment(text)
found = match(text, template_re)
}
if (length(text) > 0)
emit_text_nl(text)
}
$0 !~ template_re {
emit_text_nl($0)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment