From f6ceb7e3972e08c1f554aa683ac19fa6e6d621c9 Mon Sep 17 00:00:00 2001
From: Case Duckworth
Date: Tue, 6 Feb 2024 00:12:15 -0600
Subject: Various changes

---
 subtext.awk | 81 +++++++++++++++++++++++++++++++++++++++++++++++++------------
 subtext.sh  | 13 ++++++----
 2 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/subtext.awk b/subtext.awk
index 09ec882..07dfb76 100644
--- a/subtext.awk
+++ b/subtext.awk
@@ -9,7 +9,8 @@
 BEGIN {
 	## Tuneables
 	dryrun = dryrun ? dryrun : 0
-	sopath = sopath ? sopath : ".:" ENVIRON["HOME"] "/.subtext"
+	sopath = sopath ? sopath : "."
+	sofile = sofile ? sofile : ""
 	shxend = shxend ? shxend : "%%end"
 	## Shellfix: escape ` and $ in input
 	# Ask sed to do these b/c awk has no capture groups ;_;
@@ -25,34 +26,60 @@ BEGIN {
 	$0 = $0 " " nl
 }
 
-/^#so/ { # source a file
+### AWK layer
+
+/^%so/ { # source a file
 	pushpar()
 	source($2)
 	next
 }
 
+/^%/ { next } # comments
+
+### Shell layer
+
 /^#/ { # head lines
 	sub(/^#+[ 	]*/,"")
 	head = head (head?"\n":"") $0
 	next
 }
 
+### Text layer
+
+end[endn] && $0 == end[endn] {
+	par = par "\n" end[endn--] "\n)"
+	next
+}
+
 /^\.\./ { # block
-	body = body (body?"\n":"") \
-		"$$(unquote + << .." \
-		(length>2 ? " | " substr($1,3) " " shquote(2) : "") \
-		slurp("..") \
-		"..\n)"
+	if (match($0, /[ 	]*<<[ 	]*/))
+		end[++endn] = substr($0, RSTART+RLENGTH)
+	else
+		end[++endn] = ".."
+	$0 = substr($0, 3, RSTART?RSTART-3:length)
+	par = par (par?"\n":"") \
+		"$$(" ($1 ? $1 " " shquote(2) : "") " << " end[endn]
+	# par = par (par?"\n":"") \
+	# 	"$$(unquote + << .." \
+	# 	(length>2 ? " | " substr($1,3) " " shquote(2) : "") \
+	# 	slurp("..") \
+	# 	"..\n)"
 	next
 }
 
+/^\.$/ { next } # continuation line
+
 /^\./ { # line
-	body = body (body?"\n":"") \
+	par = par (body?"\n":"") \
 		"$$(" substr($1, 2) " " shquote(2) ")"
 	next
 }
 
-/^$/ { # line break
+/^\\/ { # special line escape
+	$0 = substr($0, 2)
+}
+
+/^$/ { # blank line
 	if (!pushpar()) next
 }
 
@@ -70,25 +97,45 @@ END {
 	printf "shexpand()(eval \"$(echo 'cat<<%s';cat;echo '%s')\")\n", \
 		shxend, shxend
 	printf "shellfix()(%s)\n", shellfix
+	print "echo()(printf '%s\\n' \"$@\")"
+	print "handle_input()("\
+		"test -n \"$1\" && printf '%s' \"$*\";"\
+		"if read -r first_line;"\
+		"then echo \"$first_line\";cat;return 0;"\
+		"else echo;return 1;fi)"
 	printf "ST_SOPATH=%s\n", sopath
+	if (sofile) source(sofile)
 	print "### head"
 	print head
 	print "### body"
 	print "body(){ unquote : << \\_ | shexpand"
 	pushpar()
-	print body | (shellfix " -e 's/^/:/'")
-	close(shellfix " -e 's/^/:/'")
+	shfq = shellfix " -e 's/^/:/'"
+	print body | shfq
+	close(shfq)
 	print "_"
 	print "}"
 	if (!dryrun) print "body"
 }
 
-function shquote(begin, end,	out) {
+function shquote(begin, end,	quoted, out) {
 	if (!begin) begin = 1
 	if (!end) end = NF
 	for (i=begin; i<=NF; i++) {
-		gsub(/"/, "\\\"", $i)
-		out = out (out?" ":"") "\"" $i "\""
+		if ($i ~ /^\$/) {
+			quoted = 1
+			out = out (out?" ":"") "\"" $i
+			continue
+		}
+		if (($i ~ /\)$/) && quoted) {
+			quoted = 0
+			out = out (out?" ":"") $i "\""
+			continue
+		}
+		if (!quoted) {
+			gsub(/"/, "\\\"", $i)
+			out = out (out?" ":"") "\"" $i "\""
+		} else out = out (out?" ":"") $i
 	}
 	return out
 }
@@ -104,8 +151,9 @@ function slurp(to,	out, nl) {
 
 function pushpar() {
 	if (!par) return 0
-	if (!match(par, /^[ 	]*</))
-		par = "<p>" par "</p>"
+	if (!match(par, /^[ \t\n]*[<$]/)) {
+		par = "$$(p<<../p\n" par "\n../p\n)"
+	}
 	body = body (body?"\n":"") par
 	par = ""
 	return 1
@@ -120,6 +168,7 @@ function source(name,	found, sp) {
 			found = 1
 			head = head (head?"\n":"") ln
 		}
+		close(fn)
 		if (found) break
 	}
 	if (!found) {
diff --git a/subtext.sh b/subtext.sh
index d845955..a60f0d6 100755
--- a/subtext.sh
+++ b/subtext.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 stawk() {
-	awk -f subtext.awk "$@" # SUBTEXT AWK SCRIPT HERE
+	awk -f subtext.awk "$@"
 }
 
 usage() {
@@ -23,14 +23,17 @@ configure() {
 	: "${ST_MACROFILE:=}"
 	: "${ST_SOPATH:=.:$HOME/.subtext}"
 	: "${ST_PIPE_SH:=true}"
+	: "${ST_TRACE=+x}"
 	## Process options
-	while getopts :hm:I:n  OPT
+	while getopts :hm:I:no:x  OPT
 	do
 		case "$OPT" in
 			(h) usage ;;
-			(m) ST_MACROFILE="$OPTARG" ;;
+			(m) ST_MACROFILE="$OPTARG.st.sh" ;;
 			(I) ST_SOPATH="$ST_SOPATH:$OPTARG" ;;
 			(n) ST_PIPE_SH=false ;;
+			(o) exec > "$OPTARG" ;;
+			(x) ST_TRACE=-x ;;
 			(:) printf >&2 'Unknown option -%s\n' "$OPTARG";
 			    usage 1 ;;
 			(*) usage 1 ;;
@@ -41,9 +44,9 @@ configure() {
 main() {
 	configure "$@"
 	shift $((OPTIND-1))
-	stawk -vsopath="$ST_SOPATH" "$@" |
+	stawk -vsopath="$ST_SOPATH" -vsofile="$ST_MACROFILE" "$@" |
 		if "$ST_PIPE_SH"
-		then sh
+		then sh "$ST_TRACE"
 		else cat
 		fi
 }
-- 
cgit 1.4.1-21-gabe81