Update typesetting of text/gemini
authorCase Duckworth <acdw@acdw.net>
Sat, 30 May 2020 21:00:12 +0000 (16:00 -0500)
committerCase Duckworth <acdw@acdw.net>
Sat, 30 May 2020 21:00:12 +0000 (16:00 -0500)
bollux
typeset_gemini.sh [deleted file]

diff --git a/bollux b/bollux
index 87c35fb..6f121b0 100755 (executable)
--- a/bollux
+++ b/bollux
@@ -104,6 +104,7 @@ bollux_config() {
                log debug "Can't load config file '$BOLLUX_CONFIG'."
        fi
 
+       ## behavior
        : "${BOLLUX_DOWNDIR:=.}"                   # where to save downloads
        : "${BOLLUX_LOGLEVEL:=3}"                  # log level
        : "${BOLLUX_MAXREDIR:=5}"                  # max redirects
@@ -112,6 +113,20 @@ bollux_config() {
        : "${BOLLUX_LESSKEY:=/tmp/bollux-lesskey}" # where to store binds
        : "${BOLLUX_PAGESRC:=/tmp/bollux-src}"     # where to save the page source
        : "${BOLLUX_URL:=}"                        # start url
+       ## typesetting
+       : "${T_MARGIN:=4}"      # left and right margin
+       : "${T_WIDTH:=0}"       # width of the viewport -- 0 = get term width
+       # colors -- these will be wrapped in \e[ __ m
+       C_RESET='\e[0m'         # reset
+       : "${C_SIGIL:=35}"      # sigil (=>, #, ##, ###, *, ```)
+       : "${C_LINK_NUMBER:=1}" # link number
+       : "${C_LINK_TITLE:=4}"  # link title
+       : "${C_LINK_URL:=36}"   # link URL
+       : "${C_HEADER1:=1;4}"   # header 1 formatting
+       : "${C_HEADER2:=1}"     # header 2 formatting
+       : "${C_HEADER3:=3}"     # header 3 formatting
+       : "${C_LIST:=0}"        # list formatting
+       : "${C_PRE:=0}"         # preformatted text formatting
 }
 
 prompt() {
@@ -399,74 +414,146 @@ mklesskey() {
 }
 
 normalize_crlf() {
-       while read -r line; do
-               printf '%s\n' "${line//$'\r'?($'\n')/}"
+       while IFS= read -r; do
+               printf '%s\n' "${REPLY//$'\r'?($'\n')/}"
        done
 }
 
 typeset_gemini() {
-       gawk '
-       BEGIN {
-               pre = 0
-               margin = margin ? margin : 4
-               txs = ""        
-               lns = "\033[1m" 
-               lus = "\033[36m"        
-               lts = "\033[4m" 
-               pfs = ""        
-               h1s = "\033[1;4m"       
-               h2s = "\033[1m" 
-               h3s = "\033[3m" 
-               lis = ""        
-               res = "\033[0m" 
-               ms = "\033[35m"
-       }
-       /```/ {
-               pre = ! pre
-               next
-       }
-       pre {
-               mark = "```"
-               fmt = pfs "%s" res
-               text = $0
-       }
-       /^#/ {
-               match($0, /#+/)
-               mark = substr($0, RSTART, RLENGTH)
-               sub(/#+[[:space:]]*/, "", $0)
-               level = length(mark)
-               if (level == 1) {
-                       fmt = h1s "%s" res
-               } else if (level == 2) {
-                       fmt = h2s "%s" res
-               } else {
-                       fmt = h3s "%s" res
-               }
-       }
-       /^=>/ {
-               mark = "=>"
-               sub(/=>[[:space:]]*/, "", $0)
-               desc = $1
-               text = ""
-               for (w = 2; w <= NF; w++) {
-                       text = text (text ? " " : "") $w
-               }
-               fmt = lns "[" (++ln) "]" res " " lts "%s" res "\t" lus "%s" res
-       }
-       /^\*[[:space:]]/ {
-               mark = "*"
-               sub(/\*[[:space:]]*/, "", $0)
-               fmt = lis "%s" res
-       }
-       {
-               mark = mark ? mark : mark
-               fmt = fmt ? fmt : "%s"
-               text = text ? text : $0
-               desc = desc ? desc : ""
-               printf ms "%" (margin-1) "s " res fmt "\n", mark, text, desc
-               mark = fmt = text = desc = ""
-       }
-       '
+       local pre=false
+       local ln=0 # link number
+
+       if ((T_WIDTH == 0)); then
+               shopt -s checkwinsize
+               (
+                       :
+                       :
+               ) # XXX this doesn't work!?
+               log d "LINES=$LINES; COLUMNS=$COLUMNS"
+               T_WIDTH=$COLUMNS
+       fi
+
+       WIDTH=$((T_WIDTH - (T_MARGIN * 2)))
+       ((WIDTH < 0)) && WIDTH=80 # default if dumb
+
+       log d "T_WIDTH=$T_WIDTH"
+       log d "WIDTH=$WIDTH"
+
+       while IFS= read -r; do
+               case "$REPLY" in
+               '```')
+                       if $pre; then
+                               pre=false
+                       else
+                               pre=true
+                       fi
+                       continue
+                       ;;
+               =\>*)
+                       : $((ln += 1))
+                       gemini_link "$REPLY" $pre "$ln"
+                       ;;
+               \#*) gemini_header "$REPLY" $pre ;;
+               \**) gemini_list "$REPLY" $pre ;;
+               *) gemini_text "$REPLY" $pre ;;
+               esac
+       done
+}
+
+gemini_link() {
+       local re="^(=>)[[:blank:]]*([^[:blank:]]+)[[:blank:]]*(.*)"
+       local s t a l # sigil, text, annotation(url), line
+       if ! ${2-false} && [[ "$1" =~ $re ]]; then
+               s="${BASH_REMATCH[1]}"
+               a="${BASH_REMATCH[2]}"
+               t="${BASH_REMATCH[3]}"
+               if [[ -z "$t" ]]; then
+                       t="$a"
+                       a=
+               fi
+
+               printf "\e[${C_SIGIL}m%-${T_MARGIN}s${C_RESET}" "$s"
+               printf -v l "\e[${C_LINK_NUMBER}m[%d]${C_RESET} \
+                       \e[${C_LINK_TITLE}m%s${C_RESET} \
+                       \e[${C_LINK_URL}m%s${C_RESET}\n" \
+                       "$3" "$t" "$a"
+               fold_line "$WIDTH" "$l"
+       else
+               gemini_pre "$1"
+       fi
+}
+
+gemini_header() {
+       local re="^(#+)[[:blank:]]*(.*)"
+       local s t a l # sigil, text, annotation(lvl), line
+       if ! ${2-false} && [[ "$1" =~ $re ]]; then
+               s="${BASH_REMATCH[1]}"
+               a="${#BASH_REMATCH[1]}"
+               t="${BASH_REMATCH[2]}"
+               local hdrfmt
+               hdrfmt="$(eval echo "\$C_HEADER$a")"
+
+               printf "\e[${C_SIGIL}m%$((T_MARGIN - 1))s ${C_RESET}" "$s"
+               printf -v l "\e[${hdrfmt}m%s${C_RESET}\n" "$t"
+               fold_line "$WIDTH" "$l"
+       else
+               gemini_pre "$1"
+       fi
+}
+
+gemini_list() {
+       local re="^(\*)[[:blank:]]*(.*)"
+       local s t a l # sigil, text, annotation(n/a), line
+       if ! ${2-false} && [[ "$1" =~ $re ]]; then
+               s="${BASH_REMATCH[1]}"
+               t="${BASH_REMATCH[2]}"
+
+               printf "\e[${C_SIGIL}m%-${T_MARGIN}s" "$s"
+               printf -v l "\e[${C_LIST}m%s${C_RESET}\n" "$t"
+               fold_line "$WIDTH" "$l"
+       else
+               gemini_pre "$1"
+       fi
+}
+
+gemini_text() {
+       if ! ${2-false}; then
+               printf "%${T_MARGIN}s" ' '
+               fold_line "$WIDTH" "$1"
+       else
+               gemini_pre "$1"
+       fi
+}
+
+gemini_pre() {
+       printf "\e[${C_SIGIL}m%-${T_MARGIN}s" '```'
+       printf "\e[${C_PRE}m%s${C_RESET}\n" "$1"
+}
+
+fold_line() { # fold_line WIDTH TEXT
+       local width="$1"
+       local margin="${2%%[![:space:]]*}"
+       if [[ "$margin" ]]; then
+               margin="${#margin}"
+       else
+               margin="$T_MARGIN"
+       fi
+       local ll=0 wl plain
+       # shellcheck disable=2086
+       set -- $2 # TODO: is this the best way?
+
+       for word; do
+               plain="${word//$'\x1b'\[*([0-9;])m/}"
+               wl=$((${#plain} + 1))
+               if (((ll + wl) >= width)); then
+                       printf "\n%${margin}s" ' '
+                       ll=$wl
+               else
+                       ll=$((ll + wl))
+               fi
+               printf '%s ' "$word"
+       done
+       printf '\n'
 }
 
 handle_keypress() {
@@ -500,7 +587,7 @@ select_url() {
 }
 
 extract_links() {
-       gawk -F$'\t' '
+       gawk '
        /^=>/ {
                sub(/=>[[:space:]]*/,"")
                if ($2) 
diff --git a/typeset_gemini.sh b/typeset_gemini.sh
deleted file mode 100644 (file)
index 2f9abbc..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-typeset_gemini() {
-       local pre=false
-       local ln=0
-
-       while read -r line; do
-               case "$line" in
-               '```')
-                       flip pre
-                       continue
-                       ;;
-               =\>*)
-                       : $((ln += 1))
-                       gemini_link "$line" $pre
-                       ;;
-               \#*) gemini_header "$line" $pre ;;
-               \**) gemini_list "$line" $pre ;;
-               *) gemini_text "$line" $pre ;;
-               esac
-       done
-}
-
-gemini_link() {
-       local re="^(=>)[[:blank:]]*([^[:blank:]]+)[[:blank:]]*(.*)"
-       local s t a # sigil, text, annotation(url)
-       if ! ${2-false} && [[ "$1" =~ $re ]]; then
-               s="${BASH_REMATCH[1]}"
-               t="${BASH_REMATCH[3]}"
-               a="${BASH_REMATCH[2]}"
-
-               printf "$C_SIGIL%-${MARGIN}s" "$s"
-               fold_line "$WIDTH" "$(printf "$C_LINK_TITLE%s $C_LINK_URL%s$C_RESET\n" \
-                       "$t" "$a")"
-       else
-               gemini_pre "$1"
-       fi
-}
-
-gemini_header() {
-       local re="^(#+)[[:blank:]]*(.*)"
-       local s t a # sigil, text, annotation(lvl)
-       if ! ${2-false} && [[ "$1" =~ $re ]]; then
-               s="${BASH_REMATCH[1]}"
-               a="${#BASH_REMATCH[1]}"
-               t="${BASH_REMATCH[2]}"
-
-               local hdrfmt
-               hdrfmt="$(eval echo "\$C_HEADER$a")"
-               printf "$C_SIGIL%-${MARGIN}s$hdrfmt%s$C_RESET\n" \
-                       "$s" "$(fold_line "$WIDTH" "$t")"
-       else
-               gemini_pre "$1"
-       fi
-}
-
-gemini_list() {
-       local re="^(\*)[[:blank:]]*(.*)"
-       local s t a # sigil, text, annotation(n/a)
-       if ! ${2-false} && [[ "$1" =~ $re ]]; then
-               s="${BASH_REMATCH[1]}"
-               t="${BASH_REMATCH[2]}"
-
-               printf "$C_SIGIL%-${MARGIN}s$C_LIST%s$C_RESET\n" \
-                       "$s" "$(fold_line "$WIDTH" "$t")"
-       else
-               gemini_pre "$1"
-       fi
-}
-
-gemini_text() {
-       printf "%${MARGIN}s" ' '
-       if ! ${2-false}; then
-               fold_line "$WIDTH" "$1"
-       else
-               gemini_pre "$1"
-       fi
-}
-
-gemini_pre() {
-       printf "%${MARGIN}s%s" ' ' "$1"
-}
-
-flip() { # flip NAME
-       [[ "${!1}" == true || "${!1}" == false ]] || return 1
-
-       if "${!1}"; then
-               eval "$1=false"
-       else
-               eval "$1=true"
-       fi
-}
-
-fold_line() { # fold_line WIDTH TEXT
-       local width="$1"
-       local ll=0 wl plain
-       # shellcheck disable=2086
-       # TODO: determine if this is the best way to do it
-       set -- $2
-
-       for word; do
-               plain="${word//$'\x1b'\[*([0-9;])m/}"
-               wl=$((${#plain} + 1))
-               if (((ll + wl) >= width)); then
-                       printf "\n%${MARGIN}s" ' '
-                       ll=$wl
-               else
-                       ll=$((ll + wl))
-               fi
-               printf '%s ' "$word"
-       done
-       printf '\n'
-}
-
-# just here for reference
-strip() { # strip control sequences
-       # https://stackoverflow.com/a/55872518
-       shopt -s extglob
-       while IFS='' read -r x; do
-               # remove colors
-               echo "${x//$'\x1b'\[*([0-9;])m/}"
-       done
-}
-
-test() {
-       MARGIN=4
-       WIDTH=60
-       #shopt -s checkwinsize; (:;:)
-       #WIDTH="$((COLUMNS - (MARGIN*2)))"
-       C_LINK_TITLE=$'\e[34m'
-       C_LINK_URL=$'\e[31m'
-       C_RESET=$'\e[0m'
-       typeset_gemini <<-'EOF'
-               # Project Gemini
-               
-               ## Overview
-               
-               Gemini is a new internet protocol which:
-               
-               * Is heavier than gopher
-               * Is lighter than the web
-               * Will not replace either
-               * Strives for maximum power to weight ratio
-               * Takes user privacy very seriously
-               
-               ## Resources
-               
-               => docs/        Gemini documentation
-               => software/    Gemini software
-               => servers/     Known Gemini servers
-               => https://lists.orbitalfox.eu/listinfo/gemini  Gemini mailing list
-               => gemini://gemini.conman.org/test/torture/     Gemini client torture test
-               
-               ## Web proxies
-               
-               => https://portal.mozz.us/?url=gemini%3A%2F%2Fgemini.circumlunar.space%2F&fmt=fixed     Gemini-to-web proxy service
-               => https://proxy.vulpes.one/gemini/gemini.circumlunar.space     Another Gemini-to-web proxy service
-               
-               ## Search engines
-               
-               => gemini://gus.guru/   Gemini Universal Search engine
-               => gemini://houston.coder.town  Houston search engine
-               
-               ## Geminispace aggregators (experimental!)
-               
-               => capcom/      CAPCOM
-               => gemini://rawtext.club:1965/~sloum/spacewalk.gmi      Spacewalk
-               
-               ## Free Gemini hosting
-               
-               => users/       Users with Gemini content on this server
-       EOF
-}
-test