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
: "${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() {
}
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() {
}
extract_links() {
- gawk -F$'\t' '
+ gawk '
/^=>/ {
sub(/=>[[:space:]]*/,"")
if ($2)
+++ /dev/null
-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