From 75f5c10088f77adece45bf0d1cc6868d4fff95d2 Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Mon, 13 May 2024 22:40:58 -0500 Subject: Add readme stub --- README.gmi | 4 ++ jimmy | 240 ++++++++++++++++++++++++++++++++++++++----------------------- test.gmi | 6 +- 3 files changed, 160 insertions(+), 90 deletions(-) create mode 100644 README.gmi diff --git a/README.gmi b/README.gmi new file mode 100644 index 0000000..3abdd2a --- /dev/null +++ b/README.gmi @@ -0,0 +1,4 @@ +# jimmy --- convert .gmi to .html and other formats + +[to be documented] + diff --git a/jimmy b/jimmy index ed6c2b7..f5dfa0f 100755 --- a/jimmy +++ b/jimmy @@ -4,16 +4,22 @@ # init buffers buff="$(mktemp)" lbuf="$(mktemp)" -trap 'rm "$buff" "$lbuf"' EXIT INT KILL +meta="$(mktemp)" +cleanup() { rm "$buff" "$lbuff" "$meta" 2>/dev/null; } +trap cleanup EXIT INT KILL # init state -prev= -curr= -verbatim=false +prev= # previous linetype +curr= # current linetype +tmpl= # template (optional) +verbatimp=false # in verbatim block? +metap=true # in metadata block? +IPATH="$PWD" # inclusion path # (tuneables) -nl='::NL::' -sp='::SP::' -to=html +: "${nl:=::NL::}" # newline +: "${sp:=::SP::}" # space +: "${te:=::END::}" # template end +: "${to:=html}" # output format ### Formats ## HTML and GMI are given here. Other formats can be defined in their @@ -23,64 +29,62 @@ to=html # should we allow modifying variables from the environment ? html() { - fmtbuff_hd_1="
$nl%s$nl" - fmtline_quot="%s$nl" - fmtbuff_list="
%s
$nl" - fmtline_para="%s$nl" - fmtline_plnk="%s$nl" - fmtbuff_link="%s
$nl"
- fmtline_verb="%s$nl"
- fmtbuff_blank="$nl"
- fmtline_blank="$nl"
+ : "${fmtbuff_hd_1:=$nl%s$nl}" + : "${fmtline_quot:=%s$nl}" + : "${fmtbuff_list:=
%s
$nl}" + : "${fmtline_para:=%s$nl}" + : "${fmtline_plnk:=%s$nl}" + : "${fmtbuff_link:=%s
$nl}"
+ : "${fmtline_verb:=%s$nl}"
+ : "${fmtbuff_blank:=$nl}"
+ : "${fmtline_blank:=$nl}"
}
gmi() {
- fmtbuff_hd_1="# %s$nl"
- fmtline_hd_1="%s"
- fmtbuff_hd_2="## %s$nl"
- fmtline_hd_2="%s"
- fmtbuff_hd_3="### %s$nl"
- fmtline_hd_3="%s"
- fmtbuff_quot="> %s$nl"
- fmtline_quot="%s$sp"
- fmtbuff_list="%s$nl"
- fmtline_list="* %s$nl"
- fmtbuff_para="%s$nl"
- fmtline_para="%s$sp"
- fmtline_plnk="$nl=> %s %s$nl"
- fmtbuff_link="%s$nl"
- fmtline_link="=> %s %s"
- fmtbuff_verb="\`\`\`$nl%s\`\`\`$nl"
- fmtline_verb="%s$nl"
- fmtbuff_blank="$nl"
- fmtline_blank="$nl"
+ : "${fmtbuff_hd_1:=# %s$nl}"
+ : "${fmtline_hd_1:=%s}"
+ : "${fmtbuff_hd_2:=## %s$nl}"
+ : "${fmtline_hd_2:=%s}"
+ : "${fmtbuff_hd_3:=### %s$nl}"
+ : "${fmtline_hd_3:=%s}"
+ : "${fmtbuff_quot:=> %s$nl}"
+ : "${fmtline_quot:=%s$sp}"
+ : "${fmtbuff_list:=%s$nl}"
+ : "${fmtline_list:=* %s$nl}"
+ : "${fmtbuff_para:=%s$nl}"
+ : "${fmtline_para:=%s$sp}"
+ : "${fmtline_plnk:=$nl=> %s %s$nl}"
+ : "${fmtbuff_link:=%s$nl}"
+ : "${fmtline_link:==> %s %s}"
+ : "${fmtbuff_verb:=\`\`\`$nl%s\`\`\`$nl}"
+ : "${fmtline_verb:=%s$nl}"
+ : "${fmtbuff_blank:=$nl}"
+ : "${fmtline_blank:=$nl}"
}
### Filters
-filter_buff_html(){ cat; }
-
filter_buff() {
f="filter_buff_$to"
- if type "$f" | grep -q function
+ if type "$f" 2>/dev/null | grep -q function
then "$f"
else cat
- fi | sed -e "s/$nl/\n/g" -e "s/$sp/ /g" # fix whitespace
+ fi
}
filter_line() {
f="filter_line_$to"
- if type "$f" | grep -q function
+ if type "$f" 2>/dev/null | grep -q function
then printf '%s\n' "$*" | "$f"
else printf '%s\n' "$*"
fi
@@ -89,12 +93,16 @@ filter_line() {
filter_line_html() {
# s/// : escape <, >, & from html
# s### : *bold*, _italic_, `code`
- sed -e 's/&/\&/g' \
- -e 's/\</g' \
- -e 's/>/\>/g' \
- -e 's#\*\([^*]*\)\*#\1#g' \
- -e 's#_\([^_]*\)_#\1#g' \
- -e 's#`\([^`]*\)`#\1
#'
+ # s@@@ : smart versions of things
+ sed \
+ -e 's/&/\&/g' \
+ -e 's/\</g' \
+ -e 's/>/\>/g' \
+ -e 's#\*\([^*]*\)\*#\1#g' \
+ -e 's#_\([^_]*\)_#\1#g' \
+ -e 's#`\([^`]*\)`#\1
#' \
+ -e 's@---@\—@g' \
+ -e 's@--@\–@g'
}
@@ -108,46 +116,55 @@ pushline() {
}
bufprint() {
- b="$(cat<"$buff")"
- printf "$(eval echo "\$fmtbuff_$1")" "$b" | filter_buff
+ b="$(filter_buff<"$buff")"
+ printf "$(eval echo "\$fmtbuff_$1")" "$b" |
+ sed -e "s/$nl/\n/g" -e "s/$sp/ /g" # fix whitespace
: > "$buff"
}
-## Where the magic happens
+### Where the magic happens
process() {
set -f
while read -r sigil line
do
- if $verbatim && test "$sigil" != '```'
+ if $verbatimp && test "$sigil" != '```'
then
pushline verb "$(filter_line "$sigil $line")"
continue
fi
case "$sigil" in
- ('```')
- if $verbatim
+ (*':') # metadata
+ if $metap
+ then printf 'export %s="%s"\n' \
+ "${sigil%:}" "$line" >>"$meta"
+ fi
+ ;;
+ ('```') # verbatim
+ # CONSIDER: "types" of verbatim
+ # designated by extra fields after the
+ # sigil
+ ## ``` class_of_content
+ # ^--- change the class of the content,
+ # eg. in html do + # other formats might do other things + ## ``` | some_program + # ^--- pipe the buffer to some_program + metap=false + if $verbatimp then bufprint verb - verbatim=false + verbatimp=false prev= else - # CONSIDER: "types" of verbatim - # designated by extra fields after the - # sigil - ## ``` class_of_content - # ^- change the class of the content, - # eg. in html do- # other formats might do other things - ## ``` | some_program - # ^- pipe the buffer to some_program - ## others? bufprint "$prev" - verbatim=true + verbatimp=true fi continue ;; - ('=>') + ('=>') # link + metap=false + printf '%s\n' "$line" > "$lbuf" read -r url title < "$lbuf" if test "$curr" = para @@ -157,11 +174,20 @@ process() { else curr=link fi ;; - ('#'*) curr=hd_${#sigil} ;; - ('>') curr=quot ;; - ('*') curr=list ;; - ('') curr=blank ;; - (*) + ('#'*) # header + metap=false + curr=hd_${#sigil} ;; + ('>') # quote + metap=false + curr=quot ;; + ('*') # list + metap=false + curr=list ;; + ('') # blank line + metap=false + curr=blank ;; + (*) # paragraph + metap=false curr=para line="$sigil $line" ;; @@ -185,28 +211,43 @@ process() { bufprint "$curr" } +templatize() { + eval "cat<<$te +$(cat $@) +$te" +} + ### Entry point usage() { cat <&2 jimmy: convert gmi to other formats -usage: jimmy [-h] [-t FORMAT] [FILE...] +usage: jimmy [-h] [-t FORMAT] [-I DIRECTORY] [-T FILE] [FILE...] If no FILE is given on the command line, jimmy reads standard input. options: -h show this help and exit + -x enable xtrace (set -x) -t FORMAT convert gmi to FORMAT. html is default, gmi is built-in. you can also pass the name of a file that will be sourced. + -I DIRECTORY + add DIRECTORY to the include path for -t. the current + directory is always in the include path. + -T FILE + use FILE as a template for the output text. EOF + exit $1 } main() { - while getopts ht:x OPT + while getopts hxI:t:T: OPT do case "$OPT" in (h) usage 0 ;; - (t) to="$OPTARG" ;; (x) set -x ;; + (I) IPATH="$OPTARG:$IPATH" ;; + (t) to="$OPTARG" ;; + (T) tmpl="$OPTARG" ;; (*) usage 1 ;; esac done @@ -214,15 +255,36 @@ main() { case "$to" in (html|gmi) "$to" ;; - (*) . "$to" || { - echo >&2 "Can't find file: '$to'" - exit 2 - } - ;; + (*) + found=false + for p in $(echo "$IPATH"|tr : ' ') + do + if test -f "$p/$to" + then . "$p/$to"; found=true + elif test -f "$p/$to.sh" + then . "$p/$to.sh"; found=true + fi + done + if ! $found + then + echo >&2 "Can't find file: '$to'" + echo >&2 "Looked in $IPATH" + exit 2 + fi + ;; esac # while read requires a final newline - (cat "${@:--}"; echo) | process + (cat "${@:--}"; echo) | + process | + if test -n "$tmpl" + then + # use eval cat instead of source for pipe sequencing + # reasons + eval "$(cat "$meta")" + templatize "$tmpl" + else cat + fi } main "$@" diff --git a/test.gmi b/test.gmi index f2dc0dc..62bed2e 100644 --- a/test.gmi +++ b/test.gmi @@ -1,3 +1,7 @@ +title: a test document +date: 2024-05-13T03:02:45Z +uuid: b3daebf1-440b-4828-a4d9-9089c7bd7c61 + # a test document of some kind here is a test document. @@ -30,4 +34,4 @@ as well as `code`, _emph_ and such? what if *i _nest_ them* what if *i _nest them* wrong_ ? what about *breaking them -over two lines?* \ No newline at end of file +over two lines?* -- cgit 1.4.1-21-gabe81