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 = "
" par "
" + 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