about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--subtext.awk81
-rwxr-xr-xsubtext.sh13
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 @@
9BEGIN { 9BEGIN {
10 ## Tuneables 10 ## Tuneables
11 dryrun = dryrun ? dryrun : 0 11 dryrun = dryrun ? dryrun : 0
12 sopath = sopath ? sopath : ".:" ENVIRON["HOME"] "/.subtext" 12 sopath = sopath ? sopath : "."
13 sofile = sofile ? sofile : ""
13 shxend = shxend ? shxend : "%%end" 14 shxend = shxend ? shxend : "%%end"
14 ## Shellfix: escape ` and $ in input 15 ## Shellfix: escape ` and $ in input
15 # Ask sed to do these b/c awk has no capture groups ;_; 16 # Ask sed to do these b/c awk has no capture groups ;_;
@@ -25,34 +26,60 @@ BEGIN {
25 $0 = $0 " " nl 26 $0 = $0 " " nl
26} 27}
27 28
28/^#so/ { # source a file 29### AWK layer
30
31/^%so/ { # source a file
29 pushpar() 32 pushpar()
30 source($2) 33 source($2)
31 next 34 next
32} 35}
33 36
37/^%/ { next } # comments
38
39### Shell layer
40
34/^#/ { # head lines 41/^#/ { # head lines
35 sub(/^#+[ ]*/,"") 42 sub(/^#+[ ]*/,"")
36 head = head (head?"\n":"") $0 43 head = head (head?"\n":"") $0
37 next 44 next
38} 45}
39 46
47### Text layer
48
49end[endn] && $0 == end[endn] {
50 par = par "\n" end[endn--] "\n)"
51 next
52}
53
40/^\.\./ { # block 54/^\.\./ { # block
41 body = body (body?"\n":"") \ 55 if (match($0, /[ ]*<<[ ]*/))
42 "$$(unquote + << .." \ 56 end[++endn] = substr($0, RSTART+RLENGTH)
43 (length>2 ? " | " substr($1,3) " " shquote(2) : "") \ 57 else
44 slurp("..") \ 58 end[++endn] = ".."
45 "..\n)" 59 $0 = substr($0, 3, RSTART?RSTART-3:length)
60 par = par (par?"\n":"") \
61 "$$(" ($1 ? $1 " " shquote(2) : "") " << " end[endn]
62 # par = par (par?"\n":"") \
63 # "$$(unquote + << .." \
64 # (length>2 ? " | " substr($1,3) " " shquote(2) : "") \
65 # slurp("..") \
66 # "..\n)"
46 next 67 next
47} 68}
48 69
70/^\.$/ { next } # continuation line
71
49/^\./ { # line 72/^\./ { # line
50 body = body (body?"\n":"") \ 73 par = par (body?"\n":"") \
51 "$$(" substr($1, 2) " " shquote(2) ")" 74 "$$(" substr($1, 2) " " shquote(2) ")"
52 next 75 next
53} 76}
54 77
55/^$/ { # line break 78/^\\/ { # special line escape
79 $0 = substr($0, 2)
80}
81
82/^$/ { # blank line
56 if (!pushpar()) next 83 if (!pushpar()) next
57} 84}
58 85
@@ -70,25 +97,45 @@ END {
70 printf "shexpand()(eval \"$(echo 'cat<<%s';cat;echo '%s')\")\n", \ 97 printf "shexpand()(eval \"$(echo 'cat<<%s';cat;echo '%s')\")\n", \
71 shxend, shxend 98 shxend, shxend
72 printf "shellfix()(%s)\n", shellfix 99 printf "shellfix()(%s)\n", shellfix
100 print "echo()(printf '%s\\n' \"$@\")"
101 print "handle_input()("\
102 "test -n \"$1\" && printf '%s' \"$*\";"\
103 "if read -r first_line;"\
104 "then echo \"$first_line\";cat;return 0;"\
105 "else echo;return 1;fi)"
73 printf "ST_SOPATH=%s\n", sopath 106 printf "ST_SOPATH=%s\n", sopath
107 if (sofile) source(sofile)
74 print "### head" 108 print "### head"
75 print head 109 print head
76 print "### body" 110 print "### body"
77 print "body(){ unquote : << \\_ | shexpand" 111 print "body(){ unquote : << \\_ | shexpand"
78 pushpar() 112 pushpar()
79 print body | (shellfix " -e 's/^/:/'") 113 shfq = shellfix " -e 's/^/:/'"
80 close(shellfix " -e 's/^/:/'") 114 print body | shfq
115 close(shfq)
81 print "_" 116 print "_"
82 print "}" 117 print "}"
83 if (!dryrun) print "body" 118 if (!dryrun) print "body"
84} 119}
85 120
86function shquote(begin, end, out) { 121function shquote(begin, end, quoted, out) {
87 if (!begin) begin = 1 122 if (!begin) begin = 1
88 if (!end) end = NF 123 if (!end) end = NF
89 for (i=begin; i<=NF; i++) { 124 for (i=begin; i<=NF; i++) {
90 gsub(/"/, "\\\"", $i) 125 if ($i ~ /^\$/) {
91 out = out (out?" ":"") "\"" $i "\"" 126 quoted = 1
127 out = out (out?" ":"") "\"" $i
128 continue
129 }
130 if (($i ~ /\)$/) && quoted) {
131 quoted = 0
132 out = out (out?" ":"") $i "\""
133 continue
134 }
135 if (!quoted) {
136 gsub(/"/, "\\\"", $i)
137 out = out (out?" ":"") "\"" $i "\""
138 } else out = out (out?" ":"") $i
92 } 139 }
93 return out 140 return out
94} 141}
@@ -104,8 +151,9 @@ function slurp(to, out, nl) {
104 151
105function pushpar() { 152function pushpar() {
106 if (!par) return 0 153 if (!par) return 0
107 if (!match(par, /^[ ]*</)) 154 if (!match(par, /^[ \t\n]*[<$]/)) {
108 par = "<p>" par "</p>" 155 par = "$$(p<<../p\n" par "\n../p\n)"
156 }
109 body = body (body?"\n":"") par 157 body = body (body?"\n":"") par
110 par = "" 158 par = ""
111 return 1 159 return 1
@@ -120,6 +168,7 @@ function source(name, found, sp) {
120 found = 1 168 found = 1
121 head = head (head?"\n":"") ln 169 head = head (head?"\n":"") ln
122 } 170 }
171 close(fn)
123 if (found) break 172 if (found) break
124 } 173 }
125 if (!found) { 174 if (!found) {
diff --git a/subtext.sh b/subtext.sh index d845955..a60f0d6 100755 --- a/subtext.sh +++ b/subtext.sh
@@ -1,7 +1,7 @@
1#!/bin/sh 1#!/bin/sh
2 2
3stawk() { 3stawk() {
4 awk -f subtext.awk "$@" # SUBTEXT AWK SCRIPT HERE 4 awk -f subtext.awk "$@"
5} 5}
6 6
7usage() { 7usage() {
@@ -23,14 +23,17 @@ configure() {
23 : "${ST_MACROFILE:=}" 23 : "${ST_MACROFILE:=}"
24 : "${ST_SOPATH:=.:$HOME/.subtext}" 24 : "${ST_SOPATH:=.:$HOME/.subtext}"
25 : "${ST_PIPE_SH:=true}" 25 : "${ST_PIPE_SH:=true}"
26 : "${ST_TRACE=+x}"
26 ## Process options 27 ## Process options
27 while getopts :hm:I:n OPT 28 while getopts :hm:I:no:x OPT
28 do 29 do
29 case "$OPT" in 30 case "$OPT" in
30 (h) usage ;; 31 (h) usage ;;
31 (m) ST_MACROFILE="$OPTARG" ;; 32 (m) ST_MACROFILE="$OPTARG.st.sh" ;;
32 (I) ST_SOPATH="$ST_SOPATH:$OPTARG" ;; 33 (I) ST_SOPATH="$ST_SOPATH:$OPTARG" ;;
33 (n) ST_PIPE_SH=false ;; 34 (n) ST_PIPE_SH=false ;;
35 (o) exec > "$OPTARG" ;;
36 (x) ST_TRACE=-x ;;
34 (:) printf >&2 'Unknown option -%s\n' "$OPTARG"; 37 (:) printf >&2 'Unknown option -%s\n' "$OPTARG";
35 usage 1 ;; 38 usage 1 ;;
36 (*) usage 1 ;; 39 (*) usage 1 ;;
@@ -41,9 +44,9 @@ configure() {
41main() { 44main() {
42 configure "$@" 45 configure "$@"
43 shift $((OPTIND-1)) 46 shift $((OPTIND-1))
44 stawk -vsopath="$ST_SOPATH" "$@" | 47 stawk -vsopath="$ST_SOPATH" -vsofile="$ST_MACROFILE" "$@" |
45 if "$ST_PIPE_SH" 48 if "$ST_PIPE_SH"
46 then sh 49 then sh "$ST_TRACE"
47 else cat 50 else cat
48 fi 51 fi
49} 52}