blob: 9c3302f03e5bd3c7a1cb94044fb236a6e86eb839 (
plain)
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
|
#!/bin/sh
# HAT TRICK
# (C) 2022 C. Duckworth
[ "x$DEBUG" = "xYES" ] && set -x
: "${HTDAT:=$(date +%s)}"
: "${HTTMP:=/tmp/ht}"; mkdir -p "$HTTMP"
: "${HTENV:=$HTTMP/env-$HTDAT.sh}"
: "${HTBOD:=$HTTMP/bod-$HTDAT.txt}"
export HTDAT HTTMP HTENV HTBOD
HT_TMPL_COUNT=1
HT_TMPL_PRE=:
print() { # print STRING...
## A sane version of `echo`.
printf '%s\n' "$*"
}
htt() { # htt FILES...
# Like `cat`, but with templating.
ht_end="ht_main_$HTDAT_$HT_TMPL_COUNT" # be extra double sure
eval "$(print "cat <<$ht_end"; cat "$@"; print; print "$ht_end")"
HT_TMPL_COUNT=$(expr $HT_TMPL_COUNT + 1)
}
ht_build_env() { # ht_build_env FILE...
print "body() { cat \"$HTBOD\"; }" > "$HTENV"
: > "$HTBOD"; # clear out body
while read -r line; do
case "$line" in
*@@*:*@@*) # "simple" metadata; just a string
print "$line" |
sed 's/.*@@\([^:]*\): \?\(.*\)@@.*/\1() { print "\2"; }/'
;;
*@@*::*@@*) # "complex" metadata: can be anything
print "$line" |
sed 's/.*@@\([^:]*\):: \?\(.*\)@@.*/\1() { \2 ; }/'
;;
esac >> "$HTENV"
# Still print the line to the body (no need to escape or w/e)
print "$line" >> "$HTBOD"
done
env | grep '^HT' | sort | uniq >> "$HTENV"
}
ht_main() { # main TEMPLATE < INPUT
## Apply TEMPLATE to INPUT and print it.
# TEMPLATE will be interpreted as a heredoc.
if [ $# -eq 0 ]; then
print "ht.sh TEMPLATE < INPUT" >&2
exit 1
fi
eval "ht_build_env; . \"$HTENV\"; print \"\$(htt \"\$@\")\";";
}
# To keep this POSIX-compliant, we can't use a bashism like
# [[ "$0" == # "$BASH_SOURCE[0]" ]]. However, there are still ways to guess
# whether the user is sourcing this file as a library or executing it as a
# script.
case "$0" in
*ht.sh) ht_main "$@" ;;
*) print "Sourcing ht.sh" ;;
esac
|