Skip to content

Instantly share code, notes, and snippets.

@Miciah
Last active March 30, 2021 21:33
Show Gist options
  • Save Miciah/8a2d5245ba8150a626acb16a16926021 to your computer and use it in GitHub Desktop.
Save Miciah/8a2d5245ba8150a626acb16a16926021 to your computer and use it in GitHub Desktop.
AWK script to indent Go template actions
#!/bin/awk
# This AWK script indents actions in Go templates. The script only modifies
# indentation for lines that begin with any amount of indentation followed by
# "{{". The script also normalizes blanks within the action, so that "{{if
# foo}}" or "{{ if foo }}" becomes "{{ if foo }}". Minus signs (as in "{{-
# if foo}}") are skipped over and preserved. Comment-only actions are formatted
# as "{{/* comment */}}" or "{{- /* command */ -}}".
#
# Shortcomings:
#
# - This script only recognizes a single "if", "with", "else", or "range"
# statement per line.
#
# - This script only recognizes a single "else" or "end" statement per line.
#
# - The normalization of blanks is rudimentary; if a line mixes "{{"/"}}"
# markers and "{{-"/"-}}" markers, the normalization may produce bad results.
#
# For example, the script indents the following:
#
# {{if .Foo}}
# {{if .Bar}}
# {{ .Baz }}
# {{end}}
# {{end}}
#
# as the following:
#
# {{if .Foo}}
# {{if .Bar}}
# {{ .Baz }}
# {{end}}
# {{end}}
#
# However, the script incorrectly indents the following:
#
# {{if .Foo}}{{if .Bar}}
# {{ .Baz }}
# {{end}}
# {{end}}
#
# as the following:
#
# {{if .Foo}}{{if .Bar}}
# {{ .Baz }}
# {{end}}
# {{end}}
#
# Also, the script incorrectly normalizes the following:
#
# {{if .Foo}} {{-if .Bar}}
# {{ .Baz }}
# {{end}} {{-end}}
#
# as the following:
#
# {{if .Foo }} {{- if .Bar }}
# {{ .Baz }}
# {{end }} {{- end }}
# Decrease the indentation level if the line has an "end" stanzza. Do this
# before printing indentation so that an "end" is indented at the same level as
# the matching "if"/"with"/"range" stanza. Similarly, decrease the indentation
# level for "else" stanzas (although we increase indentation again after
# printing the line with the "else").
/{{[-[:space:]]*(end|else)/ {
if (indentation > 0) {
indentation-=2
}
}
# Re-indent based on the current indentation level.
/^[[:space:]]*{{/ {
spaces = sprintf("%*.*s", indentation, indentation, " ");
sub(/^[[:space:]]*/, spaces)
}
# Normalize blanks within the action delimiters and print the line.
{
# Compact blanks after "{{" or "{{-" or before "}}" or "-}}".
if ($0 ~ /{{-/) {
gsub(/{{-[[:space:]]*/, "{{- ")
} else {
gsub(/{{[[:space:]]*/, "{{ ");
}
if ($0 ~ /-}}/) {
gsub(/[[:space:]]*-}}/, " -}}");
} else {
gsub(/[[:space:]]*}}/, " }}");
}
# Delete any space between "{{" and "/*" and between "*/" and "}}".
gsub(/{{ \/\*/, "{{/*")
gsub(/\*\/ }}/, "*/}}")
# Printing with the indentation level is useful when hacking on this script.
#print indentation " " $0
print
}
# Increase the indentation level if the line has an "if", "with", or "range"
# stanza. Do this after re-indenting the line so that the "if"/"with"/"range"
# stanza doesn't increase its own indentation. If the line has an "else"
# stanza, increase the indentation, which we decreased so that the line wouldn't
# be indented.
/{{[-[:space:]]*(if|with|range|else)/ {
indentation+=2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment