about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xjimmy290
-rw-r--r--test.gmi37
2 files changed, 0 insertions, 327 deletions
diff --git a/jimmy b/jimmy deleted file mode 100755 index 3e4485e..0000000 --- a/jimmy +++ /dev/null
@@ -1,290 +0,0 @@
1#!/bin/sh
2
3### Initialize
4# init buffers
5buff="$(mktemp)"
6lbuf="$(mktemp)"
7meta="$(mktemp)"
8cleanup() { rm "$buff" "$lbuff" "$meta" 2>/dev/null; }
9trap cleanup EXIT INT KILL
10
11# init state
12prev= # previous linetype
13curr= # current linetype
14tmpl= # template (optional)
15verbatimp=false # in verbatim block?
16metap=true # in metadata block?
17IPATH="$PWD" # inclusion path
18# (tuneables)
19: "${nl:=::NL::}" # newline
20: "${sp:=::SP::}" # space
21: "${te:=::END::}" # template end
22: "${to:=html}" # output format
23
24### Formats
25## HTML and GMI are given here. Other formats can be defined in their
26## own files and they'll be sourced.
27
28## NOTES
29# should we allow modifying variables from the environment ?
30
31html() {
32 : "${fmtbuff_hd_1:=<h1>%s</h1>$nl}"
33 : "${fmtline_hd_1:=%s}"
34 : "${fmtbuff_hd_2:=<h2>%s</h2>$nl}"
35 : "${fmtline_hd_2:=%s}"
36 : "${fmtbuff_hd_3:=<h3>%s</h3>$nl}"
37 : "${fmtline_hd_3:=%s}"
38 : "${fmtbuff_quot:=<blockquote>$nl%s</blockquote>$nl}"
39 : "${fmtline_quot:=%s$nl}"
40 : "${fmtbuff_list:=<ul>$nl%s</ul>$nl}"
41 : "${fmtline_list:=<li>%s</li>$nl}"
42 : "${fmtbuff_para:=<p>%s</p>$nl}"
43 : "${fmtline_para:=%s$nl}"
44 : "${fmtline_plnk:=<a href=\"%s\">%s</a>$nl}"
45 : "${fmtbuff_link:=<ul class=\"links\">$nl%s</ul>$nl}"
46 : "${fmtline_link:=<li><a href=\"%s\">%s</li>$nl}"
47 : "${fmtbuff_verb:=<pre><code>%s</code></pre>$nl}"
48 : "${fmtline_verb:=%s$nl}"
49 : "${fmtbuff_blank:=$nl}"
50 : "${fmtline_blank:=$nl}"
51}
52
53gmi() {
54 : "${fmtbuff_hd_1:=# %s$nl}"
55 : "${fmtline_hd_1:=%s}"
56 : "${fmtbuff_hd_2:=## %s$nl}"
57 : "${fmtline_hd_2:=%s}"
58 : "${fmtbuff_hd_3:=### %s$nl}"
59 : "${fmtline_hd_3:=%s}"
60 : "${fmtbuff_quot:=> %s$nl}"
61 : "${fmtline_quot:=%s$sp}"
62 : "${fmtbuff_list:=%s$nl}"
63 : "${fmtline_list:=* %s$nl}"
64 : "${fmtbuff_para:=%s$nl}"
65 : "${fmtline_para:=%s$sp}"
66 : "${fmtline_plnk:=$nl=> %s %s$nl}"
67 : "${fmtbuff_link:=%s}"
68 : "${fmtline_link:==> %s %s$nl}"
69 : "${fmtbuff_verb:=\`\`\`$nl%s\`\`\`$nl}"
70 : "${fmtline_verb:=%s$nl}"
71 : "${fmtbuff_blank:=$nl}"
72 : "${fmtline_blank:=$nl}"
73}
74
75### Filters
76
77filter_buff() {
78 f="filter_buff_$to"
79 if type "$f" 2>/dev/null | grep -q function
80 then "$f"
81 else cat
82 fi
83}
84
85filter_line() {
86 f="filter_line_$to"
87 if type "$f" 2>/dev/null | grep -q function
88 then printf '%s\n' "$*" | "$f"
89 else printf '%s\n' "$*"
90 fi
91}
92
93filter_line_html() {
94 # s/// : escape <, >, & from html
95 # s### : *bold*, _italic_, `code`
96 # s@@@ : smart versions of things
97 sed \
98 -e 's/&/\&amp;/g' \
99 -e 's/</\&lt;/g' \
100 -e 's/>/\&gt;/g' \
101 -e 's#\*\([^*]*\)\*#<b>\1</b>#g' \
102 -e 's#_\([^_]*\)_#<i>\1</i>#g' \
103 -e 's#`\([^`]*\)`#<code>\1</code>#' \
104 -e 's@---@\&mdash;@g' \
105 -e 's@--@\&ndash;@g'
106
107}
108
109### Processing
110
111## Utility functions
112
113pushline() {
114 tag="$1"; shift
115 printf "$(eval echo "\$fmtline_$tag")" "$@" >> "$buff"
116}
117
118bufprint() {
119 b="$(filter_buff<"$buff")"
120 printf "$(eval echo "\$fmtbuff_$1")" "$b" |
121 sed -e "s/$nl/\n/g" -e "s/$sp/ /g" # fix whitespace
122 : > "$buff"
123}
124
125### Where the magic happens
126process() {
127 set -f
128 while read -r sigil line
129 do
130 if $verbatimp && test "$sigil" != '```'
131 then
132 pushline verb "$(filter_line "$sigil $line")"
133 continue
134 fi
135
136 case "$sigil" in
137 (*':') # metadata
138 if $metap
139 then printf 'export %s="%s"\n' \
140 "${sigil%:}" "$line" >>"$meta"
141 fi
142 ;;
143 ('```') # verbatim
144 # CONSIDER: "types" of verbatim
145 # designated by extra fields after the
146 # sigil
147 ## ``` class_of_content
148 # ^--- change the class of the content,
149 # eg. in html do <pre class="type">
150 # other formats might do other things
151 ## ``` | some_program
152 # ^--- pipe the buffer to some_program
153 metap=false
154 if $verbatimp
155 then
156 bufprint verb
157 verbatimp=false
158 prev=
159 else
160 bufprint "$prev"
161 verbatimp=true
162 fi
163 continue
164 ;;
165 ('=>') # link
166 metap=false
167
168 printf '%s\n' "$line" > "$lbuf"
169 read -r url title < "$lbuf"
170 if test "$curr" = para
171 then
172 pushline plnk "$url" "$title"
173 continue
174 else curr=link
175 fi
176 ;;
177 ('#'*) # header
178 metap=false
179 curr=hd_${#sigil} ;;
180 ('>') # quote
181 metap=false
182 curr=quot ;;
183 ('*') # list
184 metap=false
185 curr=list ;;
186 ('') # blank line
187 metap=false
188 curr=blank ;;
189 (*) # paragraph
190 metap=false
191 curr=para
192 line="$sigil $line"
193 ;;
194 esac
195
196 test "$curr" = "$prev" || bufprint "$prev"
197 prev="$curr"
198
199 if test "$curr" = verb
200 then
201 pushline "$curr" "$line"
202 continue
203 fi
204
205 if test "$curr" = link
206 then pushline "$curr" "$url" "$(filter_line "$title")"
207 else pushline "$curr" "$(filter_line "$line")"
208 fi
209 done
210
211 bufprint "$curr"
212}
213
214templatize() {
215 eval "cat<<$te
216$(cat $@)
217$te"
218}
219
220### Entry point
221
222usage() {
223 cat <<EOF >&2
224jimmy: convert gmi to other formats
225usage: jimmy [-h] [-t FORMAT] [-I DIRECTORY] [-T FILE] [FILE...]
226If no FILE is given on the command line, jimmy reads standard input.
227options:
228 -h show this help and exit
229 -x enable xtrace (set -x)
230 -t FORMAT
231 convert gmi to FORMAT. html is default, gmi is built-in.
232 you can also pass the name of a file that will be sourced.
233 -I DIRECTORY
234 add DIRECTORY to the include path for -t. the current
235 directory is always in the include path.
236 -T FILE
237 use FILE as a template for the output text.
238EOF
239 exit $1
240}
241
242main() {
243 while getopts hxI:t:T: OPT
244 do
245 case "$OPT" in
246 (h) usage 0 ;;
247 (x) set -x ;;
248 (I) IPATH="$OPTARG:$IPATH" ;;
249 (t) to="$OPTARG" ;;
250 (T) tmpl="$OPTARG" ;;
251 (*) usage 1 ;;
252 esac
253 done
254 shift $((OPTIND - 1))
255
256 case "$to" in
257 (html|gmi) "$to" ;;
258 (*)
259 found=false
260 for p in $(echo "$IPATH"|tr : ' ')
261 do
262 if test -f "$p/$to"
263 then . "$p/$to"; found=true
264 elif test -f "$p/$to.sh"
265 then . "$p/$to.sh"; found=true
266 fi
267 done
268 if ! $found
269 then
270 echo >&2 "Can't find file: '$to'"
271 echo >&2 "Looked in $IPATH"
272 exit 2
273 fi
274 ;;
275 esac
276
277 # while read requires a final newline
278 (cat "${@:--}"; echo) |
279 process |
280 if test -n "$tmpl"
281 then
282 # use eval cat instead of source for pipe sequencing
283 # reasons
284 eval "$(cat "$meta")"
285 templatize "$tmpl"
286 else cat
287 fi
288}
289
290main "$@"
diff --git a/test.gmi b/test.gmi deleted file mode 100644 index 62bed2e..0000000 --- a/test.gmi +++ /dev/null
@@ -1,37 +0,0 @@
1title: a test document
2date: 2024-05-13T03:02:45Z
3uuid: b3daebf1-440b-4828-a4d9-9089c7bd7c61
4
5# a test document of some kind
6
7here is a test document.
8it has paragraphs
9=> example.com with links!
10and other things.
11
12## a code example
13```
14for (a=1;a<=4;a++) {
15 printf("%d\n", a);
16}
17```
18
19### other examples
20
21> a blockquote is a quote
22> that is blocky.
23
24* list 1
25* list 2
26* list 3
27=> example.com link list 1
28=> example.com link list 2
29=> example.com link list 3
30
31ok, now for another test:
32will *strong* in-line text be converted?
33as well as `code`, _emph_ and such?
34what if *i _nest_ them*
35what if *i _nest them* wrong_ ?
36what about *breaking them
37over two lines?*