#!/bin/sh -

# plug - update sections of files with the output of embedded commands
# Steve Kinzler, steve@kinzler.com, Jun 16/Jun 22
# https://kinzler.com/me/home.html#unix

one=0; pfx=; sfx=
while :
do
	case $# in
	0)	break;;
	*)	case "$1" in
		-1)	one=1;;
		-p)	shift; pfx="$1";;
		-s)	shift; sfx="$1";;

		--)	shift; break;;
		-h)	bad=t; break;;
		-)	break;;
		-*)	bad=t; echo "$0: unknown option ($1)" 1>&2;;
		*)	break;;
		esac
		shift;;
	esac
done

case "$bad" in
?*)	cat <<EOF 1>&2
usage: $0 [ -1 ] [ -p prefix ] [ -s suffix ] [ file ... ]
	-1	don't include #PLUG# lines in results
	-p	recognize #PLUG# lines with the given prefix before #PLUG#
	-s	ignore the given suffix at the end of #PLUG# lines
The lines between a contiguous set of lines beginning with "#PLUG#"
and a line exactly "#PLUG#END#" are replaced with the output of the
shell commands following "#PLUG#" on those beginning lines.  The string
"{{FILE}}" in a command is replace with the filename being changed.
Files are modified in place if changed.  The optional prefix and suffix
are perl regexps.
EOF
	exit 1;;
esac

case "$#" in
0)	set x -; shift;;
esac

tmp="${TMPDIR:-/tmp}/plug$$"
trap "rm -f '$tmp'; exit" 0 1 2 13 15

for file
do
	cat "$file" | perl -ne	'sub runcmd { system "($cmd) < /dev/null"; }
$| = 1; $l = $_; s|\Q{{FILE}}\E|\Q'"$file"'\E|g;
if (/^'"$pfx"'#PLUG#END#'"$sfx"'$/) {
	if    ($in eq "cmd") { &runcmd(); $cmd = $in = ""; }
	elsif ($in eq "txt") { $in = ""; }
	else { warn "'"$0"': warning, ignoring unmatched #PLUG#END#\n"; }
	print $l unless '"$one"';
} elsif (s/^'"$pfx"'#PLUG#//) {
	if ($in eq "txt")
	     { warn "'"$0"': warning, ignoring unmatched #PLUG#\n"; }
	else { s/'"$sfx"'$//; $cmd .= $_; $in = "cmd"; }
	print $l unless '"$one"';
} else {
	if    ($in eq "cmd") { &runcmd(); $cmd = ""; $in = "txt"; }
	elsif ($in ne "txt") { print; }
}				' > "$tmp"
	case "$file" in
	-)	cat "$tmp";;
	*)	cmp "$tmp" "$file" > /dev/null 2>&1 && continue
		test -s "$tmp" && cat < "$tmp" > "$file";;
	esac
done
